Skip to content

feat(extract): write the omitted-file list where a user can read it - #3577

Open
L4XB wants to merge 1 commit into
Graphify-Labs:v8from
L4XB:fix/3574-uncovered-files-list
Open

L4XB wants to merge 1 commit into
Graphify-Labs:v8from
L4XB:fix/3574-uncovered-files-list

Conversation

@L4XB

@L4XB L4XB commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Part 3 of #3574.

The incomplete-extraction warning names five files and counts the rest:

[graphify extract] semantic extraction is incomplete: 73 dispatched file(s)
produced no nodes and 0 came back truncated or hollow. ...

and the reporter had to diff the graph against a filesystem walk to find out which 73. The list was never missing: llm.py already puts every one of them on the merged result as uncovered_files, and cli.py reads that only for its length and then drops it.

The change

cli.py writes it to graphify-out/.graphify_uncovered_files.json, next to the other dot-prefixed artifacts, and the warning ends with the path so the next step is obvious rather than archaeological.

Two boundaries, each with a cell:

  • A clean run clears it. A list left over from an earlier run describes files that are covered now, which is worse than no list at all, so an empty result unlinks the file.
  • It never costs the extraction. An output directory that refuses the write loses the diagnostic and nothing else, the same stance backup_if_protected takes.

Test

Three cells in tests/test_hollow_chunks_arm_shrink_guard.py, which is where the _omitted_files path is already exercised end to end through mainmod.main(). Two of them drive the real CLI rather than the helper: one asserts the written list and that the warning names its path, the other seeds a stale list and asserts a covered run removes it.

All three fail on v8 (ImportError, the API is new). The suite is green at 8, and the related slices at 350 passed, 6 skipped. The one failure in that run, test_ollama_retry_cap.py::test_api_timeout_is_passed_to_client, also fails on unmodified v8 here.

Mutation-checked: four seeded defects — never writing, keeping a stale list, dropping the path from the message, and letting a refused write abort the run — each caught by a named cell, none surviving.

Parts 1 and 2 are separate. Part 1 is #3576. Part 2, the AST cache pinning ids to the extraction root, I could not reproduce on v8; the details are in a comment on the issue.

The incomplete-extraction warning names five files and counts the rest, and
the full list was already sitting in `uncovered_files` on the merged result:
`cli.py` read it only for its length and then dropped it. Recovering the rest
meant diffing the graph against a filesystem walk.

Write it to graphify-out/.graphify_uncovered_files.json and say so in the
warning. A run with everything covered removes the file rather than leaving
one that describes an earlier run, and an output directory that refuses the
write costs the diagnostic rather than the extraction.

@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 a .graphify_uncovered_files.json sidecar written into the graphify-out directory during semantic extraction that records the full sorted list of dispatched files that produced no nodes, so the list is recoverable instead of only counted in the incomplete-extraction warning. The warning now appends the path to that file when it was written, an empty list deletes any stale sidecar from an earlier run, and _write_uncovered_files swallows OSError so a read-only output directory drops the diagnostic without failing the extraction.

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

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 294 functions depend on the 81 functions this change touches.

Health — this change adds coupling hotspots:

  • new: dispatch_command() — 2 callers, 125 callees
  • new: _stale_graph_sources() — 7 callers, 6 callees
  • new: _run_hook_guard() — 4 callers, 8 callees
  • new: test_poisoned_manifest_is_healed() — 0 callers, 6 callees

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

Test selection

Test selection

24 of 275 test file(s) selected (9%) via static blast radius.

  • tests/test_affected_cli.py — impact
  • tests/test_agents_platform.py — impact
  • tests/test_codebuddy.py — impact
  • tests/test_devin.py — impact
  • tests/test_explain_cli.py — impact
  • tests/test_extract_cli.py — impact
  • tests/test_global_add_tag_inference.py — impact
  • tests/test_god_nodes_cli.py — impact
  • tests/test_hollow_chunks_arm_shrink_guard.py — impact, changed-test
  • tests/test_hook_guard_token_match.py — impact
  • tests/test_hook_out_of_project_paths.py — impact
  • tests/test_hook_strict.py — impact
  • tests/test_incomplete_build_guard.py — impact
  • tests/test_install.py — impact
  • tests/test_install_references.py — impact
  • tests/test_merge_chunks_validation.py — impact
  • tests/test_multigraph_diagnostics.py — impact
  • tests/test_no_dedup_flag.py — impact
  • tests/test_partial_cache.py — impact
  • tests/test_path_cli.py — impact
  • tests/test_query_cli.py — impact
  • tests/test_query_induced_edges.py — impact
  • tests/test_stale_prune.py — impact
  • tests/test_unverified_semantic_shrink.py — impact

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

Could not verify: Could not verify dispatch\_command.

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

· 4 more finding(s) on lines outside this diff (see the check run).

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