[PR #843] [MERGED] fix(javascript): keep exact empty values in graph identities #2282

Closed
opened 2026-10-16 21:16:42 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/843
Author: @kaoru0822-kitauji
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/exact-empty-graph-identities


📝 Commits (7)

  • 63012ee fix(javascript): keep exact empty values in graph identities
  • 527b76e fix(javascript): leave empty application values unlabeled
  • e20da1f fix(javascript): match exact empty literal channels and seeds
  • 6cc45e8 Merge remote-tracking branch 'origin/main' into fix/exact-empty-graph-identities
  • 35e5508 fix(javascript): advertise the exact empty seed rule and match empty API keys
  • b6d9acc Merge remote-tracking branch 'origin/main' into fix/exact-empty-graph-identities
  • bddeb63 fix(errors): report union input issues at the union's path

📊 Changes

14 files changed (+277 additions, -71 deletions)

View changed files

📝 docs/product-catalog.json (+2 -2)
📝 docs/verification/managed-conformance-manifest.json (+2 -2)
📝 skills/reverse-engineer-anything/SKILL.md (+1 -1)
📝 src/application/JavaScriptApplicationEmptyLiterals.test.ts (+150 -4)
📝 src/application/JavaScriptArtifactGraphAccumulator.ts (+5 -30)
📝 src/application/JavaScriptSemanticGraphBuilder.test.ts (+15 -5)
📝 src/application/JavaScriptSemanticGraphBuilder.ts (+2 -0)
📝 src/domain/inputIssueProjection.test.ts (+23 -0)
📝 src/domain/inputIssueProjection.ts (+16 -2)
📝 src/domain/javascriptApplicationEvidenceSchemas.ts (+4 -2)
📝 src/domain/javascriptApplicationVersionKeys.ts (+15 -4)
📝 src/domain/javascriptFeatureSeed.ts (+6 -3)
📝 src/domain/javascriptFeatureTraceSchemas.ts (+35 -15)
📝 src/generatedMcpToolCatalog.ts (+1 -1)

📄 Description

Summary

Follow-up to #839 and #836, addressing the Codex review findings on both (#839 P1/P2, #836 P2). #839's description listed these as its trade-off.

#839 kept schemas unchanged by displaying the empty string as "" everywhere, including inside node identities. That substitution isn't injective:

Input On main after #839
fetch(''); fetch('""') both endpoints get identity.key: "\"\"" → one merged node
source map sources: ["", "\"\""] both get original_source: "\"\"" → one merged node
{ ['']() {}, ['""']() {} } both function nodes have only label: "\"\""; no exact name in the graph

original_source also feeds version keys (javascriptApplicationVersionKeys.ts) and source-to-bundle path signals (sourceToBundleSignals.ts). On main, those see the two-character display text as if it were the reported path.

Fix

  • Identity is exact. artifact-local-key.key and source-map-original.original_source now accept the empty string (z.string() instead of min(1)). The accumulator no longer rewrites identities, so node IDs are derived from the exact reported value.
  • No synthetic application labels. An empty value gets label: null (no display label) on application-graph observations, so trace_application_feature literal seeds, which match labels, cannot conflate fetch('') with fetch('""'). Semantic-graph labels keep the "" display convention from #764, because feature seeds don't read them.
  • Version comparison pairs exact empty values. Semantic version keys read the exact ipc-channel channel, the context-bridge-api api_key when no label exists, and the endpoint value. The same empty IPC channel in two versions still pairs, and it stays distinct from a two-quote channel.
  • Exact empty seeds are accepted. trace_application_feature seed is a JSON-Schema-representable union. One branch is any kind with a nonempty value. The other is a non-node-id kind with value: "" and an explicit match: "exact". The advertised schema and runtime validation therefore agree (contains "" would select every node). Empty context-bridge API seeds match the exact properties.api_key.
  • Union input diagnostics keep their path. Zod reports union branch issues relative to the union, so projectInputIssues now prefixes the union's path and deduplicates identical branch issues. A missing seed reports ["seed"] missing_argument once instead of root-level invalid_type entries.
  • Function nodes carry the exact name. properties.name is added to every semantic function node, matching how property slots already carry name.

Downstream consumers handle the exact empty value correctly:

  • sourceToBundleSignals normalizeCurrentPath("") returns null, so an empty source is not treated as a path.
  • Version keys become source-map\0, which stays distinct.
  • Feature-seed candidates never match an empty query.

Contract / behavior changes

  • Input schema relaxed: trace_application_feature seed also admits { kind: <non-node-id>, value: "", match: "exact" }. Every previously valid seed is still valid.
  • Output schema relaxed: identity.key (artifact-local-key) and identity.original_source (source-map-original) may now be "". This is backward compatible for consumers because it only admits more values. npm run docs:generate updated the catalog, skill, and conformance-manifest digests.
  • Graphs containing empty literals or empty source names now have distinct, exact identities. Output for inputs without them is unchanged, except that semantic function nodes now include properties.name.

Verification

  • Updated and new regressions in JavaScriptApplicationEmptyLiterals.test.ts and JavaScriptSemanticGraphBuilder.test.ts: fetch('') vs fetch('""') give distinct endpoints with exact keys, sources: ["", "\"\""] gives distinct source modules, and ['']() vs ['""']() give distinct properties.name. There is also a feature-seed regression: a "" exact seed matches only the two-quote endpoint. New regressions validate exact empty seeds against both Zod and the advertised JSON Schema (via Ajv 2020), plus an empty context-bridge API seed and union issue paths and cross-version pairing of an empty IPC channel. The pairing regression fails without the version-key change. 6 fail on current main and pass here.
  • npm run check:changed after merging main: 62 files / 615 tests passed.
  • 18 JavaScript-graph boundary/acceptance suites (every test referencing the application or semantic graph): 119 tests passed (with the new regressions).
  • Contract and MCP catalog/schema suites: 12 files / 45 tests passed. After this round, toolSchemaValidity, product catalog, and the application workflow/MCP acceptance suites also passed (4 files / 28 tests); with applicationWorkflowCli and retainedApplicationEvidenceMcp added in the latest round, 6 files / 40 tests passed.
  • npm run docs:check and npm run check:fast passed.

No Hopper/Ghidra/IDA verification needed (static JavaScript analysis only).

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/843 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/exact-empty-graph-identities` --- ### 📝 Commits (7) - [`63012ee`](https://github.com/morluto/rea/commit/63012eeb601fc74ca82f3a027d852a5da1b099d2) fix(javascript): keep exact empty values in graph identities - [`527b76e`](https://github.com/morluto/rea/commit/527b76ef78e84d29bb41bd45f1f83fae05ca66ca) fix(javascript): leave empty application values unlabeled - [`e20da1f`](https://github.com/morluto/rea/commit/e20da1f205b105b1b6a5decd3c2d0fe36fd12410) fix(javascript): match exact empty literal channels and seeds - [`6cc45e8`](https://github.com/morluto/rea/commit/6cc45e8dc90ab80045574f725c22675566b69b5c) Merge remote-tracking branch 'origin/main' into fix/exact-empty-graph-identities - [`35e5508`](https://github.com/morluto/rea/commit/35e5508fd095a062d7477bd6bb7d2d8e28201cd8) fix(javascript): advertise the exact empty seed rule and match empty API keys - [`b6d9acc`](https://github.com/morluto/rea/commit/b6d9acca6391114f95b7dbfc2619301cbf23b55c) Merge remote-tracking branch 'origin/main' into fix/exact-empty-graph-identities - [`bddeb63`](https://github.com/morluto/rea/commit/bddeb634b583cf4f7d5fa6cf3a1ee821e05d2923) fix(errors): report union input issues at the union's path ### 📊 Changes **14 files changed** (+277 additions, -71 deletions) <details> <summary>View changed files</summary> 📝 `docs/product-catalog.json` (+2 -2) 📝 `docs/verification/managed-conformance-manifest.json` (+2 -2) 📝 `skills/reverse-engineer-anything/SKILL.md` (+1 -1) 📝 `src/application/JavaScriptApplicationEmptyLiterals.test.ts` (+150 -4) 📝 `src/application/JavaScriptArtifactGraphAccumulator.ts` (+5 -30) 📝 `src/application/JavaScriptSemanticGraphBuilder.test.ts` (+15 -5) 📝 `src/application/JavaScriptSemanticGraphBuilder.ts` (+2 -0) 📝 `src/domain/inputIssueProjection.test.ts` (+23 -0) 📝 `src/domain/inputIssueProjection.ts` (+16 -2) 📝 `src/domain/javascriptApplicationEvidenceSchemas.ts` (+4 -2) 📝 `src/domain/javascriptApplicationVersionKeys.ts` (+15 -4) 📝 `src/domain/javascriptFeatureSeed.ts` (+6 -3) 📝 `src/domain/javascriptFeatureTraceSchemas.ts` (+35 -15) 📝 `src/generatedMcpToolCatalog.ts` (+1 -1) </details> ### 📄 Description ## Summary Follow-up to #839 and #836, addressing the Codex review findings on both ([#839 P1/P2](https://github.com/morluto/rea/pull/839), [#836 P2](https://github.com/morluto/rea/pull/836)). #839's description listed these as its trade-off. #839 kept schemas unchanged by displaying the empty string as `""` everywhere, **including inside node identities**. That substitution isn't injective: | Input | On `main` after #839 | |---|---| | `fetch(''); fetch('""')` | both endpoints get `identity.key: "\"\""` → **one merged node** | | source map `sources: ["", "\"\""]` | both get `original_source: "\"\""` → **one merged node** | | `{ ['']() {}, ['""']() {} }` | both function nodes have only `label: "\"\""`; no exact name in the graph | `original_source` also feeds version keys (`javascriptApplicationVersionKeys.ts`) and source-to-bundle path signals (`sourceToBundleSignals.ts`). On `main`, those see the two-character display text as if it were the reported path. ## Fix - **Identity is exact.** `artifact-local-key.key` and `source-map-original.original_source` now accept the empty string (`z.string()` instead of `min(1)`). The accumulator no longer rewrites identities, so node IDs are derived from the exact reported value. - **No synthetic application labels.** An empty value gets `label: null` (no display label) on application-graph observations, so `trace_application_feature` literal seeds, which match labels, cannot conflate `fetch('')` with `fetch('""')`. Semantic-graph labels keep the `""` display convention from #764, because feature seeds don't read them. - **Version comparison pairs exact empty values.** Semantic version keys read the exact `ipc-channel` `channel`, the `context-bridge-api` `api_key` when no label exists, and the `endpoint` `value`. The same empty IPC channel in two versions still pairs, and it stays distinct from a two-quote channel. - **Exact empty seeds are accepted.** `trace_application_feature` `seed` is a JSON-Schema-representable union. One branch is any kind with a nonempty `value`. The other is a non-`node-id` kind with `value: ""` and an explicit `match: "exact"`. The advertised schema and runtime validation therefore agree (`contains ""` would select every node). Empty context-bridge API seeds match the exact `properties.api_key`. - **Union input diagnostics keep their path.** Zod reports union branch issues relative to the union, so `projectInputIssues` now prefixes the union's path and deduplicates identical branch issues. A missing `seed` reports `["seed"] missing_argument` once instead of root-level `invalid_type` entries. - **Function nodes carry the exact name.** `properties.name` is added to every semantic `function` node, matching how property slots already carry `name`. Downstream consumers handle the exact empty value correctly: - `sourceToBundleSignals` `normalizeCurrentPath("")` returns `null`, so an empty source is not treated as a path. - Version keys become `source-map\0`, which stays distinct. - Feature-seed candidates never match an empty query. ## Contract / behavior changes - **Input schema relaxed:** `trace_application_feature` `seed` also admits `{ kind: <non-node-id>, value: "", match: "exact" }`. Every previously valid seed is still valid. - **Output schema relaxed:** `identity.key` (`artifact-local-key`) and `identity.original_source` (`source-map-original`) may now be `""`. This is backward compatible for consumers because it only admits more values. `npm run docs:generate` updated the catalog, skill, and conformance-manifest digests. - Graphs containing empty literals or empty source names now have distinct, exact identities. Output for inputs without them is unchanged, except that semantic `function` nodes now include `properties.name`. ## Verification - Updated and new regressions in `JavaScriptApplicationEmptyLiterals.test.ts` and `JavaScriptSemanticGraphBuilder.test.ts`: `fetch('')` vs `fetch('""')` give distinct endpoints with exact keys, `sources: ["", "\"\""]` gives distinct source modules, and `['']()` vs `['""']()` give distinct `properties.name`. There is also a feature-seed regression: a `""` exact seed matches only the two-quote endpoint. New regressions validate exact empty seeds against both Zod and the advertised JSON Schema (via Ajv 2020), plus an empty context-bridge API seed and union issue paths and cross-version pairing of an empty IPC channel. The pairing regression fails without the version-key change. **6 fail on current `main` and pass here.** - `npm run check:changed` after merging `main`: 62 files / 615 tests passed. - 18 JavaScript-graph boundary/acceptance suites (every test referencing the application or semantic graph): 119 tests passed (with the new regressions). - Contract and MCP catalog/schema suites: 12 files / 45 tests passed. After this round, `toolSchemaValidity`, product catalog, and the application workflow/MCP acceptance suites also passed (4 files / 28 tests); with `applicationWorkflowCli` and `retainedApplicationEvidenceMcp` added in the latest round, 6 files / 40 tests passed. - `npm run docs:check` and `npm run check:fast` passed. No Hopper/Ghidra/IDA verification needed (static JavaScript analysis only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-16 21:16:42 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2282
No description provided.