fix(detect): gate the bare out dir on build-output evidence (#3347) - #3424
fix(detect): gate the bare out dir on build-output evidence (#3347)#3424abhay-codes07 wants to merge 2 commits into
Conversation
…-Labs#3347) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJbLfztSxm2tH5cJwBbe9q
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Gates pruning of a bare out/ directory on actual build-output evidence instead of removing it by name, so hexagonal codebases' adapter/out/ and port/out/ source layers stay in the scan. A new _has_build_output_markers prunes only when it finds an IntelliJ production/ layout, a Next.js _next/ export tree, or compiled artifacts (.class, .js.map, .d.ts, etc.) in the top two levels, and keeps the directory when the parent can't be verified. build, dist, and target still prune unconditionally.
Worth a look
- Build markers after the first 20 subdirectories are ignored —
graphify/detect.py· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- Bare out directories are no longer excluded from detect results —
graphify/detect.py:830· 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 — 2165 functions depend on the 134 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 559 callers, 43 callees - new:
_rebuild_code()— 115 callers, 51 callees - new:
detect()— 110 callers, 15 callees - new:
_extract_generic()— 18 callers, 26 callees - new:
save_manifest()— 40 callers, 11 callees - new:
extract_files_direct()— 17 callers, 20 callees - new:
extract_js()— 85 callers, 4 callees - new:
extract_xaml()— 19 callers, 17 callees - …and 44 more — each is listed as a finding
Verification — 2165 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
Test selection
Test selection
51 of 260 test file(s) selected (20%) via static blast radius.
tests/test_astro_extraction.py— impacttests/test_atomic_writes.py— impacttests/test_build.py— impacttests/test_charmap_encoding.py— impacttests/test_chunking.py— impacttests/test_cjs_module_extension.py— impacttests/test_claude_cli_backend.py— impacttests/test_cpp_nested_and_cli.py— impacttests/test_detect.py— impacttests/test_dotnet.py— impacttests/test_evidence_binding.py— impacttests/test_extract.py— impacttests/test_extract_cli.py— impacttests/test_file_slice.py— impacttests/test_ignore_file_encoding.py— impacttests/test_image_vision.py— impacttests/test_import_extension_resolution.py— impacttests/test_incremental_mtime_collision.py— impacttests/test_indirect_dispatch.py— impacttests/test_indirect_dispatch_assign_return.py— impacttests/test_indirect_dispatch_getattr.py— impacttests/test_js_exported_scalar_bindings.py— impacttests/test_languages.py— impacttests/test_llm_backends.py— impacttests/test_long_path_hashing.py— impacttests/test_manifest_ingest.py— impacttests/test_mcp_ingest.py— impacttests/test_multilang.py— impacttests/test_non_regular_files.py— impacttests/test_office_incremental.py— impacttests/test_office_limits.py— impacttests/test_ollama.py— impacttests/test_out_dir_evidence.py— impact, changed-testtests/test_oversized_document_slicing.py— impacttests/test_package_json_subpath_imports.py— impacttests/test_pdf_slicing.py— impacttests/test_pdf_token_estimate.py— impacttests/test_phantom_external_import.py— impacttests/test_pipeline.py— impacttests/test_python_underscore_resolution.py— impacttests/test_rationale.py— impacttests/test_ruby_resolution.py— impacttests/test_scala_self_type.py— impacttests/test_stale_prune.py— impacttests/test_swift_computed_properties.py— impacttests/test_ts_new_expression_calls.py— impacttests/test_typescript_module_extensions.py— impacttests/test_unmapped_at_alias_resolution.py— impacttests/test_vue_extraction.py— impacttests/test_watch.py— impact- … and 1 more
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 \_is\_noise\_dir.
The verifier did not have enough to check \_is\_noise\_dir, 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 `parent` is annotated `'Path | None'` — outside the synthesizable primitive/collection set
· 52 more finding(s) on lines outside this diff (see the check run).
…the first 20 Review follow-up: a wide TS outDir keeping compiled files only under a late-sorted module dir slipped past the 20-subdirectory cap. The level-two probe now covers every subdirectory, bounded by total entries scanned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJbLfztSxm2tH5cJwBbe9q
|
On the two advisories: the 20-subdirectory cap was a fair catch — ff0a8f6 replaces it with a probe over every subdirectory bounded by total entries scanned (4000), with a test putting the only .js.map under the 31st-sorted subdir. The second finding describes the PR's intended behavior rather than a defect: an unverifiable |
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Gates pruning of bare out/ directories on build-output evidence instead of removing them by name, so hexagonal source layers like adapter/out/ and port/out/ stay in the scan. _has_build_output_markers treats an IntelliJ production/ dir, a next export _next/ tree, or compiled artifacts (.class, .js.map, .pyc, etc.) in the top two levels as proof it's generated, probing one level into subdirs under a 4000-entry scan budget; an out/ that can't be verified is kept, matching the keep-on-doubt bias of the existing env/coverage/snapshots gates. build, dist, and target still prune unconditionally.
Worth a look
- Wide-outDir budget probe order is nondeterministic (os.scandir order), so late-artifact detection is not guaranteed —
graphify/detect.py· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- Nested source out/production packages are pruned as IntelliJ output —
graphify/detect.py:928· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
- Build-output probe follows directory symlinks outside the scan tree —
graphify/detect.py:934· 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 — 2167 functions depend on the 136 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 559 callers, 43 callees - new:
_rebuild_code()— 115 callers, 51 callees - new:
detect()— 110 callers, 15 callees - new:
_extract_generic()— 18 callers, 26 callees - new:
save_manifest()— 40 callers, 11 callees - new:
extract_files_direct()— 17 callers, 20 callees - new:
extract_js()— 85 callers, 4 callees - new:
extract_xaml()— 19 callers, 17 callees - …and 44 more — each is listed as a finding
Verification — 2167 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: 777 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
51 of 260 test file(s) selected (20%) via static blast radius.
tests/test_astro_extraction.py— impacttests/test_atomic_writes.py— impacttests/test_build.py— impacttests/test_charmap_encoding.py— impacttests/test_chunking.py— impacttests/test_cjs_module_extension.py— impacttests/test_claude_cli_backend.py— impacttests/test_cpp_nested_and_cli.py— impacttests/test_detect.py— impacttests/test_dotnet.py— impacttests/test_evidence_binding.py— impacttests/test_extract.py— impacttests/test_extract_cli.py— impacttests/test_file_slice.py— impacttests/test_ignore_file_encoding.py— impacttests/test_image_vision.py— impacttests/test_import_extension_resolution.py— impacttests/test_incremental_mtime_collision.py— impacttests/test_indirect_dispatch.py— impacttests/test_indirect_dispatch_assign_return.py— impacttests/test_indirect_dispatch_getattr.py— impacttests/test_js_exported_scalar_bindings.py— impacttests/test_languages.py— impacttests/test_llm_backends.py— impacttests/test_long_path_hashing.py— impacttests/test_manifest_ingest.py— impacttests/test_mcp_ingest.py— impacttests/test_multilang.py— impacttests/test_non_regular_files.py— impacttests/test_office_incremental.py— impacttests/test_office_limits.py— impacttests/test_ollama.py— impacttests/test_out_dir_evidence.py— impact, changed-testtests/test_oversized_document_slicing.py— impacttests/test_package_json_subpath_imports.py— impacttests/test_pdf_slicing.py— impacttests/test_pdf_token_estimate.py— impacttests/test_phantom_external_import.py— impacttests/test_pipeline.py— impacttests/test_python_underscore_resolution.py— impacttests/test_rationale.py— impacttests/test_ruby_resolution.py— impacttests/test_scala_self_type.py— impacttests/test_stale_prune.py— impacttests/test_swift_computed_properties.py— impacttests/test_ts_new_expression_calls.py— impacttests/test_typescript_module_extensions.py— impacttests/test_unmapped_at_alias_resolution.py— impacttests/test_vue_extraction.py— impacttests/test_watch.py— impact- … and 1 more
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 \_is\_noise\_dir.
The verifier did not have enough to check \_is\_noise\_dir, 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 `parent` is annotated `'Path | None'` — outside the synthesizable primitive/collection set
· 52 more finding(s) on lines outside this diff (see the check run).
Closes #3347.
The problem
_SKIP_DIRScontains the bare nameout, matched unconditionally — so in a hexagonal / ports-and-adapters codebase,adapter/out/andport/out/(the entire outbound layer: persistence adapters, entities, outbound ports) are silently dropped from the scan. On the reporting repo that was 196 of 655.javafiles — 30%, including every@Entityclass — with exit code 0 and no warning._is_noise_diralready gates three ambiguous names on corroborating evidence, keeping the directory when it cannot verify:env/.env/*_envon venv markers (#2058),coverageon report artifacts (#2339),snapshotson.snapfiles (#1666).outgot none of it.The change
outbecomes the fourth gated name._has_build_output_markersprunes it only on real generated-output evidence:out/production/subdir);out/_next/subtree);.class,.jar,.o,.obj,.exe,.dll,.pyc,.js.map,.css.map,.d.ts) in the top two directory levels — a boundedos.scandirprobe, same cost profile as the venv/coverage gates.An
outthat cannot be verified is kept — the same keep-on-doubt bias every other gated name has, and pruned-as-noise dirs stay traceable viapruned_noise_dirs(#2058).build,distandtargetremain unconditional; the wider question of gating those is #2479's, and this PR deliberately stays on theoutcase where the dropped set is an architectural layer under a mainstream source convention rather than an incidental directory.Tests
tests/test_out_dir_evidence.py— 5 tests:adapter/out/andport/out/holding only source stay in the corpus (the issue's shape, and the test that failson the unpatched tree); IntelliJ
out/production/, anext exportout/, and a TS outDir with.js.mapone level down are all still pruned; andbuild/dist/targetstay unconditionally pruned. The detect suites are unchanged (584 passed; the two failing hook tests fail identically on cleanv8on this Windows machine); the full suite matches a fresh same-versionv8(0.9.56) baseline.🤖 Generated with Claude Code
https://claude.ai/code/session_01JJbLfztSxm2tH5cJwBbe9q