Conversation
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.
There was a problem hiding this comment.
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— impacttests/test_agents_platform.py— impacttests/test_codebuddy.py— impacttests/test_devin.py— impacttests/test_explain_cli.py— impacttests/test_extract_cli.py— impacttests/test_global_add_tag_inference.py— impacttests/test_god_nodes_cli.py— impacttests/test_hollow_chunks_arm_shrink_guard.py— impact, changed-testtests/test_hook_guard_token_match.py— impacttests/test_hook_out_of_project_paths.py— impacttests/test_hook_strict.py— impacttests/test_incomplete_build_guard.py— impacttests/test_install.py— impacttests/test_install_references.py— impacttests/test_merge_chunks_validation.py— impacttests/test_multigraph_diagnostics.py— impacttests/test_no_dedup_flag.py— impacttests/test_partial_cache.py— impacttests/test_path_cli.py— impacttests/test_query_cli.py— impacttests/test_query_induced_edges.py— impacttests/test_stale_prune.py— impacttests/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).
Part 3 of #3574.
The incomplete-extraction warning names five files and counts the rest:
and the reporter had to diff the graph against a filesystem walk to find out which 73. The list was never missing:
llm.pyalready puts every one of them on the merged result asuncovered_files, andcli.pyreads that only for its length and then drops it.The change
cli.pywrites it tographify-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:
backup_if_protectedtakes.Test
Three cells in
tests/test_hollow_chunks_arm_shrink_guard.py, which is where the_omitted_filespath is already exercised end to end throughmainmod.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 unmodifiedv8here.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.