Repository navigation
Wire the merge-admission producers into --required-ci, and make a green certificate over a red run unrepresentable - #8752
Conversation
…en certificate over a red run unrepresentable
WHAT THIS CLOSES. gunbc.merge_admission already models the wall that would have
refused the merge behind the 2026-08-21 main-floor red: classify_merge_admission_verdict_v2
compares the receipt's tested base tree against the current merge target tree and
answers MergeDeniedStaleBase ("stale base tree -- re-run CI against current main").
Nothing invoked it, because nothing minted its inputs. The module says so itself, at
merge_admission_current_context_staging_note: the entry "can fetch the current merge
target, read attempt-scoped TestedSubject and MergeAdmissionReceiptV2 wires, and
classify them ... but no production path invokes the entry and no production path mints
either V2 wire."
This lands the two producers that merge_admission_v2_production_wires_dissolution_trigger
names, as PHASES INSIDE --required-ci rather than workflow steps -- the 2026-08-20
operator directive puts these "within the witnesses step and within the gunbc binary,
not at a github actions job level".
PHASE 0 merge-admission-capture, ahead of every other phase. The subject is what the
run is ABOUT, and it has to exist before anything is tested: afterwards the
only remaining account of it is the receipt's own claim, and a receipt that
both states and certifies its subject can restate it. This is exactly the
independence merge_admission_subject_binding_note requires ("three bindings
are therefore required BEFORE any freshness question").
PHASE 7 merge-admission-stamp, after the floor, carrying THIS RUN'S conclusion.
IT IS NOT PURE WIRING, AND THIS IS THE PART THAT MATTERS. tools.merge_admission_walk
stamp_tested_floor writes `conclusion: Success` as a LITERAL. That was not a defect
while it ran: its safety came from an ordering law held outside it, declared by the
WalkPlan -- "stamp is reachable only after the whole ordinary floor and its
finalization passed" -- so the constant could only be written over a run that had in
fact passed.
THE FLOOR CUT DELETED THE WALKPLAN. The constant survived; the law that made it true
did not. Calling it from a new site would mint a receipt certifying Success over a red
run -- a fabricated plausible output (DESIGN §5) aimed at the merge gate, the one
consumer that must never be lied to, and undetectable downstream because a receipt is
believed exactly to the extent that it is well-formed.
So the conclusion becomes an OPERAND. stamp_tested_floor_with_conclusion takes it;
stamp_tested_floor_for_exit_code routes an exit code through the existing
gunbc.merge_admission_produce floor_exit_to_check_conclusion rather than re-deciding
what a zero exit means; the zero-argument stamp_tested_floor is retained for the
existing success-stage claim, where the constant is still true by that stage's own
reachability. A green certificate over a red run stops being something a caller can
produce by forgetting an ordering rule and becomes something it would have to state --
the §4b climb from mitigatable toward structural.
FAILURE ARMS, none of which widen:
- absent walk-attempt identity is a reported SKIP, not a pass and not a failure. The
identity derives from GITHUB_RUN_ID + GITHUB_RUN_ATTEMPT + GITHUB_JOB, so the arm
is unreachable on CI; off CI there is no merge attempt and therefore no subject.
This is phase 5's NoSubject shape, not phase 3's.
- every OTHER capture refusal -- head unreadable, base tree unreadable, unparseable
oid, attempt dir, write -- fails the phase, classified from the producer's own
typed refusal wire rather than guessed.
- no subject means no receipt, and that is fail-closed rather than a gap: the gate
refuses on a missing wire ("floor-receipt wire missing"), so declining to stamp
cannot admit anything.
NOT IN THIS CHANGE, DELIBERATELY: gunbc.ci_failure_class merge_freshness_gating_status
stays GatingComputedDeferred. Flipping it to GatingEnforced converts every in-flight
branch the moment it lands and is gated on operator sign-off, so it belongs in its own
change with a single subject.
RECEIPTS. Remote release build of claim_executor: CARGO_EXIT=0 with `Finished release
profile`, against a must-fail control in the same dispatch (a nonexistent bin) that
returned 101 -- so a real compiler was reached, not a cached no-op. `gunbc compile` on
dag/tools/merge_admission_walk.dag: 0 `source annotation` diagnostics and no errors.
The phases themselves are exercised by CI on this PR, which is the first run that has
both producers in it.
2d33177 to
cc259ef
Compare
|
Execution receipt from this PR's own run (32467142304) — the first run containing both producers. Green alone would not establish that they ran, so the log lines: The subject wire landed at the attempt-scoped path carrying the real run id ( What this receipt does NOT establish, stated rather than left to be assumed. The run was green, so The honest next-rung trigger is the first red — sent from bold-pike-155 |
…PILING it One .dag conflict (merge_admission_walk) taken from main and recut, 61 qualified, 0 refused, then the post-integration fixup pass applied. bin/claim_executor.rs auto-merged again with no conflict. It is hand-maintained, so an ordinary merge is correct -- but the LAST clean auto-merge of this exact file produced a hybrid that referenced main's call sites without their definitions and failed to compile with 3 errors. A clean merge is not evidence of a coherent file, so this one was verified by execution: cargo check -p v1-compiler --bin claim_executor passes. Invariants: imports tree-wide 0, conflict markers 0, entry resolves clean.
What this closes
gunbc.merge_admissionalready models the wall that would have refused the merge behind the 2026-08-21 main-floor red:classify_merge_admission_verdict_v2compares the receipt's tested base tree against the current merge target tree and answersMergeDeniedStaleBase— "stale base tree — re-run CI against current main".Nothing invoked it, because nothing minted its inputs. The module says so itself, at
merge_admission_current_context_staging_note: the entry "can fetch the current merge target, read attempt-scoped TestedSubject and MergeAdmissionReceiptV2 wires, and classify them … but no production path invokes the entry and no production path mints either V2 wire."This lands the two producers
merge_admission_v2_production_wires_dissolution_triggernames, as phases inside--required-cirather than workflow steps — the 2026-08-20 operator directive puts these "within the witnesses step and within the gunbc binary, not at a github actions job level".merge_admission_subject_binding_noterequires ("three bindings are therefore required BEFORE any freshness question").Why it is not pure wiring — the part that matters
tools.merge_admission_walkstamp_tested_floorwritesconclusion: Successas a literal. That was not a defect while it ran: its safety came from an ordering law held outside it, declared by the WalkPlan — "stamp is reachable only after the whole ordinary floor and its finalization passed" — so the constant could only ever be written over a run that had in fact passed.The floor cut deleted the WalkPlan. The constant survived; the law that made it true did not. Calling it from a new site would mint a receipt certifying
Successover a red run — a fabricated plausible output (§5) aimed at the merge gate, the one consumer that must never be lied to, and undetectable downstream because a receipt is believed exactly to the extent that it is well-formed.So the conclusion becomes an operand:
stamp_tested_floor_with_conclusiontakes it, andstamp_tested_floor_for_exit_coderoutes an exit code through the existingfloor_exit_to_check_conclusionrather than re-deciding what a zero exit means. The zero-argumentstamp_tested_flooris retained for the existing success-stage claim, where the constant is still true by that stage's own reachability. A green certificate over a red run stops being something a caller can produce by forgetting an ordering rule and becomes something it would have to state — the §4b climb from mitigatable toward structural.Failure arms — none of which widen
GITHUB_RUN_ID+GITHUB_RUN_ATTEMPT+GITHUB_JOB, so the arm is unreachable on CI; off CI there is no merge attempt and therefore no subject. This is phase 5'sNoSubjectshape, not phase 3's.Deliberately not in this change
gunbc.ci_failure_classmerge_freshness_gating_statusstaysGatingComputedDeferred. Flipping it toGatingEnforcedconverts every in-flight branch the moment it lands and is gated on operator sign-off, so it belongs in its own change with a single subject.Receipts
claim_executor:CARGO_EXIT=0withFinished release profile, against a must-fail control in the same dispatch (a nonexistent bin) returning101— so a real compiler was reached, not a cached no-op.gunbc compileondag/tools/merge_admission_walk.dag: 0source annotationdiagnostics, no errors.Diff hygiene note: the first push of this branch accidentally reverted #8743 by copying a working file onto a newer
origin/main. Caught from the diffstat (290 deletions for a change that adds ~126 lines), corrected by replaying only this change's own hunks onto current main, and re-verified:claim_executor.rsis now +126 / −0. The compile receipt above is from the corrected base; the earlier one was void.