Repository navigation
Required CI: the measuring process adjudicates the receipt it writes, so a refused phase reaches the exit - #11861
Conversation
… so a refused phase reaches the exit claim_executor --required-ci maps phase outcomes to a process exit in two places. Without --measurement-receipt it refuses on a non-empty phase-failure set. WITH the flag it wrote the receipt and returned ExitCode::SUCCESS unconditionally, because the D0 design it was written for published the receipt and let a separate step adjudicate it. gunbc#11791 restored a floor job carrying that receipt-bearing command into a workflow with no adjudicating step, so the measuring process became the only authority left standing on a route where it had been built to decide nothing: runs 35503853026 and 35510547600 both printed `FAILED PHASE floor refused: ... ChangedWitnessObservationFailed` and concluded success. The refusal itself is correct and is untouched. What changes is only the exit status: the measuring process now adjudicates the FILE it just wrote -- readback, JSON transport and version agreement all inside the verdict -- and reaches the exit through the same function --adjudicate-measurement-receipt uses. One relation, one exit. A second leak in the same branch, found by the audit the first one forced: the blocker set written into the receipt was synthesized by comparing a blocker's PHASE to the whole failure SENTENCE, and the failure spelled exactly `floor` was exempted by name, so a floor reporting not-clean while yielding no blockers of its own produced a COMPLETED measurement with an EMPTY blocker set. Phase word against phase word now, no exemption. The receipt types and the admission relation move to v1_compiler::cli_run::required_ci_measurement so the relation has an executing discriminating red -- a completed measurement carrying one blocker must never be admitted, run through the write and the readback rather than asserted against a string -- plus its green control, on the one Rust route the repository documents (`cargo test --release -p v1-compiler --lib`). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…an losing them The convergence lane is winding down so the fleet can prioritise v1 performance and v2 migration. Five subjects it found are unfinished and none of them has a home outside a session transcript, so they are declared here with the measurements that produced them rather than a summary of them. - claim-entry-resolution-population: 8 claim entries cannot resolve for a closure gap and 20 more cannot typecheck at all, from 17 sites, EIGHT of them in production modules including dag/std/algebra.dag. The floor is green over all of them, because an entry that fails to resolve is indistinguishable there from one never selected. The counts are a partial census (512 of 1582, sorted prefix) and the row says so rather than extrapolating a rate. - compiler-import-list-binds: the flip control takes the subject from 41 registry-row-absent causes to 585 modules with one host-loader predicate removed; the alternative widen costs 358442 -> 586388 closure rows, moves 1502 of 1582 entries and charges every already-correct entry. 646 files are bare-eligible, which is the transition scope. The fork is the operator's, so the row carries both costs rather than a preference. - boot-probe-must-not-read-a-bare-124-as-a-deadline: executed on coreutils 9.7, timeout forwards a child's own 124 (6ms, no expiry) and returns 124 on expiry (111ms), so boot_probe_verdict's bare-status reading renders a deadline sentence for an ordinary VMM failure. Contained only by its consumer refusing both verdicts. - fleet-srv2-retirement-completion and fleet-assessment-build-provenance-join: what remains of srv2 -- seven local slot trees, two live registrations (251463, 251484; 91529 and 91513 are already absent by per-ID read), the plan/apply spine reaching a target that is not the executor, graceful retirement, and the provenance join the assessment consumes as a blocker. NOT filed here: the required lane concluding success over its own refused phase. #11857 already declares that subject as required-lane-exit-on-refused-phase and #11861 implements it, so a second row would be the DESIGN section 3 fork. The rows carry receipts, not adjectives: each names the run, the command or the measured pair that established it, so the next lane re-derives rather than re-discovers. ROADMAP.md is a projection of this authority and regenerates from it; the host is too loaded to run that regeneration here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Operator wind-down (2026-09-20): step back to v1 performance and v2 migration; record progress and remaining items as project items. - action-use-yaml-reader-contract: the bounded-subset YAML contract and the deletion of the action-use line projection (#11730, held). - required-lane-exit-on-refused-phase: the required lane exits 0 on a refused phase, with runs 35503853026 and 35510547600 as receipts (#11861). - workflow-census-claim-budget-margin: cut the reader's per-entry cost so the census is not one unrelated workflow edit from red. - action-runtime-epoch-observation: nothing reads the epoch date against a clock, and a runner-host override is unobserved. - namespace-relocation-batch-grain: one relocation should not cost one admission file per consuming declaration. ROADMAP.md regenerated through gunbc.roadmap_authority expected_roadmap_md. HISTORY NOTE: this branch is rebuilt on origin/main. The previous head carried a merge made with -s ours, which recorded main as merged while keeping this side of every file -- silently reverting main's changes in 17 unrelated files. That merge is discarded rather than fixed forward, so nothing of main's is lost. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Operator wind-down (2026-09-20): step back to v1 performance and v2 migration; record progress and remaining items as project items. - action-use-yaml-reader-contract: the bounded-subset YAML contract and the deletion of the action-use line projection (#11730, held). - required-lane-exit-on-refused-phase: the required lane exits 0 on a refused phase, with runs 35503853026 and 35510547600 as receipts (#11861). - workflow-census-claim-budget-margin: cut the reader's per-entry cost so the census is not one unrelated workflow edit from red. - action-runtime-epoch-observation: nothing reads the epoch date against a clock, and a runner-host override is unobserved. - namespace-relocation-batch-grain: one relocation should not cost one admission file per consuming declaration. Rebuilt on current main (other lanes keep appending nodes at the same point); ROADMAP.md regenerated through gunbc.roadmap_authority expected_roadmap_md. Verified like for like: main 51 PASS, mine 51 PASS, identical FAIL set, 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Operator wind-down (2026-09-20): step back to v1 performance and v2 migration; record progress and remaining items as project items. - action-use-yaml-reader-contract: the bounded-subset YAML contract and the deletion of the action-use line projection (#11730, held). - required-lane-exit-on-refused-phase: the required lane exits 0 on a refused phase, with runs 35503853026 and 35510547600 as receipts (#11861). - workflow-census-claim-budget-margin: cut the reader's per-entry cost so the census is not one unrelated workflow edit from red. - action-runtime-epoch-observation: nothing reads the epoch date against a clock, and a runner-host override is unobserved. - namespace-relocation-batch-grain: one relocation should not cost one admission file per consuming declaration. Rebuilt on current main again (sixth time: other lanes keep appending nodes at the same point). The five rows are byte-identical to the head verified at d5dc91b -- main 51 PASS, mine 51 PASS, identical FAIL set, 0 errors -- and ROADMAP.md is regenerated on this head through expected_roadmap_md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…fabric storage wire witness (#11967) `dag/test/claim/fabric/fabric_storage_wire_witness_test.dag` carried three `//` blocks INSIDE the body of `a_presented_login_crosses_the_wire_as_that_login_and_absent_as_absent`. DESIGN §4c admits only standalone leading blocks attached to a module-scope declaration, so the file refuses and, because one witness compile error refuses the whole floor, every required floor run on main is red. The three sentences are merged into the declaration's existing leading block. That is a widening of scope, not a verbatim move -- an annotation's subject is the declaration it attaches to -- and it is honest here because the function exercises exactly the grammar and single-line cases the sentences describe. Evidence, at this head: the module now typechecks and the claim evaluates to `true`; the only refusal left is the `ProcessExit` wrapper that every `-> Bool` claim fn gets under `gunbc run --function`. On origin/main the same invocation refuses at the annotation. This is the SECOND regression of a class already repaired twice (#11875, #11907). Repairs treat instances; the supply is the required lane exiting 0 on a refused phase, which is #11861. Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… phase word (review 69681) The fix for the empty-blocker-set leak over-corrected. It deduped the synthesized blockers BY PHASE WORD, and the phase words are not unique across the failure list: `generated-artifact` carries six distinct sentences and `regen-fixed-point` four, so every cause after the first in each phase was dropped from the receipt the separate `--adjudicate-measurement-receipt` consumer reads. The exit stayed non-zero because the set stayed non-empty, which is exactly why nothing caught it -- the status was right while the located diagnostic was gone. That contradicted this diff's own stated invariant and the ledger row's claim, both of which are corrected here rather than restated. THE RULE THAT SURVIVES BOTH DEFECTS. A failure sentence carrying its own cause is its own located diagnostic and always reaches the set; only an EXACT duplicate cause is suppressed. A failure spelled exactly as the bare phase word is a SUMMARY of blockers that phase already minted in full, so it is suppressed only when that phase actually has some -- and published when it does not, which is what keeps the original leak closed. The old predicate held only the first property; its repair held only the second. The fold moves into the library as `synthesize_phase_blockers` with five controls, because it has now been wrong twice in two directions and neither was visible from the process status. Mutation-verified: restoring the phase-word dedupe reds 2 of the 11. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Addressed in Confirmed: The rule that survives both defects, rather than a revert to the old predicate (which held only the first property, as its repair held only the second):
Made executable. The fold moved to the library as Mutation-verified: restoring the phase-word dedupe gives I also corrected the ledger row, which claimed "every one of them now reaches the blocker set." That was false as written; it now records the miss with its review id instead of restating the claim. — sent from still-crane-198 |
What
claim_executor --required-cimaps phase outcomes to a process exit in two places. Without--measurement-receiptit refuses on a non-empty phase-failure set. With the flag it wrote the receipt and returnedExitCode::SUCCESSunconditionally — because the D0 design it was written for published the receipt and let a separate step adjudicate it.So the lane printed a complete, typed, located refusal and then answered success:
…with the step and the job both
conclusion=success. Verified against the GitHub jobs API, not only the log: run 35503853026 (head cb39f95, floor job 106060214538) and run 35510547600 (head e78927a, floor job 106077573881).The refusal itself is correct and is untouched. When a changed kernel file such as
dag/std/types.dagmakes the base side impossible to reconstruct, the changed-witness sublane declines to plan rather than widening to everything or narrowing to nothing. What was wrong is only the exit status and what the PR view was told.The two repairs
1. The write is not the verdict. The measuring process now adjudicates the file it just wrote and returns that verdict, reaching the exit through the same function
--adjudicate-measurement-receiptuses. One relation, one exit. Readback, JSON transport and version agreement are all inside the verdict, so a receipt that serialized its blockers away is a refusal rather than a pass.2. A second leak in the same branch, found by the audit the first one forced. The blocker set written into the receipt was synthesized from the phase-failure list by comparing a blocker's phase to the whole failure sentence, and the failure spelled exactly
floorwas exempted by name. So a floor reporting not-clean while yielding no blockers of its own produced aMeasurementCompletedreceipt with an empty blocker set — a failed phase with nothing to adjudicate, i.e. a green built by construction. The test is now phase word against phase word, and no phase is exempt.Audit of the lane's other refusal arms: all 22 appends to
phase_failures(lane-roster, parse, generated-artifact stage0-mirrors / docs-projections / carrier / unadjudicated, regen-fixed-point incl. its unmeasured and refused arms, dag-artifact-identity incl. subject-unobtainable, floor incl. floor-refused, lane-roster ran-set, source-root ingest receipt) now reach the blocker set, and the blocker set is what the exit is derived from. One arm is deliberately not a phase and stays as it is:--measurement-unreached-receiptseals aMeasurementUnreachedstanding for a separate adjudicator to read, and that standing is typed non-admitted — it says so in the receipt rather than by an exit.Compatibility
This is the seed-side half and it depends on neither #11829 nor #11836; it is correct under either. It takes no position on which should land.
Evidence
v1_compiler::cli_run::required_ci_measurement. Six tests; the pair that matters is a completed measurement carrying one blocker is never admitted and a clean one is, each also run through the write and the readback. Mutation-verified: forcing the blocker arm to returnAdmittedreds 2 of the 6 and leaves the green controls green.cargo test --release -p v1-compiler --lib(gunbc.repo_self_buildrepo_self_test_command) — 6 passed. This is why the receipt types moved out of the binary:gunbc.rung_droprust_unit_tests_off_the_merge_pathalready declares that no CI step runs it, and a#[cfg(test)]module beside the binary has no documented route at all. The rung is stated honestly in the failure-mode row rather than claimed at the merge path.cargo clippy --all-targets -p v1-compiler -- -D warnings: clean.cargo fmt --all --check: clean.The discriminating control, on real CI
Not planned — it arrived while this PR sat red, and it is the comparison the unit controls cannot make.
106103511181(run 35520456015, queue branch for pr-11769)source annotation sits inside a declaration bodyphases_run=2 phases_failed=2106102498242(run 35520066541, head 9ae301c)phases_run=2 phases_failed=2It then reproduced on a second, unrelated cause. After #11875 repaired the annotations, parse went clean (
6455 file(s) parse-clean) and the declarations sub-check began refusing two different things that had landed on main (IMPORT-MEMBER-ABSENTindag/test/claim/machine_intake/jade_first_contact_model_witness_test.dag, from #11758;LENS-AUTHORSHIP-ABSENTinsrc/v2/lens/reference_derived_residency_reading.dag, from #11740). Queue floor job106184155659(run35550476069, queue branch for pr-11676) carried both diagnostics and concluded success; job106184184120(run35550463080, head5e1a5035a44), this branch with the same two diagnostics, concluded failure.And the green control arrived too. On head
46a4a6306f2, once main was clean, run35645340055floor job106484305229passed in 39m31s with the lane exiting 0 — so the pair is complete on live CI: a refused phase reds (twice, on two unrelated corpora), and a clean lane greens.Same corpus, same refused phases, opposite verdicts. That is a real red and a real green of the mapping on live CI — which no unit test in this repository could have produced, because the thing under test is a process exit read by a CI job.
Two consequences worth stating plainly:
FloorClean(planned=401 executed=401 claims_failed=0); it refuses because main's parse phase is refusing. It cannot go green until main's parse is repaired, and that repair is not this PR's to author — it is open separately as Main repair: hoist three in-body annotations to their module items (parse refuses fleet-wide) #11875, after which this branch takes one merge and one re-run.success, so commits are being admitted to main by a required gate that declined every phase it ran. That is a plausible mechanism for main having broken twice in one afternoon: the breakages land green.An earlier draft of this section claimed a red on this PR as evidence the fix worked. That was wrong when written — the only comparison available then failed identically with and without the change — and it is replaced by the table above rather than quietly dropped.
Blind window, stated as what the emission shows
--measurement-receiptappears zero times in the workflow emitted at85c1356300c(#11742). gunbc#11791 (merged 2026-09-20 05:18 UTC) restored a floor job carrying the receipt-bearing command into a workflow with no adjudicating step. So the window opens there and not earlier; within it, a required run whose floor phase refused reported green with its changed-witness observation never made. Two such runs are named above. No claim is made about how many others fell in it.Ledger
dag/gunbc/recurring_failure_mode/gate_reported_success_on_a_phase_it_refused.dag— the general class (a gate reporting success on a phase it refused), with both runs as receipts, rung found at mitigatable, rung now mechanically preventable with the honesty bound stated, ceiling structurally impossible, and a next-rung trigger naming the capability (the lane's phase-outcome-to-exit decision as a.dagfold returningstd.processProcessExit). It is bounded explicitly against #11836'smeasure_mode_command_emitted_into_a_lane_with_no_adjudicatorrather than duplicating it: that class is about an emission and its wall is at the emitter; this one is about what the instrument returns when nothing adjudicates.🤖 Generated with Claude Code