Repository navigation
Capture Lean sources once per doctor run - #236
Conversation
diagnose_project handed the Lean root to build_runtime_graph and to audit_graph, and each captured the sources on its own. A source that could not be captured (a named pipe, an unreadable folder, an edit during the capture) made the runtime projection raise first, so the runtime check carried the reason while graph, references and audit were marked as not run although the Markdown roadmap was fine, and lean targets said it was not checked. When only the second capture failed, lean targets reported a bare unreadable-lean-sources code instead. The two captures were never compared, so the projection and the Lean target checks could also judge different source sets in one run (B-F5, contracts-note-1). The doctor now resolves the root once, captures it once with snapshot_project_sources, and shares that capture: build_runtime_graph takes it through a new keyword-only lean_index and audit_graph through a new keyword-only lean_snapshot. Callers that pass lean_root keep the previous behavior, and passing both raises TypeError. audit's Lean target evaluation is split from its capture into _lean_target_findings, which takes the whole IndexedSourceSnapshot because the deprecation check reads the captured source files. A capture failure is reported once, by lean targets, with index_failure_message's reason, and the other checks still judge the roadmap; when the runtime projection fails for a Markdown reason, _blocked_result takes the capture failure as its lean targets check, so lean targets still names it. unreadable-lean-sources is dropped from the doctor's Lean finding codes because the audit can no longer return it to the doctor. The doctor section of autoform_cli/README.md now says the sources are captured once and where a capture failure is reported (README-doctor-indexes-twice). The test that pinned a failure of the audit's second capture is rewritten as a real edit during every capture attempt.
Main reworked tests/test_audit.py imports (os, Graph and Node for the implementation note tests). The conflict is resolved as the union with this branch's shutil and snapshot_project_sources imports.
47c671b gave build_runtime_graph a lean_index keyword and audit_graph a lean_snapshot keyword next to their lean_root keywords, with a TypeError when both were passed. That left two ways to hand each function Lean sources, and the doctor still sorted the audit's findings into roadmap and Lean findings by code. build_runtime_graph now takes only lean_index; load_runtime_graph, the one caller that passes a Lean root, resolves and captures it before projecting. audit_graph is unchanged: the doctor runs it without a Lean root and calls _lean_target_findings on its own capture, so _LEAN_FINDING_CODES and the code filter go away. An invalid Lean root is now the same lean targets failure as an unreadable source, so it is also reported when the runtime projection fails instead of "not checked". Tests: the runtime and audit tests that pinned the two-keyword API are removed (load_runtime_graph and audit_blueprint tests cover the capture paths). The doctor test that edited sources at an internal checkpoint is removed; the named-pipe test covers a capture failure failing only lean targets. The blocked-path test now also covers a missing Lean root.
The previous commit handed the doctor's one Lean capture to both the runtime projection and the lean targets check. The runtime half did nothing visible: the doctor reports only the runtime's schema, authority, source revision and counts, and none of them read Lean (source_revision ignores Lean, see #59). Its one Lean-dependent refusal, a source path escaping the Lean root, cannot come from a capture, whose paths are relative and whose entry names are checked. A mutant passing no Lean index survived every touched test. The doctor now projects the runtime without Lean and takes the lean targets findings from audit._lean_findings, so the audit's capture is the doctor's only one. That reverts runtime.py and audit.py to main, drops the doctor's own root resolution and its blocked-path Lean check, and leaves the blocked path saying "not checked because runtime projection failed" as on main. An unreadable source now reports "1 finding(s): unreadable-lean-sources" like every other finding; autoform audit --lean-root gives the reason. node-too-large needs the Lean root, so it now reports under lean targets instead of audit. The earlier rework made that move without saying so; a doctor test now pins it and the README states it.
The nested Project/ folder only fixed the path in the capture failure text, which the doctor no longer prints. The flat layout from main is enough for the FIFO and capture-count tests.
Review at d37e50eVerdict: Merge-ready. On main, Optional
Landing
Decision for the maintainer
This was a static review: no tests were run locally. CI at this head: all 9 checks pass. Posted by PR swarm: PR Swarm Lead |
#236 made the lean targets check the doctor's only Lean capture and dropped the runtime projection's Lean root, so this branch's _resolve_lean_root helper and its audit split no longer apply. The lean targets branch now calls resolve_lean_root itself: an unusable root reports the reason, otherwise the resolved root goes to _lean_findings, as the recipe in #236's body describes.
Resolves the conflicts the merged PRs' descriptions point at: - runtime: resolve the Lean root with resolve_lean_root before the name-filtered index (#231). - render: keep #235's no-capture path around the name-filtered capture, and warn when code links are skipped. - graph pages: count each chapter's formalization targets as #250 does, with the explorer's collapsed-node wording. - lean: take #265's section forms and mutual scopes. #269 removed tolerated_links, so the generation revision now filters the omitted entries that editor lock links leave. - tests: take #236's doctor test; keep the targeted-index tests beside #265's scope test.
Summary
autoform doctor --lean-rootcaptured the Lean sources twice (for the runtime projection and for the audit) and never compared the two. A source the capture refused, such as a named pipe or an edit during every attempt, failedruntimeand markedgraph,referencesandauditas not checked even when the roadmap was fine.source_revisionignores Lean, see runtime: build_runtime_graph labels stale node data with the current files' source_revision #59).audit_graphwithout Lean for theauditcheck, and takes thelean targetsfindings fromaudit._lean_findings, its only capture.autoform_cli/doctor.pyis +6/-36:_LEAN_FINDING_CODES, the step that split audit findings by code, and the doctor's own_resolve_lean_rootare gone. The README's doctor paragraph says which check reads Lean.runtime.pyandaudit.pyare unchanged.Behavior changes
lean targets, as1 finding(s): unreadable-lean-sources;runtime,graph,referencesandauditstill judge the roadmap.autoform audit --lean-rootprints the reason. On Windows, which has no descriptor traversal,doctor --lean-rootnow fails onlylean targetsthe same way.node-too-largereports underlean targetsinstead ofaudit. It needs--lean-root, andaudit_graphwithout a Lean root never produces it. The exit code is unchanged; the check lines and JSON change.Tests
All in
tests/test_doctor.py; each fails at main ae2db51:test_an_unindexable_lean_source_fails_only_the_lean_targets_checkreplacestest_unreadable_lean_sources_are_a_lean_target_failure, which patched the audit's capture and never saw the runtime one. A FIFO namedF.leanfails onlylean targets, with no host path in the JSON. At main,runtimefails.test_an_oversized_node_fails_the_lean_targets_check_not_the_audit: at main,auditfails withnode-too-largeandlean targetspasses.test_doctor_captures_the_lean_sources_oncecounts the capture'sbefore-final-verificationcheckpoint: 2 at main, 1 now. It also kills passinglean_roottobuild_runtime_graphagain.Overlap with open PRs
MAIN_REF=upstream/main pr_conflicts.shon this branch merged with main ae2db51, conflicts it adds:auditline, drop Name why a Lean root is unusable instead of indexing nothing or crashing #231's_resolve_lean_root, and in thelean targetsbranch callresolve_lean_root(lean_root)in atry: onLeanSourceErrorreportDoctorCheck("lean targets", False, str(error)), otherwise_finding_checkover_lean_findings(graph, lean_root). On that trial mergetest_doctor,test_lean_root,test_audit,test_runtimeandtest_clipass (167 tests) and ruff is clean.review-bundle-missingto the codes dropped from the audit; useaudit_graph(graph).findingsfiltered bycode != "review-bundle-missing". Also 1 more README hunk in the doctor paragraph; keep both added sentences.tests/test_doctor.py, from its**_kwargson the monkeypatch this branch's FIFO test replaces. Take this branch's test.Validation
At d37e50e:
test_doctor,test_runtime,test_audit,test_work,test_cli: 155 passed on Python 3.13 and 3.10.tests/test_doctor.pyon main ae2db51: 3 failed (the tests above), 13 passed.ruff check autoform_cli servers tests: clean.