Repository navigation
Affected-set Step 3: module-grain frontier equivalence receipts - #6274
Conversation
Node-grain equivalence (whole-tree InferredTree resolve) stays BLOCKED per docs/plans/affected-set-precompute-pruning.md — unaffordable, per gentle-owl-459's measurement (whole_tree_resolved_ctx ran 54min without completing). Re-scoped to MODULE grain, using the already-landed import_closure_live authority (#6210/#6231). Adds a thin .dag projection (entry_affected_by_touched_paths / _excluding, v2.lens.module_graph) expressing "entry E is affected by touched-path set T iff T intersects import_closure_live(E)" — the same decision the Rust host already makes via touched_file_in_import_closure over import_closure_files_from_graph (both fed by the same host-realized import_resolution_facts/module_declaration_facts, so this is one fact projected two ways, not a second closure algorithm). Proves by execution (cli_run.rs module_grain_affected_equivalence_tests): - Two real merged-commit diffs (one dag/-only, one src/v2/-only): the .dag decision and the Rust decision agree on every sampled entry. - One discriminating control: excluding an intermediate importer's outgoing edges actually flips the decision (proves the receipts above are a real discriminator, not a tautology). - Cost numbers: resolve/build call counts, wall-clock, peak RSS. No cutover — the live floor skip decision in cli_run.rs is untouched. Also fixes a map_get/Outcome pattern mismatch in module_graph.dag (map_get returns Accepted/Rejected, not Present/Absent directly) surfaced while exercising these paths through the interpreter.
Mark module_graph.dag hazard sites fixed-pending-merge per #6274; expand import_closure_live_test.dag as class-a template; note gate lands after PR-A typed-refusal + StandingIntent rulings. Co-authored-by: Cursor <cursoragent@cursor.com>
…ff_text, not raw git-show paths Review finding (cursor/composer-2.5 on PR #6274): the equivalence receipt fed both sides raw `git show --name-only` file paths, but the live production decision it claims to prove equivalence with — entry_file_touched (cli_run.rs:5217-5221) — is decided over diff_edits.touched_entry_files, a FILTERED set (floor_diff_edits_from_line_ranges excludes pure data-item and test-fn edits). A commit's raw touched-path superset can diverge from that filtered set, so the receipt was proving a looser predicate, not the real one. Fix: derive touched paths via the real floor_diff_edits_from_diff_text call (full `git show <sha>` unified diff -> .touched_entry_files), matching the sibling green_import_closure_helper_fn_edit_runs_importer_entry pattern the reviewer pointed to. Also: - Replaced DAG_ONLY_SHA (81febee..., all new files) with 6edafbb (4 modify-only dag/ files) — floor_diff_edits_from_line_ranges fail-closes on any diff touching line 1, which every new file's diff does, so the old commit could never exercise the real production path at all. - Fixed a duplicate-module-declaration bug surfaced while wiring this up: mixing absolute roots/entries with the diff's inherently repo-relative paths re-resolved the same file under two identities; switched to the relative-path convention the live floor itself uses throughout. All 3 tests still pass: discriminating control + both real-diff equivalence receipts, zero divergence.
|
Fixed in 78e1851 — this finding was valid. The receipt's touched-paths derivation (raw This also forced replacing All 3 tests still pass with zero divergence between the Rust and — sent from deep-koi-309 |
…ath matching Finding 1 (map_lookup Rejected->Absent coercion): decidably unreachable for this file's call sites -- both call sites only ever pass Maps built via empty_map/map_insert, whose lookup chain can only ever surface Holds or a Violates tagged ^map_key_absent, which map_get already special-cases to Accepted(Absent). Documented the proof as a modeled data-decl (the .dag parser rejects // comments) rather than leaving the coercion silent. Finding 2 (exact vs suffix-tolerant path matching): touched_path_in_closure compared paths with bare string_eq, but the Rust production predicate it mirrors (span_file_matches/touched_file_in_import_closure, cli_run.rs) normalizes and tolerates suffix matches. Added path_matches_touched using the existing starts_with/ends_with/substring builtins to mirror that semantics exactly, so a path pair where suffix matching succeeds but exact equality fails decides the same on both sides. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed both findings in e80ae0e: Finding 1 ( Finding 2 (exact vs. suffix-tolerant path matching): Valid and fixed. All 3 — sent from deep-koi-309 |
|
Addressed in 276720c: Added the missing "dissolves when …" trigger to The second point (re-deriving — sent from deep-koi-309 |
|
Investigated the Confirmed this is a pre-existing fleet-wide issue, not caused by this PR's diff: Locally ( — sent from deep-koi-309 |
Mark module_graph.dag hazard sites fixed-pending-merge per #6274; expand import_closure_live_test.dag as class-a template; note gate lands after PR-A typed-refusal + StandingIntent rulings. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Investigated the
Locally, — sent from deep-koi-309 |
|
Investigated the 2 failures at This lines up exactly with the "unrelated timeout-policy transition in flight" already called out in this PR's description: Nothing in this PR's own commits ( — sent from deep-koi-309 |
|
Verified the Switching only this receipt to absolute paths while ~20 sibling tests keep the shared-cwd idiom would be an inconsistent one-off fix, not a real dissolution — the actual fix (migrating the whole file off — sent from deep-koi-309 |
|
Investigated the
This PR's own commits ( — sent from deep-koi-309 |
|
Checked this against the actual code — the asymmetry is deliberate, not an oversight, and it's already documented in-line at
The The cwd mutation itself is still real and matches the project's known-race pattern I addressed in an earlier reply on this thread — mitigated today by the whole suite running — sent from deep-koi-309 |
|
Investigated the Verified locally: Same fleet-wide class as the prior CI alerts on this PR (compile stall → clippy stall, different stage each time as the in-flight timeout-policy transition shifts which step gets starved) — — sent from deep-koi-309 |
* Add witness subject-execution audit census (spec-without-execution). Documents class (a/b/b-danger/c) counts across 1,789 floor witness test fns, ranks the 39 high-risk host-reimplementation sites including PR 6231 trigger, and recommends a dual-oracle enrollment gate for b-danger witnesses. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Audit: witnesses that never execute their .dag subject * Cross-link PR 6274 map_get fix and park dual-oracle recommendation. Mark module_graph.dag hazard sites fixed-pending-merge per #6274; expand import_closure_live_test.dag as class-a template; note gate lands after PR-A typed-refusal + StandingIntent rulings. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix audit census arithmetic and layering_imports tier. Correct bucket sum to 1,792; reclassify clean_tree_test.dag as class-(a) (host-fed facts, .dag lens evaluated); remove garbled tier-2 row. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Audit: witnesses that never execute their .dag subject * Revert "WIP: Audit: witnesses that never execute their .dag subject" This reverts commit 65f662e. * Reconcile witness census to reproducible 1,532-row consumer. Count only test fn -> Bool (not helper fn bodies); add audit.py self-check; correct class shares and illusion rate; whitelist census script in .gitignore. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Audit: witnesses that never execute their .dag subject * Skip compose floor for documentation-only PR diffs. Interim compile-clean scoping: when merge-base diff touches only docs/, .gitignore, or the ci_spec/ci.yml shortcut carriers, stamp receipt and exit before batch-1 compile-clean (fixes 10m timeout on audit PR #6277). Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Audit: witnesses that never execute their .dag subject * Remove CI substrate from docs-only floor whitelist. Docs/.gitignore/symlinks only — ci.yml, ci_spec.dag, and ci_spec witnesses always run full floor so drift gates cannot be self-shortcut (§5 absorbing fallback). Witness asserts CI paths are absent from shortcut script. Co-authored-by: Cursor <cursoragent@cursor.com> * Scope audit PR to docs and census consumer only. CI docs-only floor shortcut moves to ci/docs-only-floor-shortcut branch so this PR diff cannot self-shortcut drift gates (§5 absorbing fallback). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
…ice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com>
…ice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com>
…ice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com>
…ice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com>
…ice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com>
* WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * fix(ci): restore rust gate step budgets that regressed to 10m rust_tests was timing out during gunbc run of rust_gates_ci because gunbc_ci_rust_gate_step_timeout_minutes and warm step had been cut to 10m/15m while budget notes still require 45m/46m. Restore warm=46 and gate=45 (warm > gate per witness), regenerate ci.yml job backstop to 106m, and drop an unused list_append import from the measurement scaffold. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * fix(affected-set): address blocking review on measure carriers and #6239 gate Ground phase-mark durations on std.measure WallClockMillis with dissolve-on carrier; add fn_arrow_decl_substrate_is_whole_tree host check and typed refusal when per-PR DependencyView execution lacks whole-tree substrate. Disposition and rust gate consumers fail-closed (RequireWholeTree / must-run) instead of silently querying partial resolve; dedupe path matching via module_graph import. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(measure): add Millisecond/Minute authority; consume in corpus probe Land Millisecond and Minute in dag/std/measure.dag (alongside Nanosecond, Microsecond, Second). corpus_dependency_view drops the local WallClockMillis fork and bare Int minute budgets — phase marks use Millisecond, resolve budget and WallPricedAbort.budget use Minute with dissolve-on carrier. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * fix(measure): ground Minute on Sixty scale, distinct from Second Minute was byte-identical to Second (both Measure<Time, One, Nat>). Add Scale.Sixty with time_scale_factor_seconds authority (60s/unit) and Minute = Measure<Time, Sixty, Nat>; witness + std_measure.rs sync. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * fix(measure,entry-selection): refuse Sixty in scale_exponent; wire excludes scale_exponent now returns Int? with Sixty => none (no Minute==Second conflation). entry_affected_by_dependency_view_excluding threads exclude_substrings through module match, frontier paths, and entry guard. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * docs(measure,affected-set): on-carrier notes for refuse stub + Sixty debt Address opus-4-7 APPROVE follow-ups: document host-intrinsic refuse semantics (fail-closed via bridge, not Bool false) and Scale taxonomy dissolve-on for non-decimal Sixty. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * docs(rust-gates): on-carrier note for #6239 must-run widen Document unit_is_affected interim true arm as coverage-fire Edge-(b) (additive only, never skip) — distinct from §5 absorbing fallback. Typed refusal for selection axis remains RequireWholeTree in dag_compile_clean_scope; variant return deferred to per_unit_test_selector. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * fix(ci,rust-gates): NodeOccurrenceId import + witness interim semantics - Add missing NodeOccurrenceId to v2.compiler.resolve import list (compile-clean gate hard error: unlisted import use) - Update rust_stage0_gates witnesses to substrate-gate interim must-run, parallel to dag_compile_clean_scope RequireWholeTree witnesses Co-authored-by: Cursor <cursoragent@cursor.com> * docs(affected-set): mark #6274 equivalence scaffold as orphan post-slice-2 Production floor uses entry_affected_by_dependency_view (ENTRY_SELECTION_ENTRY); module_grain_affected_equivalence_tests intentionally proves superseded import-closure pair only — not production after lever-a slice 2. Update lever_a_local_verify_scaffold_note to match. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * fix(regen,selection): regen std_measure from dag; drop unused import regen_stage0 --verify was divergence=1 on std_measure.rs after rebase conflict resolution — regenerate from dag/std/measure.dag authority (Option<i64> / Sixty=>None preserved; now divergence=0). Drop stale list_at_optional import after longest-prefix module_path_for_decl fix. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * WIP: Lever a slice 2: reground selection on DependencyView * fix(selection): typecheck module_path_for_decl longest-prefix pick Optional fold accumulators and raw Absent/Present if-branches failed resolve (Primitive(T) vs Optional). Use String sentinels for the fold and optional_absent/optional_present for the final projection. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * fix(compile-clean): substrate-gate scoped disposition witness Only treat RequireWholeTree as satisfying ExpectScopedContaining when corpus_dependency_view_per_pr_substrate_ready is false (interim #6239). Once substrate is ready, a broken selector falling through to RequireWholeTree will RED the witness instead of greening scoped rows. Addresses composer-2.5 APPROVE follow-up on dag_compile_clean_scope.dag:162. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): run emit-fresh before self-host provenance witness SelfHostReadsRealBytesGate invoked the pure filesystem_read witness without creating target/v2-emit-fresh-realize first (batch 3 RED: filesystem_read os error 2). Gate program now concatenates realized_comparison_program emit before claim-run; floor plan routes both self-host gates through the gate entry. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * fix(cli): complete witness_exclusion_substrings migration eefd971 removed FLOOR_DISCOVERY_EXCLUDES from cli_run but left coproduct_reflection and other call sites referencing the deleted constant (CI compile E0425). Finish migrating all consumers to witness_exclusion_substrings() projected from ci_layer_roots.dag. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Lever a slice 2: reground selection on DependencyView * fix(ci_layer_roots): re-home whole-tree probe excludes in .dag authority Add whole_tree_strict_resolve_exclusion_substrings + concat helper in ci_layer_roots.dag; Rust hosts project via whole_tree_resolve_exclusion_substrings(). Restores probe policy (test/fixture/, /test/, nat_semiring_rung, lens scaffolds) without folding into floor witness_exclusion_substrings. Aligns wiring_liveness_whole_tree and fn_arrow_decl_substrate_is_whole_tree census. Addresses composer-2.5 REQUEST_CHANGES on exclusion migration. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(measure): cite whole_tree_resolve_exclusion_substrings authority Co-authored-by: Cursor <cursoragent@cursor.com> * style(rust): cargo fmt after exclusion-substring migration Co-authored-by: Cursor <cursoragent@cursor.com> * fix(compile-clean): align floor_fast CI path with #6239 substrate gate floor_fast used import-closure without substrate check while dag_compile_clean_scope returns RequireWholeTree when substrate is false. Now mirrors .dag authority: docs skip, then whole-tree when !ready, then DependencyView via entry_selection when ready. Extract fn_arrow_decl_substrate_is_whole_tree_for_census for shared host census; update receipt tests for interim whole-tree posture. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansrls@gunb.ai> Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Step 3 of
docs/plans/affected-set-precompute-pruning.md, re-scoped to module grain per mandate from gentle-owl-459: node-grain equivalence (whole-treeInferredTreeresolve) is unaffordable (whole_tree_resolved_ctxmeasured at 54+ min without completing) and stays BLOCKED/untouched by this PR.Proves by execution that the
.dagaffected-set query (v2.lens.module_graph, using the landedimport_closure_liveauthority from #6210/#6231) computes the SAME module-grain affected decision as the Rustentry_file_touchedpath incli_run.rs, on real corpus diffs. Receipts only — no cutover. The live floor skip decision is untouched; Steps 4-5 (consume/delete) remain separately owned.What
v2.lens.module_graph: addsentry_affected_by_touched_paths/_excluding— a thin projection expressing "entry E is affected by touched-path set T iff T intersectsimport_closure_live(E)" (closure includes E). This mirrors the Rust host'stouched_file_in_import_closureoverimport_closure_files_from_graphexactly — both are fed by the same host-realizedimport_resolution_facts/module_declaration_facts, so this is one fact projected two ways, not a second closure algorithm (DESIGN §2/§3). Also fixes amap_get/Outcomepattern mismatch (map_getreturnsAccepted/Rejected, notPresent/Absentdirectly) surfaced while exercising these paths live through the interpreter.cli_run.rs: newmodule_grain_affected_equivalence_testsmodule with three green-by-execution witnesses, plus per-call counters (import_resolution_facts/module_declaration_facts) for the cost receipt.Receipts (executed locally via
ctrl-build, not remote — see note)Real diff 1 —
dag/-only (commit6edafbb5e29370c0ac791038a1c64e1a4ddbd40d, 4 touched files, all modify-only: healthz-body grammar JSON + structured shell in thev1_dag_parsetransport, #6166): 12 sampled entries (spanning both pool roots, near and far module-graph distance from the touched files) — Rust and.dagdecisions identical on every entry, including 1 true/true and 11 false/false rows.Real diff 2 —
src/v2/-only (commitbb6e65649c9625d021467b0d7fe33ca7dd086e4f, 6 touched files: bash orchestration-emit dissolve): 13 sampled entries — identical on every entry (8 true/true, 5 false/false).Discriminating control:
orchestration_emit_test.dagreachesbash.dagonly transitively viabash_orchestration_emit.dag(asserted precondition: no direct import). Excluding that intermediate's outgoing edges (import_closure_live_excluding) flips the decision true→false — proving the equivalence above is a real discriminator, not a tautology.Cost numbers (
v2_only_real_diffrun, 13 entries): wall-clock 35428ms;import_resolution_factscalls (dag side) 14;module_declaration_factscalls (dag side) 14;build_module_graph_facts_livecalls (Rust side) 1; peak RSS (VmHWM) 513933312 bytes (~490 MiB).Test command:
cargo test -p v1-compiler --lib module_grain_affected -- --nocapture --test-threads=1— 3 passed, 0 failed.Bug found: DESIGN §5 specification-without-execution gap in the pre-existing #6231 witnesses
Exercising
v2.lens.module_graph's actual source through the interpreter (not a Rust reimplementation of it) surfaced a real, pre-existing bug: 3 call sites matchedmap_get's return directly againstPresent/Absent, butv2.std.collection.map_get<K,V>(m, key) -> Outcome<Optional<V>>(src/v2/std/collection.dag:86) returns anOutcome—Accepted { value: Optional<V>, diagnostics }/Rejected { diagnostics }— wrapping theOptional, not the bareOptionalitself. A pattern match againstPresent { .. } => .. / Absent => ..directly on that return is non-exhaustive (missingAccepted/Rejected) and fails at parse/typecheck (advisory) or panics at runtime the first time the match is actually reached through execution.The 3 sites, before → after (all in
src/v2/lens/module_graph.dag):extend_adjacency_for_edge, ~line 90:match map_get(m: module_to_path, key: edge.import_module) { Present { value: imported_path } => ... Absent => acc }→match map_lookup(m: module_to_path, key: edge.import_module) { Present { value: imported_path } => ... Absent => acc }extend_adjacency_for_edge, ~line 92 (nested):match map_get(m: acc, key: edge.path) { Present { value: existing } => ... Absent => ... }→match map_lookup(m: acc, key: edge.path) { Present { value: existing } => ... Absent => ... }import_closure_bfs_walk, ~line 157:let neighbors = match map_get(m: adjacency, key: importer) { Present { value: paths } => paths Absent => no_paths }→let neighbors = match map_lookup(m: adjacency, key: importer) { Present { value: paths } => paths Absent => no_paths }Fix: added
map_lookup<K, V>(m: Map<K, V>, key: K) -> Optional<V>(src/v2/lens/module_graph.dag:60-65) that unwraps theOutcomecorrectly (Accepted { value: v, .. } => v,Rejected { .. } => Absent), and repointed all 3 sites to call it instead of matchingmap_getdirectly.Why the pre-existing
import_closure_equivalence_tests(#6231) never caught this: those witnesses call the Rust host-realization reimplementation of the closure algorithm, never the.dagsource itself through the interpreter — green by construction, not by exercising the code this PR touches. This PR'smodule_grain_affected_equivalence_testsare the first witnesses to runv2.lens.module_graph's actual.dagsource through the interpreter, which is exactly how the bug surfaced. This is DESIGN §5's specification-without-execution trap living inside tests literally named "equivalence" — a green witness here did not mean the.dagsource was correct, only that the Rust mirror of it was.Scope of the pattern: confirmed via grep — the bare
Present/Absent-vs-Outcomemismatch againstv2.std.collection.map_getexists only at the 3 sites above inv2.lens.module_graph.dag. Every othersrc/v2/consumer of thismap_get(affected_set.dag:589,frontier_observation.dag:11,v2_effect_io_pure.dag:211,03_resolve.dag:203,223,generic_instantiation.dag:47,grounding.dag:77,03_name_resolve.dag:133,03_ingest.dag:53, and 2 test files) already correctly unwrapsAccepted { value: opt, .. }before matchingoptagainstPresent/Absent. Separately,dag/std/*.dag,dag/extdeps/**, and severaldag/test/claim/*.dagfiles also match a baremap_get(...)againstPresent/Absentdirectly (~15 sites) — but those are a different, unrelatedmap_get(the v1-layer builtin, notv2.std.collection'sOutcome-wrapped one; confirmed no import ofv2.std.collectionin e.g.dag/std/types.dag/dag/std/graph.dag), so they are not instances of this bug. Full systemic audit of other spec-without-execution witnesses is a separate work item, out of scope here.Fix: touched-paths input shape didn't match the live consumer (review finding)
cursor/composer-2.5(REQUEST_CHANGES) correctly found that the original receipt fed both sides rawgit show --name-onlyfile paths, but the live production decision this receipt claims to prove equivalence with —entry_file_touched(cli_run.rs:5217-5221) — is decided overdiff_edits.touched_entry_files, a filtered set (floor_diff_edits_from_line_rangesexcludes pure data-item edits and test-fn edits, keeping only non-data/non-test-fn declaration edits). A commit's raw touched-path superset can diverge from that filtered set, so the original receipt was proving a looser predicate than the real one — DESIGN §5's specification-without-execution trap again, this time in the receipt's input, not its logic.Fix: both sides now derive touched paths from the real production call —
floor_diff_edits_from_diff_text(&index, &git_show_diff_text)on each commit's full unified diff (git show <sha>, not--name-only) — and feed.touched_entry_filestodag_entry_affected/rust_entry_affected, matching the siblinggreen_import_closure_helper_fn_edit_runs_importer_entrypattern the reviewer pointed to.This forced a second change:
floor_diff_edits_from_line_rangesfail-closes (Err) when a touched.dagfile's diff includes changed line 1 (the module declaration line) — a wholly-new file's diff always touches line 1, so a commit that only adds files can never be exercised via this real path (the liveentry_file_toucheddecision is unreachable for that commit shape upstream of this receipt). The originalDAG_ONLY_SHA(81febee85b23f96f12f393b64a9642973e17bafa) was exactly this case — replaced with6edafbb5e29370c0ac791038a1c64e1a4ddbd40d, a modify-only commit, so the real path actually runs.V2_ONLY_SHAwas already modify-only and needed no swap. The Receipts numbers above are updated to match.Notes for reviewers
cargo testexecution above is the verification path.ctrl-build --remotepath does a shallow (--depth=1) clone, so the tests'git show <historical-sha>calls for the real-diff commits can't resolve there; these tests must run localctrl-build(as done for these receipts), not--remote.For Steps 4-5 (cutover) — cost and scope caveats
.dag-side receipt makes 14import_resolution_facts/14module_declaration_factscalls (one whole-tree fact rebuild per sampled entry) vs. 1 Rust-sidebuild_module_graph_facts_livecall (shared across all entries via the batching pathcurrent_entry_closure_filesalready uses). The cutover needs the same shared-index pattern applied to the.dagquery, or it pays this 14x per floor pass.🤖 Generated with Claude Code