fix(detect): sort os.walk to ensure reproducible symbol IDs (#3407) - #3454
fix(detect): sort os.walk to ensure reproducible symbol IDs (#3407)#3454nikhilsaxena04 wants to merge 1 commit into
Conversation
…-Labs#3407) The bug: Cross-platform extractions were not deterministic (yielding different output graphs between macOS and Linux CI) because the fallback ordering relied on `os.walk`, which processes directories in raw filesystem order (unordered). The fix: Explicitly sorted `dirnames` and `filenames` in the `os.walk` loop in `graphify/detect.py` to guarantee that discovery is 100% reproducible regardless of the underlying OS or filesystem. Tests: `tests/test_detect_sort.py` added to assert on full relative paths to rigorously prove that os.walk is traversing the directories in sorted order. This prevents regression of non-deterministic traversal order.
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
Sorts dirnames and filenames in place during the os.walk traversal in detect, so scanned files are discovered in deterministic alphabetical order rather than filesystem-dependent order. Adds a test asserting detected code files come back in sorted repo-relative order.
No blocking issues surfaced.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 2164 functions depend on the 121 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract()— 563 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 43 more — each is listed as a finding
Verification — 2164 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: 762 function(s) in the blast radius were not formally verified this run
Test selection
Test selection
51 of 263 test file(s) selected (19%) 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_detect_sort.py— impact, changed-testtests/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_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 detect.
The verifier did not have enough to check detect, 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 `root` is annotated `Path` — outside the synthesizable primitive/collection set
· 51 more finding(s) on lines outside this diff (see the check run).
The bug:
Cross-platform extractions were not deterministic (yielding different output graphs between macOS and Linux CI) because the fallback ordering relied on
os.walk, which processes directories in raw filesystem order (unordered).The fix:
Explicitly sorted
dirnamesandfilenamesin theos.walkloop ingraphify/detect.pyto guarantee that discovery is 100% reproducible regardless of the underlying OS or filesystem.Tests:
tests/test_detect_sort.pyadded to assert on full relative paths to rigorously prove that os.walk is traversing the directories in sorted order. This prevents regression of non-deterministic traversal order.