Skip to content

feat(schema): body nodes and parameters carry their id in analysis.json - #165

Merged
rahlk merged 1 commit into
mainfrom
feat/issue-164-body-ids
Sep 6, 2026
Merged

feat(schema): body nodes and parameters carry their id in analysis.json#165
rahlk merged 1 commit into
mainfrom
feat/issue-164-body-ids

Conversation

@rahlk

@rahlk rahlk commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Closes #164. Parity with codeanalyzer-python 1.4.1's #180 (design in its #176).

Python now stamps an id on every body node in analysis.json<callable-id>@<local>, the same value its Neo4j projection merges the node on — and on every parameter — <callable-id>@formal_in:<i>, the L4 formal_in vertex that carries it, emitted as a forward reference below level 4. The shared vocabulary.md promises both. TypeScript emitted neither.

What this adds

  • TSBodyNode.id on every body node at every level, and TSCallableParameter.id on every parameter at every level
  • One definition of the join key. The composition rule lived in two private fq copies (build/neo4j/project.ts and dataflow/attach.ts). globalOrdinal in schema/ids.ts is now the single implementation; both delegate to it.
  • stampBodyIds runs after each body emitter — at the end of the L1 emitter per callable, and once over every callable at the end of applyDataflow. The second is deliberately not per-callee: L4 writes actual_in/actual_out vertices into caller bodies, so a per-callee stamp would miss them.

Verification

  • Two agreement tests, mirroring python's, pin the property against the other projection rather than a hand-typed string: every body node's id equals the set of projected :TSBodyNode keys for that callable; every parameters[i].id equals the @formal_in:i vertex's id, with the vertex's of naming the parameter. Plus an L1 test that call nodes and parameters carry ids before any dataflow exists.
  • Mutation-checked: skipping the body stamp and changing the @ separator each fail the tests
  • bun test green; container tests run (the projection's fq now delegates); schema.neo4j.json unchanged:TSBodyNode already carried id as its merge key and parameters aren't graph nodes
  • SCHEMA_VERSION stays 2.0.0 (chore(schema)!: collapse the schema version back to 2.0.0 #144); decision recorded in .claude/SCHEMA_DECISIONS.md

Note on the test's shape

Because both projections now share one definition, an agreement test alone can't detect a defect in globalOrdinal — both sides would move together. The L4 test therefore also pins the literal @formal_in:<i> shape, and the L3 test asserts a call node's id is never its callee. That's the same trade python made.

codeanalyzer-python 1.4.1 (#180, design #176) stamps `id` on every body node —
`<callable-id>@<local>`, the same value the Neo4j projection merges the node on —
and on every parameter — `<callable-id>@formal_in:<i>`, the L4 formal_in vertex
that carries it, emitted as a forward reference below level 4. The shared
vocabulary promises both. TypeScript emitted neither, and the composition rule
lived in two private `fq` copies (build/neo4j/project.ts, dataflow/attach.ts).

`globalOrdinal` in schema/ids.ts is now the single definition; both `fq`s delegate
to it. `stampBodyIds` runs after each body emitter: at the end of the L1 emitter
per callable, and once over every callable at the end of applyDataflow (L4 writes
actual_in/out into CALLER bodies, so a per-callee stamp would miss them).

Two agreement tests pin the property against the OTHER projection rather than a
hand-typed string: every body node's id equals the projected :TSBodyNode key for
that callable, and every parameters[i].id equals the @formal_in:i vertex id with
`of` naming the parameter. Mutation-checked: skipping the stamp and changing the
separator each fail the tests.

Additive; SCHEMA_VERSION stays 2.0.0 (#144). schema.neo4j.json is unchanged —
:TSBodyNode already carried id as its key, and parameters are not graph nodes.
@rahlk
rahlk merged commit 9232ebf into main Sep 6, 2026
1 check passed
@rahlk
rahlk deleted the feat/issue-164-body-ids branch September 6, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(schema): body nodes and parameters carry their id in analysis.json (python #180 parity)

1 participant