Repository navigation
Give the row-cost receipt its CPU column, beside the wall one - #7845
Merged
Merged
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>
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>
gunbai-bot
Bot
force-pushed
the
session/merry-raven-690-cpu-column
branch
from
August 5, 2026 09:48
a66c354 to
f7150fd
Compare
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
added 3 commits
August 5, 2026 15:37
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.
briansrls
pushed a commit
that referenced
this pull request
Aug 5, 2026
Integrate main through #7845 before re-running compile-clean gate.
gunbai-bot Bot
pushed a commit
that referenced
this pull request
Aug 5, 2026
…elds #7845 replaced WitnessRowCost's tuple shape with named fields and inserted eval_cpu_nanos in the middle, so every positional index in this branch's new code shifted: .0/.1/.2/.5 are entry/function/eval_wall_nanos/outcome. Merging main migrated the pre-existing call sites; these six were the residue this branch adds. The skip test now calls row_measurement_is_absent(&row.outcome) rather than comparing the outcome string inline. Same behavior — that helper tests exactly selection-skipped — but it is the existing authority for the question, and the inline compare was a second copy of it (DESIGN section 3). TimedOut rows still fall through to be measured, which is deliberate: they are the population this disclosure exists to surface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls
added a commit
that referenced
this pull request
Aug 5, 2026
…ived from the existing witness row-cost receipt, with promotion-to-refusal as its declared trigger (#7862) * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * Bind the two import-less plan sketches from their definers (unblocks this PR's compile-clean) Not this PR's defect. dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag are the only two of ~46 table-using modules under dag/gunbc/plans/ carrying no imports at all, so their cross-module names bind by pool coincidence (DESIGN #6985 Class B). This PR touches claim_executor.rs, and a non-selectable .rs path forces compile-clean to the whole-tree baseline, which compiles them; main pushes take the scoped path and never do. Same change as #7872 (authored off main). Carried here so this PR can go green without waiting for that to merge; when it does, the identical lines merge clean. Verified by execution: both modules compile with 0 blocking errors. Two imports are required, not one — adding md_helpers alone flips each module from ambient bare resolution to import-scoped visibility, which then refuses Plan/HasTrigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Migrate the migration-disclosure receipt to WitnessRowCost's named fields #7845 replaced WitnessRowCost's tuple shape with named fields and inserted eval_cpu_nanos in the middle, so every positional index in this branch's new code shifted: .0/.1/.2/.5 are entry/function/eval_wall_nanos/outcome. Merging main migrated the pre-existing call sites; these six were the residue this branch adds. The skip test now calls row_measurement_is_absent(&row.outcome) rather than comparing the outcome string inline. Same behavior — that helper tests exactly selection-skipped — but it is the existing authority for the question, and the inline compare was a second copy of it (DESIGN section 3). TimedOut rows still fall through to be measured, which is deliberate: they are the population this disclosure exists to surface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> 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>
briansrls
pushed a commit
that referenced
this pull request
Aug 6, 2026
…pt-index long-lane row (#7880) * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * WIP: Make the 500ms mandatory-migration threshold a counted disclosure derive * Bind the two import-less plan sketches from their definers (unblocks this PR's compile-clean) Not this PR's defect. dag/gunbc/plans/branch_merge_admission_model.dag and merge_admission_gate_shape_proposal.dag are the only two of ~46 table-using modules under dag/gunbc/plans/ carrying no imports at all, so their cross-module names bind by pool coincidence (DESIGN #6985 Class B). This PR touches claim_executor.rs, and a non-selectable .rs path forces compile-clean to the whole-tree baseline, which compiles them; main pushes take the scoped path and never do. Same change as #7872 (authored off main). Carried here so this PR can go green without waiting for that to merge; when it does, the identical lines merge clean. Verified by execution: both modules compile with 0 blocking errors. Two imports are required, not one — adding md_helpers alone flips each module from ambient bare resolution to import-scoped visibility, which then refuses Plan/HasTrigger. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Follow-up to #7872: the std.markdown symbols were still binding by coincidence review 48984, on the merged #7872, is correct and my completeness claim there was not. Both plan sketches still referenced MarkdownBlock, TableBlock and AlignNone with no std.markdown import, so those three kept binding by pool coincidence — the same #6985 Class B pathology #7872 exists to close, left in place by the change closing it. THE BAD INFERENCE, named because it is the trap and not a slip: I read "0 blocking error(s)" as "every name binds from a declared import". It does not. Bare resolution still answers for whatever the closure happens to contain, so a clean compile is precisely the evidence that CANNOT separate a declared binding from a coincidental one — the compiler is green either way. Only reading the file against its own import list decides it, which is what the reviewer did and I had not. Verifying the fix by the same instrument that was blind to the defect is a DESIGN §5 specification-without-execution failure wearing an execution costume. Symbol set verified against std.markdown's 34 exports this time rather than inferred from a clean compile: these two modules use MarkdownBlock, TableBlock and AlignNone and nothing else from it. Byte-identical to the most common sibling form, carried by 18 plan modules including the three #7872 cited as precedent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Migrate the migration-disclosure receipt to WitnessRowCost's named fields #7845 replaced WitnessRowCost's tuple shape with named fields and inserted eval_cpu_nanos in the middle, so every positional index in this branch's new code shifted: .0/.1/.2/.5 are entry/function/eval_wall_nanos/outcome. Merging main migrated the pre-existing call sites; these six were the residue this branch adds. The skip test now calls row_measurement_is_absent(&row.outcome) rather than comparing the outcome string inline. Same behavior — that helper tests exactly selection-skipped — but it is the existing authority for the question, and the inline compare was a second copy of it (DESIGN section 3). TimedOut rows still fall through to be measured, which is deliberate: they are the population this disclosure exists to surface. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Dissolve the concept-index long-lane row by fixing the witness's cost The witness's cost is its POOL, and the pool was 638 files. concept_index_enumeration_pool_roots was "src/v2/test/claim", and concept_decl_facts parses every .dag under the root on every call, so each parse-only witness parsed 638 files / ~3.0 MB and grew with every unrelated module added anywhere beneath it. That is precisely what the SubstrateLongLaneRow recorded ("corpus-breadth cost grows with unrelated modules in the pool") and what pushed witness_coproduct_arms_parse_only to 6065ms thread-CPU against the 5000ms fast-lane budget, rehoming it to test/claim/long/ under #7756. Breadth was never the subject. Every assertion names ONE concept by qualified name and checks its extracted fields, so the requirement is a pool CONTAINING those concepts, and the smallest pool that crosses the boundary is a directory of its own (operator ruling 2026-08-04: a witness's size is DERIVED from what it proves, never chosen for verisimilitude). src/v2/test/fixture/concept_index_pool is that pool. MEASURED, same host, same binary, toggling only the .dag source: witness_coproduct_arms_parse_only 3952ms -> 2ms whole 11-witness family, slowest 51ms (was ~4000ms for parse-only rows) All 11 pass, including the returned witness. The pool is proven non-vacuous rather than merely quiet: witness_parse_only_extract_nonempty_in_scoped_pool asserts the pool is non-empty AND contains the target, and witness_parse_only_extract_reflects_perturbed_field_type reads RecordPerturb's beta: Int out of the fixture — so the stale-field RED control cannot be passing because the pool is empty. WHY THE TYPES DID NOT ALL MOVE. The two witness families consume different inputs: concept_decl_facts_live reads the loaded module REGISTRY, concept_decl_facts reads FILES under a root. The live-registry witnesses keep local declarations (a locally-declared record IS their subject); the parse-only witnesses read the fixture pool. That is two inputs to two mechanisms, not one concept forked. A CHANGE THAT DID NOT EARN ITS PLACE ON THIS WITNESS, kept and labeled rather than quietly credited: enumerate_concepts_from_decls folded with list_snoc_item, which is list_append(xs, [item]) and therefore O(n^2) over the decl count. It is replaced with list_map (fold_list_right + Cons, O(n), order-preserving, identical output). Measured effect on this witness: 3952ms -> 3795ms, ~4%, inside noise — because the dominant cost was the host-side pool parse, not the fold. It stays because it is a proven cost-shape defect on a function enumerate_concepts() also calls corpus-wide (DESIGN section 6: fixed regardless of the realized n), NOT because it fixed anything here. My first hypothesis was that this fold WAS the cost; measurement refuted it, and the pool root was the answer. Dissolves: the SubstrateLongLaneRow, the long/ file, and coproduct_arms_parse_only_long_lane_note, all deleted together per the row's own trigger ("eval lands under gunbc_ci_fast_lane_witness_eval_budget on a measured cold run and re-enrolls per-PR discovery"). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: shell -> dag (and TS -> dag) * Drop the stale concept-index parse-only basis row invalidated by this branch witness_coproduct_arms_parse_only carried a dated basis of 3850ms from run 30550328673, measured when concept_decl_facts parsed all 638 files under src/v2/test/claim. Narrowing the pool to the witness family's own directory takes the same witness to ~1.5ms, so that basis is a measurement of a different implementation and no longer a reference for this one. Leaving it is not neutral: the drift comparator is a 2x ratio, so a 3850ms basis pins this row WithinBasis below 7700ms forever and the drift gate goes vacuous for it exactly where a future regression would show up. That is the failure committed_witness_row_cost_basis_loads_and_excludes_the_censored_row already guards against for the 900794ms censored row, in the same file. Dropped rather than re-signed: witness_row_cost_basis_host_class_note requires basis rows to be signed from a cited arm64 srv-fleet run, never a local measurement, and this container is x86. BasisAbsent is the honest third state (typed and counted, per witness_row_cost_spine_note) until the next fleet cadence re-signs it. Drift is falsifier-cadence counted and not merge-refusing, so this changes no gate verdict. 1190 rows remain, over the >=1000 floor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
The last piece of the 2026-08-05 clock-basis ruling that still had a real consumer gap. #7820 renamed
eval_ms→eval_wall_ms, #7837 made the row carry both clocks — and nothing printed the second one, so the remedy that second clock exists to discriminate could not be read from the artifact at all.The tuple becomes a struct, and that is not tidying
Vec<(String, String, u128, u128, u128, String, String)>→WitnessRowCost.A positional tuple is how
evalcame to mean "wall" by index and nothing else — the same defect one layer below theObservationEvent.wallfield name this lane retired. It is also exactly what would have turned a second clock into "the thirdu128".The column
eval_cpu_mssits immediately besideeval_wall_ms— asserted by the test, not left to convention — so an author reads the remedy from one file without joining another:It is not a second threshold. The witness threshold is stated on wall (operator ruling); CPU is the remedy discriminator, which is the only thing that earns a second clock a column.
An unsampled clock renders
unmeasured, never0A
0there 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 theoutcomecolumn already closed, one column over.Green by execution, discrimination proven
witness_row_cost_receipt_distinguishes_unexecuted_from_sub_millisecondgains a wall-only fixture and goes RED when the renderer is changed tounwrap_or(0), failing on the exact fabricated cell:It also asserts the two clocks are independent carriers — 500µs wall against 300µs cpu, so a producer filling both columns 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.CI note
The
cijob on this stack is red on two pre-existing main-red witness failures, not on anything in these diffs. Split and evidence in #7846 (which repairs one half; #7842 / #7843 already cover the other).