Repository navigation
Put the drift comparator on the clock wall, and delete the Rust arm reconstruction - #7844
Conversation
The operator's 2026-08-05 ruling: recording both clocks is correct; the defect is a duration whose meaning lives only in its field NAME. This is the observation-authority half of that ruling (7820A landed the seed half in #7820). std.observation gains ClockBasis = CpuClock | WallClock and TimedMeasurement { basis, elapsed }, and two carriers stop naming their clock in prose: ObservationOutcome.TimedOut now carries `basis`, so a kill says WHICH cap it crossed — a 5000ms thread-CPU fail-stop and a 600000ms wall receipt ceiling were previously indistinguishable, and the CI line now renders the clock beside both figures. ObservationEvent.wall becomes `durations: List<TimedMeasurement>`. A list rather than one tagged duration because the seed already holds both clocks for every occurrence (run_claim_measured), and because the operator ruled thread CPU is the REMEDY DISCRIMINATOR beside a wall threshold: high wall + high CPU is algorithm or repeated evaluation, high wall + low CPU is waiting, I/O or scheduling. One clock cannot make that call. A record with `cpu` and `wall` fields would have been the nickname twice, which is what the operator refused when 7820A's first draft proposed cpu as a third measured quantity beside wall and rss. The payoff is a construction wall, not a rename: witness_row_cost_verdict now takes the observed clock, WitnessRowCostDatedBasis carries its own, and a cross-clock comparison answers BasisClockMismatch — a fourth arm, not a Bool collapse, on the same reasoning std.content_hash refuses cross-family comparison. Comparing a CPU figure against a wall baseline used to typecheck and answer confidently; four sessions spent an evening doing exactly that. Not walled, and said so on the carrier: two entries may share one basis. The construction that would forbid it is a total function from a closed sum, which this substrate lacks (Map is a closure, not wire-serializable, and refused by the determinism gate). So observation_duration_of REFUSES an ambiguous read with the duplicate as its cause rather than silently picking the first — rung mechanically preventable, ceiling structurally impossible, trigger named. Green by execution with discriminating REDs, all run locally: witness_row_cost_projection_holds PASS; RED when the basis filter is removed from observation_clock_lookup (the silent first-match pick) witness_row_cost_drift_comparator_holds PASS incl. two new cross-clock controls on BOTH sides of the 2x ratio, so the refusal is proven to be decided by the clock and not by the magnitude; RED when the comparator stops checking it floor_component_receipt (15), observation_model (36), ci_render (19), tty_render (16), seed_scoped_run (10), crawl_replay (3) all PASS ClockBasis is exported vocabulary: gunbc#7831 states WallClock in its own policy carrier and rebases onto this. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The .dag verdict authority now refuses a cross-clock comparison, but the production falsifier receipt does not reach it: the seed calls only witness_row_cost_exceeds_basis and rebuilds the verdict arms in Rust, so the clock never crosses that seam. That comparison is still correct today — both sides are wall — but for a reason about the current producers rather than about the mechanism, which is exactly the state this ruling exists to end. Said on the carrier with its next trigger, so the rung is not inflated to cover a path the wall does not stand on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The row's eval term became List<TimedMeasurement>, and the seed's extractor still called nanosecond_count on it — so production project_witness_cost_receipt refused with "cannot access field 'count' on List" while every .dag witness stayed green, because none of them cross that Rust seam. Found two ways, independently: by running the existing production_witness_cost_projection_* Rust tests (2 of 3 failed), and by review 48651, which prescribed the same remedy. Worth naming why CI would not have: nextest was removed from CI in 2026-07-11, so those tests run locally only, and the witness corpus proves the .dag projection rather than the transport that reads it. The fix reads ONE clock through the authored projection rather than walking the list in Rust: witness_cost_clock_nanos calls std.observation.observation_duration_of, the same accessor every .dag consumer uses, so the seed cannot grow a second copy of the lookup or of its ambiguity refusal. Which clock it wants is now a thing it has to say, and it says wall — the clock the witness threshold is stated on. An unsampled clock comes back None, never 0, matching the unmeasured-cell discipline the sibling receipt already keeps. Wall coming back None refuses: the authored projection already guarantees a wall figure, so its absence here means the row reached the transport without the one measurement the receipt exists to carry. production_witness_cost_projection_preserves_exact_nanoseconds_and_ordering ok production_witness_cost_projection_preserves_failed_and_refused ok production_witness_cost_projection_refuses_missing_and_duplicate_parent ok Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…econstruction
The follow-up gunbc#7837's witness_row_cost_clock_mismatch_note declared,
now dissolved in place rather than left as a note.
That PR grew a cross-clock refusal on the .dag comparator, and the
production falsifier cadence could not reach it: the seed called only
witness_row_cost_exceeds_basis, the bare ratio predicate, and rebuilt
DriftExceeded / WithinBasis / BasisAbsent as Rust string literals. Two
defects in one shape — a second representation of WitnessRowCostVerdict,
and a seam the clock never crossed, so a CPU figure against a wall basis
would still have answered confidently. It was correct only because both
sides happened to be wall, which is a fact about the producers and not a
property of the mechanism.
Three parts, and the third is the load-bearing one:
Both basis files carry a REQUIRED per-row clock cell. An unstated clock
refuses at parse and an unmodelled one refuses too — never a default to
wall, which would be right for every row today and silently wrong the
first time someone seeds from a CPU receipt. The 1176 existing rows are
stamped wall because that is what they ARE: before the ruling the seed's
PerformanceReceipt held only wall_nanos.
The seed calls witness_row_cost_seed_verdict_dated / _undated and
renders the arm the AUTHORITY named. It constructs no carrier — the
Optional stays inside .dag and whether a dated basis exists is the map
lookup the seed already had, which is data presence, not judgement.
The Rust arm reconstruction is DELETED, not kept beside the carrier. An
arm added to WitnessRowCostVerdict now reaches the cadence receipt with
no Rust edit, and BasisClockMismatch is counted on its own line because
its remedy differs from BasisAbsent's: fix the producer handing over the
wrong clock, versus seed the missing row.
Both comparators move together — the compile-clean cost drift shares this
parser and authority by design, so leaving it on the old predicate would
have forked what it was built to share.
Green by execution, with the discrimination named:
drift_verdicts_come_from_the_authority_and_a_cross_clock_basis_refuses
asserts the cross-clock refusal on BOTH sides of the 2x ratio (21ms
and 20ms against a 10ms basis), so it is proven decided by the clock
and not by the magnitude. This is the ONLY test that crosses this Rust
seam — the .dag witnesses cannot reach it and the parser tests only
show the cell is read.
parse_witness_row_cost_basis_line_requires_srv_fleet_arm64 gains a
cpu-clock positive, a missing-clock refusal, and an unknown-clock
refusal.
committed_witness_row_cost_basis_loads_and_excludes_the_censored_row ok
over all 1176 migrated rows.
ObservationAbsent stays decided seed-side, deliberately: an absent
observation has no counterpart in the sum, and giving it one would let a
row with no measurement reach a comparator at all.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
review 48672, correctly: the sibling witness-row-cost path reports clock_mismatch on its [receipt] summary and the compile-clean path did not, so the two receipts disagreed about whether the state this change exists to expose is worth surfacing. The summary line is where a reader looks to see whether a state fired. A degradation that is counted internally but omitted from the line someone actually reads is the counting half-done: its frequency is observable in principle and invisible in practice. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One conflict, in witness_row_cost_clock_mismatch_note, and it is the note this PR exists to rewrite: main carries #7837's version declaring the production drift path as not-yet-covered with its trigger named, and this branch carries the version saying the wall now runs there. Resolved to ours, because this PR is what makes that true — the seed calls the authored verdict and the Rust arm reconstruction is gone. Green by execution on the resolved tree: witness_row_cost_projection_holds and witness_row_cost_drift_comparator_holds both PASS, cargo check clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Closing out review 48799 (REQUEST_CHANGES, conflict markers in What it saw, and why it existed: the reviewed head Which arm I kept, on the reviewer's own criterion (whichever matches the shipped Verified on the resolved tree: no markers in either conflicted file; — sent from merry-raven-690 |
Two conflicts, both the same shape: main carries the state BEFORE the drift lane, and this branch stacks on the drift lane. - witness_row_cost.dag witness_row_cost_clock_mismatch_note: kept the past-tense arm. main's arm names 'the Rust arm reconstruction is DELETED' as its NEXT TRIGGER; #7844 discharges that trigger, so carrying main's hedge forward would understate the rung. - cli_run.rs: kept the named WitnessRowCost struct and the witness_cost_clock_nanos reads over main's positional 7-tuple. The tuple is exactly the by-position naming the clock-basis ruling retired. Verified on the resolved tree: cargo check --workspace --all-targets clean; witness_row_cost_drift_comparator_holds and witness_row_cost_projection_holds green by execution.
Three conflicts, all one shape: main's claim_executor.rs reads the row positionally (row.0 / row.1 / row.2) because #7844 landed without cli_run.rs, where this branch defines the named WitnessRowCost. Resolved to ours at all three, which is the only consistent resolution -- our cli_run.rs is what declares the struct those field names read. Verified: zero conflict markers tree-wide; cargo check --workspace --all-targets clean.
The merge of main (#7824, #7790, #7844) into this branch collided at the tail of falsifier_substrate_long_lane_rows — my seven C0(b1) census rows and main's two new rows append at the same list position. Both sides are kept; 39 rows, no duplicate (entry, function) pair, every entry file present on disk. The conflicted file was committed and pushed with markers intact by the autocommit path before this resolution, so this commit is the repair of that state, not a fresh merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* WIP: Witness cost/purpose/admission: retire long/ as authority * WIP: Witness cost/purpose/admission: retire long/ as authority * WIP: Witness cost/purpose/admission: retire long/ as authority * Retire the wall nickname: durations carry their clock (7820B) The operator's 2026-08-05 ruling: recording both clocks is correct; the defect is a duration whose meaning lives only in its field NAME. This is the observation-authority half of that ruling (7820A landed the seed half in #7820). std.observation gains ClockBasis = CpuClock | WallClock and TimedMeasurement { basis, elapsed }, and two carriers stop naming their clock in prose: ObservationOutcome.TimedOut now carries `basis`, so a kill says WHICH cap it crossed — a 5000ms thread-CPU fail-stop and a 600000ms wall receipt ceiling were previously indistinguishable, and the CI line now renders the clock beside both figures. ObservationEvent.wall becomes `durations: List<TimedMeasurement>`. A list rather than one tagged duration because the seed already holds both clocks for every occurrence (run_claim_measured), and because the operator ruled thread CPU is the REMEDY DISCRIMINATOR beside a wall threshold: high wall + high CPU is algorithm or repeated evaluation, high wall + low CPU is waiting, I/O or scheduling. One clock cannot make that call. A record with `cpu` and `wall` fields would have been the nickname twice, which is what the operator refused when 7820A's first draft proposed cpu as a third measured quantity beside wall and rss. The payoff is a construction wall, not a rename: witness_row_cost_verdict now takes the observed clock, WitnessRowCostDatedBasis carries its own, and a cross-clock comparison answers BasisClockMismatch — a fourth arm, not a Bool collapse, on the same reasoning std.content_hash refuses cross-family comparison. Comparing a CPU figure against a wall baseline used to typecheck and answer confidently; four sessions spent an evening doing exactly that. Not walled, and said so on the carrier: two entries may share one basis. The construction that would forbid it is a total function from a closed sum, which this substrate lacks (Map is a closure, not wire-serializable, and refused by the determinism gate). So observation_duration_of REFUSES an ambiguous read with the duplicate as its cause rather than silently picking the first — rung mechanically preventable, ceiling structurally impossible, trigger named. Green by execution with discriminating REDs, all run locally: witness_row_cost_projection_holds PASS; RED when the basis filter is removed from observation_clock_lookup (the silent first-match pick) witness_row_cost_drift_comparator_holds PASS incl. two new cross-clock controls on BOTH sides of the 2x ratio, so the refusal is proven to be decided by the clock and not by the magnitude; RED when the comparator stops checking it floor_component_receipt (15), observation_model (36), ci_render (19), tty_render (16), seed_scoped_run (10), crawl_replay (3) all PASS ClockBasis is exported vocabulary: gunbc#7831 states WallClock in its own policy carrier and rebases onto this. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * State where the clock wall runs and where it does not The .dag verdict authority now refuses a cross-clock comparison, but the production falsifier receipt does not reach it: the seed calls only witness_row_cost_exceeds_basis and rebuilds the verdict arms in Rust, so the clock never crosses that seam. That comparison is still correct today — both sides are wall — but for a reason about the current producers rather than about the mechanism, which is exactly the state this ruling exists to end. Said on the carrier with its next trigger, so the rung is not inflated to cover a path the wall does not stand on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: Witness cost/purpose/admission: retire long/ as authority * Fix the seed decode path for the tagged eval durations The row's eval term became List<TimedMeasurement>, and the seed's extractor still called nanosecond_count on it — so production project_witness_cost_receipt refused with "cannot access field 'count' on List" while every .dag witness stayed green, because none of them cross that Rust seam. Found two ways, independently: by running the existing production_witness_cost_projection_* Rust tests (2 of 3 failed), and by review 48651, which prescribed the same remedy. Worth naming why CI would not have: nextest was removed from CI in 2026-07-11, so those tests run locally only, and the witness corpus proves the .dag projection rather than the transport that reads it. The fix reads ONE clock through the authored projection rather than walking the list in Rust: witness_cost_clock_nanos calls std.observation.observation_duration_of, the same accessor every .dag consumer uses, so the seed cannot grow a second copy of the lookup or of its ambiguity refusal. Which clock it wants is now a thing it has to say, and it says wall — the clock the witness threshold is stated on. An unsampled clock comes back None, never 0, matching the unmeasured-cell discipline the sibling receipt already keeps. Wall coming back None refuses: the authored projection already guarantees a wall figure, so its absence here means the row reached the transport without the one measurement the receipt exists to carry. production_witness_cost_projection_preserves_exact_nanoseconds_and_ordering ok production_witness_cost_projection_preserves_failed_and_refused ok production_witness_cost_projection_refuses_missing_and_duplicate_parent ok Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Put the drift comparator on the clock wall, and delete the Rust arm reconstruction The follow-up gunbc#7837's witness_row_cost_clock_mismatch_note declared, now dissolved in place rather than left as a note. That PR grew a cross-clock refusal on the .dag comparator, and the production falsifier cadence could not reach it: the seed called only witness_row_cost_exceeds_basis, the bare ratio predicate, and rebuilt DriftExceeded / WithinBasis / BasisAbsent as Rust string literals. Two defects in one shape — a second representation of WitnessRowCostVerdict, and a seam the clock never crossed, so a CPU figure against a wall basis would still have answered confidently. It was correct only because both sides happened to be wall, which is a fact about the producers and not a property of the mechanism. Three parts, and the third is the load-bearing one: Both basis files carry a REQUIRED per-row clock cell. An unstated clock refuses at parse and an unmodelled one refuses too — never a default to wall, which would be right for every row today and silently wrong the first time someone seeds from a CPU receipt. The 1176 existing rows are stamped wall because that is what they ARE: before the ruling the seed's PerformanceReceipt held only wall_nanos. The seed calls witness_row_cost_seed_verdict_dated / _undated and renders the arm the AUTHORITY named. It constructs no carrier — the Optional stays inside .dag and whether a dated basis exists is the map lookup the seed already had, which is data presence, not judgement. The Rust arm reconstruction is DELETED, not kept beside the carrier. An arm added to WitnessRowCostVerdict now reaches the cadence receipt with no Rust edit, and BasisClockMismatch is counted on its own line because its remedy differs from BasisAbsent's: fix the producer handing over the wrong clock, versus seed the missing row. Both comparators move together — the compile-clean cost drift shares this parser and authority by design, so leaving it on the old predicate would have forked what it was built to share. Green by execution, with the discrimination named: drift_verdicts_come_from_the_authority_and_a_cross_clock_basis_refuses asserts the cross-clock refusal on BOTH sides of the 2x ratio (21ms and 20ms against a 10ms basis), so it is proven decided by the clock and not by the magnitude. This is the ONLY test that crosses this Rust seam — the .dag witnesses cannot reach it and the parser tests only show the cell is read. parse_witness_row_cost_basis_line_requires_srv_fleet_arm64 gains a cpu-clock positive, a missing-clock refusal, and an unknown-clock refusal. committed_witness_row_cost_basis_loads_and_excludes_the_censored_row ok over all 1176 migrated rows. ObservationAbsent stays decided seed-side, deliberately: an absent observation has no counterpart in the sum, and giving it one would let a row with no measurement reach a comparator at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Count clock_mismatch on the compile-clean receipt line too review 48672, correctly: the sibling witness-row-cost path reports clock_mismatch on its [receipt] summary and the compile-clean path did not, so the two receipts disagreed about whether the state this change exists to expose is worth surfacing. The summary line is where a reader looks to see whether a state fired. A degradation that is counted internally but omitted from the line someone actually reads is the counting half-done: its frequency is observable in principle and invisible in practice. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Give the row-cost receipt its CPU column, beside the wall one The last piece of the 2026-08-05 clock-basis ruling with a real consumer gap. #7820 renamed eval_ms to eval_wall_ms and #7837 made the row carry both clocks; nothing yet printed the second one, so the remedy that second clock exists to discriminate could not be read from the artifact at all. The seven-wide anonymous tuple becomes WitnessRowCost. That is not tidying: a positional tuple is how `eval` came to mean "wall" by index and nothing else — the same defect one layer below the ObservationEvent.wall field name this lane retired — and it is exactly what would have made a second clock "the third u128". eval_cpu_ms sits immediately beside eval_wall_ms, asserted by the test rather than left to convention, so an author reads the remedy from one file without joining another: high wall with high CPU is algorithm or repeated evaluation, high wall with low CPU is waiting, I/O, subprocess or scheduling. It is not a second threshold — the witness threshold is stated on wall. An unsampled clock renders `unmeasured`, never 0. A `0` there would claim the witness used no CPU at all, which reads as the strongest possible remedy signal — pure waiting — about a row for which nothing was measured. That is the fabricated zero the outcome column already closed, one column over. Green by execution, with the discrimination proven rather than assumed: witness_row_cost_receipt_distinguishes_unexecuted_from_sub_millisecond gains a wall-only fixture, and goes RED when the renderer is changed to `unwrap_or(0)` — failing on the exact fabricated cell: cpu_clock_not_sampled 4 0 0 0 Done It also asserts the two clocks are independent carriers (500us wall against 300us cpu, so a producer filling both from one figure would be caught) and that the two columns are adjacent in the header. cargo test --bin claim_executor 68 passed, 0 failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Merge main (#7844 squash-merged) into the cpu-column lane Three conflicts, all one shape: main's claim_executor.rs reads the row positionally (row.0 / row.1 / row.2) because #7844 landed without cli_run.rs, where this branch defines the named WitnessRowCost. Resolved to ours at all three, which is the only consistent resolution -- our cli_run.rs is what declares the struct those field names read. Verified: zero conflict markers tree-wide; cargo check --workspace --all-targets clean. --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…1/b2 scope claims (#7821) * WIP: cost analysis * C0(b): v1 complexity capability census, typed and executed Delivers deliverable (b) of the v2 complexity capability parity program's C0 phase: one typed inventory row per capability that src/v1/complexity.dag carries, each with a disposition from a closed sum. Deliverables (a) the authority ruling and (c) the RatchetForever re-classification are operator decisions and are deliberately absent. Carrier: gunbc.v1_complexity_capability_census. Every arm carries required non-empty payloads, so an unjustified disposition is unwritable rather than lens-caught. Adds a sixth arm, DispositionDeferred, because the five declared arms had no home for a capability whose disposition is one of the note's own open questions; forcing parser-progress into a neighbouring arm would have fabricated a decision nobody made. Witness: 15 checks green by execution, including two RED controls. Each row's v1 symbol resolves against the live seed and each cited destination symbol against the file its row names, so a stale citation reds rather than reading plausibly. Four findings, each executed rather than asserted: 1. C4 is smaller than the parity note's table implied. std.graph, std.termination, std.computation and std.induction already carry the SCC and descent vocabulary and v1 reaches it by import, while v2's lens modules import none of them — owed work is consumption, not migration. The v1-AST walkers that produce that vocabulary are the real C4 surface. 2. std.induction's CostBound/derive_bound vocabulary was missing from the do-not-re-mint list; added. 3. evict_summary overwrites an entry with a zero-cost Proven summary instead of removing it, so an evicted function reads as "costs nothing, proven" rather than "not computed". Rostered as a hazard that must not migrate with the capability. 4. cost_account_space_from_summary's note cites CostAccount.space with a Derived basis; it constructs no CostAccount, v1 does not import std.realization_schedule, and CostBasis has no Derived arm. Gives parity open question 3 a receipt. Also corrects the sibling note's correction 1, which claimed no valuation environment existed anywhere in the tree: the seed has one (eval_cost_expr_concrete, env: Map<String, Int>), and it is String-keyed. The narrower claim is the useful one — the seam is absent from v2, and v1's key is the anemic identity parity §6 forbids carrying across. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: cost analysis * C0(b1): exact DeclarationRef citations, corrected disposition algebra Reworks the census on operator review. The previous revision proved its authored rows were well-formed and distinct; it did not prove its citations resolved or that its dispositions stated the remaining work honestly. Both are addressed, and the title is narrowed to what is actually established. Finding 1 — citations are exact, not substring. CitedSymbol { symbol, file } is replaced by a typed DeclarationRef resolved through v2.std.decl_ref_resolution. The file becomes an OBSERVED property of the resolved declaration (rel_path) rather than a second authored identity. The discriminating control: "Derived" appears verbatim in a seed note string, so the old check found it; as a DeclarationRef it is not a declaration and resolution refuses. Planted absent-declaration and absent-module refusals accompany it. Finding 2 — no closed denominator. Retitled C0(b1) "reviewed roster". Declaration-to-capability totality is now an explicit C0(b2) slice that derives the population from DeclFact. The 171/201 discrepancy is resolved as a method identity: 171 counts top-level fn; 201 counts fn+type+data+let (26 type, 4 data). Both correct; the method was missing. Finding 3 — disposition algebra. AvailableInSharedSubstrate projected as discharged, understating C4; it is now IntegrationOwed with its own work-state, because v2 must still consume std.graph et al. DeliberatelyRetired belonged to no partition, so exhaustiveness was green-by-vacancy; retirement now splits into RetirementOwed (replacement has not executed) and Retired (discharged), and every arm — including the two no row inhabits — carries a controlled fixture. DispositionDeferred is removed per the parser-progress ruling. Finding 4 — weak controls. Eviction is now proven by EXECUTION: cache a summary with work 42, evict, look it up; the seed returns work 0, span 0, certainty Proven instead of Absent, while a never-cached function correctly returns Absent. The constant-true finding uses the module's own typed VacuousValidation carrier plus execution rather than asserting the function exists. Finding 5 — stale contract table: linearity_audit's WallAfterGrounding boundary restored and complexity_lowering added with its distinct SingleAuthority dissolution. Operator rulings recorded: C0(a) signed (carried as the typed CostAuthorityModule vocabulary, with the atomic-relocation nuance); C0(c) split ruled as the next slice; parser progress split into migration + retirement rows; WorkAtom closed-outer/open-identity shape; CostBasis three-valued per resource axis; span stays in C2; C5 is two changes never one; no blanket specialized-lens collapse. Execution split stated rather than buried: exact resolution and the eviction control need a decl_facts pool including src/v1, so they live in the long lane and per-PR CI does not run them. The offline recipe is named in gunbc.ci_layer_roots. Fast structural half: 10/10 green, max 2ms. Long lane: 9/9 green locally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Move the vacuity control off the fast lane — measured closure cost The floor red on this PR was not the two named witnesses being flaky. Measured, same runner class: roadmap_program_view_witness_test witness_live_constraint_present_iff_line_unaccepted ran 3901.9ms on green main and 5019ms here, breaching the 5s budget without its own semantic work changing. Cause is mine. The fast-lane witness imported v2.lens.complexity, v2.lens.cost and v2.std.refinement to execute the vacuity control, and no other witness under dag/test/claim imports them — so this file was the first to drag the v2 lens closure into the per-PR witness layer, and every discovered entry paid for it. Fix keeps ownership where it belongs: the control and its imports move to the long-lane companion, which already pays a large closure. No other lane's witness is relocated, and the long/ resident count does not grow for anyone else's code. Recorded as closure_cost_note rather than silently fixed: it is a measured instance of this program's own subject — a per-witness cost invisible until it lands on somebody else's budget, and a wall-clock threshold that reports the victim rather than the cause. Fast lane 9/9, long lane 10/10. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Enroll the orphan fixture helper (floor naming-hygiene refusal) The floor refused at the pre-plan naming walk: all_disposition_fixtures was a plain fn in a *_test.dag unreachable from any test fn — silent de-enrollment, which the enroll-or-refuse hygiene rightly stops. Fixed by making it load-bearing rather than deleting it. The new w_fixture_set_covers_every_work_kind folds over all six arm fixtures and asserts the set covers every one of the four work kinds, so an arm added without a fixture now leaves a kind uncovered and reds. The enumerated per-arm check states which arm maps where; this states the fixture set is complete over the work-kind space. Fast lane 10/10. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: cost analysis * Split the v1-importing control out of the dag/ long lane (compile-clean) Compile-clean refused with a precise diagnostic: dag/test/claim/long/v1_complexity_capability_census_resolution_test.dag:26:1: error: unresolved import: module 'v1.compiler.complexity' not found The distinction the failure taught, now measured rather than assumed: reaching v1 through decl_facts POOL ROOTS is fine for a dag/ entry — pools are read independently of walk source roots — but IMPORTING a v1 module from a dag/ entry does not resolve under compile-clean's scope. Only the executing eviction control needed the import. It moves to src/v2/test/manual/v1_complexity_eviction_hazard_test.dag, beside the existing v1-importing precedent (ownership_movable_test.dag imports v1.compiler.ownership from that same directory). The resolution census stays in the dag/ long lane and keeps resolving v1 DeclarationRefs through pool roots, with no v1 import at all. Verified in each file's real condition rather than a convenient one: resolution census 7/7 with only dag + src/v2 as walk roots — exactly compile-clean's condition, the one that failed; eviction control 3/3 with src/v1 added. Recipe rows updated for the split. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Remove the self-contradicting sentence from the long-lane exclusion row review 48510: the WitnessExclusionRow reason said the resolution file "carries the EXECUTING eviction control" and then, two sentences later, that the control "does NOT live here" and was homed to src/v2/test/manual/. Both were true at different points in this PR; only the second is true now. The opening sentence survived the split I made in the previous commit. Operators read that row to run the local recipe, so a stale sentence there misdocuments what the recipe covers — the same stale-prose class this census exists to make decidable, committed in the row describing the census. Removed rather than reworded: the correction already states the fact completely. Verified the row's --functions list matches the file exactly, 7 for 7. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: cost analysis * Give every witness an executing consumer (admission-wall refusal) The floor refused with WITNESS ADMISSION REFUSAL count=10 (10 UnclassifiedPathDeferral): enrolled witnesses excluded from discovery that name zero executing consumers. As of 2026-08-04 a directory is no longer an admission answer — moving a file under a long/ or offline path removes it from per-PR discovery and executes it NOWHERE. This is the exact defect this census argues against, committed by the census. I had said in prose that green CI proves nothing about these rows unless the local recipe ran; the substrate now refuses to accept that as an answer, and it is right to. Two fixes, each verified under the cadence's real source roots rather than a convenient set: - The 7 resolution/vacuity witnesses get exact function-grain rows in gunbc.explicit_witness_admission on FalsifierSubstrateLongLane — the declared lane for SubstrateInputsOnly witnesses over the fast-lane budget. Verified 7/7 on dag + src/v2, the lane's roots. - The 3 eviction witnesses move to src/v1/tests/claim/ and enroll on v1_claim_scoped_witness_entries, the only home with an executing consumer for a v1-importing witness (batch roots: dag + src/v1). Verified 3/3 on exactly those roots, without src/v2. Both earlier homes were refuted by the floor, not by argument: dag/test/claim/long/ failed compile-clean at the v1 import line, and src/v2/test/manual/ compiled but was refused by this admission wall. Also deletes the per-file OfflineLocalRecipe path row the exact admissions supersede — precedence is total (a function with an exact admission is decided by it), so keeping both would be the dual representation that carrier exists to remove. Fast 10/10, long 7/7, v1-scoped 3/3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Regenerate artifacts after merging main * WIP: cost analysis * C0(b1) recut: split role/destination/producer axes; separate residues from capabilities; narrow the distinctness claim to validated * Linearize the distinctness fold; record the wall-vs-cpu clock basis on the cost finding; regenerate * Replace a tree-copied residue count with an identity join (DESIGN §5 oracle rule) * Emit the stage0 artifact for the v1 eviction-hazard witness (self-host fixed-point) * WIP: cost analysis * Add the long-lane row separator comma (review 48680) * Replace the unknown-size claim with the measured disjoint-range result * Restore main's generated-artifact registrations dropped by the merge driver; re-derive the eviction row * WIP: cost analysis * WIP: cost analysis * Correct the b2 trigger: capability discovery is closed by neither b1 nor b2 * Resolve ci_layer_roots long-lane conflict: keep both row sets The merge of main (#7824, #7790, #7844) into this branch collided at the tail of falsifier_substrate_long_lane_rows — my seven C0(b1) census rows and main's two new rows append at the same list position. Both sides are kept; 39 rows, no duplicate (entry, function) pair, every entry file present on disk. The conflicted file was committed and pushed with markers intact by the autocommit path before this resolution, so this commit is the repair of that state, not a fresh merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: cost analysis * Regenerate ci.yml after the main merge; correct the ValueIdentity citation in parity section 6 The generated-artifact merge driver resolved .github/workflows/ci.yml to this branch's stale side when main was merged, silently dropping #7856's [ ! -f X ] -> ! [ -f X ] transposition at two floor-peak cgroup ascent sites. That form was already present at the merge base, so this was a revert rather than the branch being behind. Re-running the registered regeneration (generated_artifact_gate main_wet) restores it; ci.yml now differs from main by exactly the one AUTHORED_CONFLICTS entry this PR legitimately adds for its own generated eviction-hazard test. No rebuild was involved: the projection is interpreted from .dag at run time, so the existing binary emits the current form. The drift was solely the merge resolution never being followed by a regeneration. Also corrects a section 6 citation the C1 lane caught. ValueIdentity was cited as something the G1 cited-symbol work 'already makes resolvable'. It resolves to no declaration anywhere in the corpus -- it exists only inside the sibling note's proposed CostSubject / CostJustification code blocks. True of DeclarationRef, false of ValueIdentity: the DESIGN section 3 cited-symbol class, decidable by grep, sitting false in an authority doc while the mechanism it described stayed correct. Edited in the carrier; the md is regenerated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Resolve the main merge by hand: keep b2's landed work, restore this branch's three corrections An autocommit committed conflict markers from the origin/main merge and pushed them (64c0af2). This replaces that content with a real resolution; the merge commit itself is kept, so no history rewrite and no force-push. C0(b2) merged to main first, so main is authoritative for every shared carrier and this branch is stale on all of them. Resolution was therefore per hunk, not per side: v1_complexity_capability_census.dag - main wholesale, then re-apply the two note strings this branch corrected (c0_scope_note and complexity_capability_id_note: capability discovery is closed by NEITHER b1 nor b2). b2's algebra import, inventory_row_semantic_capability and concat rewrite are all kept. plans/v2_complexity_capability_parity.dag - main wholesale (it correctly records b2 DELIVERED ON MERGE and drops the now-closed C0(c) OPEN), then re-apply only the ValueIdentity citation correction. v1_complexity_capability_census_witness_test.dag - one differing line; this branch's measured disjoint-range cost result supersedes main's older its-actual-size-is-unknown wording. ci_layer_roots.dag - main wholesale. Verified by extracting (entry, function) pairs from both sides: the only rows this branch has that main lacks are the five direct_rust_door rows #7814 deliberately consolidated. Taking both sides would have duplicated seven b1 census rows that had already reached main through #7840. Three files were also silently reverted and are restored to main. The merge dropped #7865's std_unicode_types from the stage0 crate partition, and a regeneration run reverted #7864's witness_report_line from claim_batch.rs plus its instrument witness. claim_batch.rs is an emitted-code artifact whose generation runs through the emit path baked into the binary, and this binary predates #7864. Only the parity md needed regenerating, and that is an interpreted projection, so it is correct. Net diff against main is four files, five insertions, five deletions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop the self-referential citation in c0_scope_note (review 49160) c0_scope_note carried the parenthetical (see c0_scope_note) inside its own declaration. It resolved to nothing a reader could follow: the citation names the note containing it, and the capability-discovery explanation it points at is already spelled out a few sentences later in the same string. That is the DESIGN section 3 cited-symbol class -- a name-level claim a grep decides -- landing in the one note whose subject is honest, resolvable scope. The same PR fixes that class for ValueIdentity in the parity carrier, so leaving it here would have been inconsistent on the exact point the note makes. Dropped rather than repointed: the following sentences ARE the explanation, so a forward reference would restate the structure the string already has, and a positional pointer (see below) is the other half of what section 3 refuses. Swept the other two carriers in this PR for the same shape -- a data note whose body names its own declaration -- and found none. --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
What this is
The follow-up #7837's
witness_row_cost_clock_mismatch_notedeclared — dissolved in place rather than left as a note.#7837 grew a cross-clock refusal on the
.dagcomparator, and the production falsifier cadence could not reach it. The seed called onlywitness_row_cost_exceeds_basis— the bare ratio predicate — and rebuiltDriftExceeded/WithinBasis/BasisAbsentas Rust string literals. Two defects in one shape:WitnessRowCostVerdict, andThat comparison was correct only because both sides happened to be wall — a fact about the producers, not a property of the mechanism, and nothing about its greenness depended on the mechanism being right.
Three parts, the third load-bearing
1. Both basis files carry a required per-row
clockcell. An unstated clock refuses at parse; an unmodelled one (monotonic) refuses too. Never a default to wall — that would be right for every row today and silently wrong the first time someone seeds from a CPU receipt, which is the exact failure the column exists to prevent. The 1176 existing rows are stampedwallbecause that is what they are: before the ruling the seed'sPerformanceReceiptheld onlywall_nanos. Grounding is stated in the file header, not assumed.2. The seed calls the authority.
witness_row_cost_seed_verdict_dated/_undated, and it renders the arm the authority named. It constructs no carrier — theOptionalstays inside.dag, and whether a dated basis exists is the map lookup the seed already had (data presence, not judgement). Same disciplinewitness_cost_timed_out_seed_deferral_notealready states for this seam.3. The Rust arm reconstruction is DELETED, not kept beside the carrier. An arm added to
WitnessRowCostVerdictnow reaches the cadence receipt with no Rust edit.BasisClockMismatchis counted on its own summary line because its remedy differs fromBasisAbsent's — fix the producer handing over the wrong clock, versus seed the missing row. Absorbing it into either neighbour would zero its frequency by construction.Both comparators move together: the compile-clean cost drift shares this parser and authority by design, so leaving it on the old predicate would have forked what it was built to share.
Green by execution, and the discrimination named
drift_verdicts_come_from_the_authority_and_a_cross_clock_basis_refusesparse_witness_row_cost_basis_line_requires_srv_fleet_arm64committed_witness_row_cost_basis_loads_and_excludes_the_censored_rowThat first test is the only consumer that crosses this Rust seam at all — the
.dagwitnesses cannot reach it, and the parser tests only show the cell is read. Worth stating because the same blind spot produced the defect review 48651 caught on #7837: nextest was removed from CI on 2026-07-11, so this class is reachable only by runningcargo testdeliberately.What stays seed-side, deliberately
ObservationAbsent— a row that never executed. An absent observation has no counterpart inWitnessRowCostVerdict, and giving it one would let a row with no measurement reach a comparator at all. The seed keeps deciding comparability before comparing.Still open
The
eval_cpu_mscolumn on the row-cost TSV. #7820 renamedeval_ms→eval_wall_msso the column is unambiguous when it arrives, and #7837's row now carries both clocks so it has something real to read rather than a fabricated zero. It is not in this diff.