Skip to content

fix: canonicalize semantic whole-file code aliases - #3249

Open
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3246-semantic-code-node-dedup
Open

fix: canonicalize semantic whole-file code aliases#3249
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3246-semantic-code-node-dedup

Conversation

@hopstreax

Copy link
Copy Markdown
Contributor

Summary

Fixes #3246.

When a code file is both AST-parsed and referenced by a semantic extraction source such as a planning document, the semantic extractor can create a suffixed alias such as <file_stem>_module. This previously survived as a separate node from the canonical AST file node, leaving the code and documentation disconnected.

This change canonicalizes recognized whole-file semantic aliases onto the existing AST file node.

What changed

  • Added deterministic resolution for semantic _module, _script, and _file aliases.

  • Only aliases whose stripped ID exactly matches an existing AST file-level node are canonicalized.

  • Preserves the AST node as the authoritative node for:

    • id
    • _origin
    • source_file
    • source_location
    • label
    • file_type
  • Preserves non-conflicting semantic metadata from the alias.

  • Rewires incoming/outgoing edges to the canonical AST node.

  • Rewrites hyperedge members when an alias is removed.

  • Added regression coverage for the issue and safety cases.

Safety

The resolver is intentionally narrow:

  • It only recognizes _module, _script, and _file.
  • It requires an exact match against an existing AST file-level node.
  • Nested symbols such as _run or _parse_args are not affected.
  • Same-named files in different directories remain isolated.

Validation

  • tests/test_semantic_code_file_alias.py8 passed
  • tests/test_build.py tests/test_dedup.py167 passed
  • Broader graph invariant suites — 88 passed
  • git diff --cached --check — clean

Total validated: 263 tests passed.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds semantic whole-file alias canonicalization (#3246): during build_from_json, _code_file_alias_remap detects LLM-minted entity nodes suffixed with _module, _script, or _file and folds them onto the matching bare-stem AST file node, keeping the AST node as the survivor with its authoritative _origin/source_file/source_location/label and merging only non-conflicting semantic attributes like rationale and summary. Edges and hyperedges pointing at the alias are rewired to the AST node, with resulting self-loops and duplicate hyperedge members dropped. Nested symbol nodes below the file stem (e.g. ..._run) and similarly named files under different paths stay distinct.

No blocking issues surfaced. 10 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1175 functions depend on the 97 functions this change touches.

Health — this change adds coupling hotspots:

  • new: _rebuild_code() — 113 callers, 50 callees
  • new: build_from_json() — 199 callers, 19 callees
  • new: build_merge() — 62 callers, 13 callees
  • new: to_obsidian() — 36 callers, 13 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: to_wiki() — 41 callers, 7 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: _call_claude_cli() — 31 callers, 9 callees
  • …and 38 more — each is listed as a finding

Verification — 1175 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 775 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify build\_from\_json.

The verifier did not have enough to check build\_from\_json, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 6 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly NameError — names the real obstacle, not a sampling gap)

· 1 grounded finding(s) anchored inline below; 45 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/build.py
return remap, attr_updates


def build_from_json(extraction: dict, *, directed: bool = False, root: str | Path | None = None) -> nx.Graph:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionbuild_from_json()

fans out to 19 callees (efferent coupling); 199 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

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.

Node merge/dedup doesn't match a code entity to a planning-doc node describing the same file (different source_file)

1 participant