Skip to content

Extract deterministic type-use relationships and graph gap evidence - #2949

Open
Soumava1 wants to merge 13 commits into
Graphify-Labs:v8from
Soumava1:v8
Open

Extract deterministic type-use relationships and graph gap evidence#2949
Soumava1 wants to merge 13 commits into
Graphify-Labs:v8from
Soumava1:v8

Conversation

@Soumava1

Copy link
Copy Markdown

Summary

  • add deterministic extracted Python type-use relationships with role metadata
  • preserve incremental resolution parity and runtime-edge precedence
  • add actionable graph-gap classification and markdown/type-alias relationship improvements
  • include implementation designs, plans, and regression coverage

Test plan

  • 375 passed, 8 skipped in the Windows-compatible extractor/build suite
  • DebtGPS acceptance audit: 34 extracted Debt type uses, 4 test-only inferred references, PlanState field role, refinance runtime call

@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.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

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


Graphify review — findings

Adds deterministic Python uses_type/EXTRACTED edges classified from Tree-sitter annotation context (parameter/return/field, plus nested variants) with aggregated per-target roles, replacing annotation-backed uses/INFERRED edges in the resolution pass. Wires the resolver to accept unchanged-corpus nodes and scan root during incremental extraction, and classifies uses_type as generic in build.py so runtime edges like calls/inherits win same-endpoint collapse. Includes an implementation plan doc and broad test coverage for extraction semantics, incremental resolution, collapse precedence, and conservative fallback on ambiguous/external/local-only references.

Worth a look

  • Unbounded Markdown line fragment can crash extractiongraphify/extractors/markdown.py:258 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Markdown extraction no longer skips non-document linksgraphify/extractors/markdown.py:358 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Duplicate bare module stems now suppress absolute import resolutiongraphify/extractors/resolution.py:1939 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Annotation-only imports no longer emit the existing uses edgegraphify/extractors/resolution.py:2187 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Graph labels are interpolated into Markdown report without escapinggraphify/report.py:318 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 3403 functions depend on the 1653 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 482 callers, 44 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: build_from_json() — 186 callers, 18 callees
  • new: build_merge() — 46 callers, 14 callees
  • new: _extract_generic() — 18 callers, 24 callees
  • new: to_obsidian() — 34 callers, 12 callees
  • new: to_json() — 50 callers, 7 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • …and 94 more — each is listed as a finding

Verification — 3403 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: 3023 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify suggest\_questions.

The verifier did not have enough to check suggest\_questions, 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 200 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly ValueError — names the real obstacle, not a sampling gap)

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, 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: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

Could not verify: Could not verify extract\_markdown.

The verifier did not have enough to check extract\_markdown, 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: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_resolve\_markdown\_link.

The verifier did not have enough to check \_resolve\_markdown\_link, 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: parameter `source_dir` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_resolve\_cross\_file\_imports.

The verifier did not have enough to check \_resolve\_cross\_file\_imports, 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: the input domain has 81 values but only 9 distinct were tested — a small finite domain must be EXHAUSTED, not sampled (an untested input could invert the result)

Could not verify: Could not verify generate.

The verifier did not have enough to check generate, 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 200 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly ValueError — names the real obstacle, not a sampling gap)

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

def _resolve_markdown_link(raw: str, source_dir: Path,
wikilink: bool = False) -> "Path | None":
"""Resolve a markdown link target to the absolute path of a sibling document.
def _resolve_markdown_target(

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 regression_resolve_markdown_target()

6 callers depend on it (afferent coupling).

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

target = _resolve_markdown_target(raw, source_dir, wikilink=wikilink)
return target.path if target is not None else None

def extract_markdown(path: Path) -> dict:

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 regressionextract_markdown()

fans out to 8 callees (efferent coupling); 14 callers depend on it (afferent coupling).

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

Comment thread graphify/gaps.py
)


def classify_gap_node(graph: nx.Graph, node_id: str) -> GapCategory:

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 regressionclassify_gap_node()

9 callers depend on it (afferent coupling).

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

return index


def canonicalize_python_type_aliases(

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 regressioncanonicalize_python_type_aliases()

7 callers depend on it (afferent coupling).

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

return int(match.group(1)) if match else None


def resolve_markdown_code_references(

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 regressionresolve_markdown_code_references()

high coupling complexity (Ca·Ce = 15).

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.

1 participant