Skip to content

The live merge policy was unrepresentable, so no witness could go red on it: model ReportedContextsAtMergeInstant and declare the rung - #10280

Merged
gunbai-bot[bot] merged 11 commits into
mainfrom
session/eager-bear-107
Sep 4, 2026
Merged

gunbai-bot[bot] merged 11 commits into
mainfrom
session/eager-bear-107

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Both halves of the main flake were measured. Only one was already declared, and the model was actively wrong about the other — in the direction of strength.

Claim 1 — the required floor's verdict is a property of the runner

Confirmed, and deliberately not re-fixed.

  • Of the 25 most recent witnesses.yml runs on main, five reported verdict=FloorRefused with claims_failed=0 and unexpected_failures=0 — the whole refusal carried by interrupted_cpu_deadline and completed_over_cost_requirement. The floor refused main five times without a single claim disagreeing with the tree.
  • Nine required-witnesses-floor jobs by runner registration: six failed (srv1-02, srv1-07, srv1-10, srv1-16, srv1-17, srv4-11) and three passed (srv3-02, srv3-04, srv3-10). The honest reading is srv3 is the only host observed clearing the ceiling — specifically not "srv1 is defective", a reading refuted by srv4-11 within the hour.

gunbc.rung_drop floor_cost_claim_qualification_unavailable already declares this class thoroughly and names its own two missing items — a step-denominated line, and the cross-envelope eval_steps identity join. This PR discharges neither, so it adds the verdict-grain and host-grain evidence to the standing row and mints nothing new. Four lanes have already closed on shaving the claim under the ceiling and it fired again tonight: a fifth shave is redundant by construction, and a new row would be a second authority for one fact.

Claim 2 — a PR can merge before its required context reports

Confirmed, and it is the current main break, not a hypothetical.

gunbc#10236 pushed head d8cd3034 at 19:49:33Z, GitHub created its witnesses run at 19:49:40Z, and the merge completed at 19:49:43Z — three seconds after run creation, before any job reported. That run then concluded with required-witnesses-build and required-witnesses-floor both FAILURE. It landed as cfe19ea7, which is the commit that added two duplicate declarations to gunbc.recurring_failure_mode and refused main at resolve.

Not a one-off: over the 40 most recently merged PRs, six had no witnesses run that completed successfully on their own head before merged_at.

And the ruleset is not drifted. Ruleset 16178731 reads back with zero divergence from gunbc.repo_ruleset desired state — active, ~DEFAULT_BRANCH, one required context (witnesses, integration 15368), no bypass visible to the reading token. The converged desired state admits the merge: GitHub's required-status-checks rule decides on the check runs that have reported at the instant of the merge call, and a context with no check run yet is expected, not failing. Absence reads as not-failure — the empty-observation narrow §5 names, one level above where observe_repo_ruleset already refuses it.

What the model said instead

gunbc.merge_lifecycle named PerPrGateOnly "the live policy". PerPrGateOnly as modeled refuses a merge at a head with no receipt — merge_enabled folded policy_admits from init: false, so one caller-local constant answered the absent-receipt question for every policy. The live behavior was literally unwritable, which is why no witness could ever go red on it.

  • AdmissionPolicy gains ReportedContextsAtMergeInstant, the live arm. It differs from PerPrGateOnly on exactly one input — the absent receipt — and no other.
  • policy_admits_absent_receipt moves that verdict onto the policy. The three receipt-derived policies still answer false, so no existing arm's behavior moves.
  • The interleaving witness carries the discriminating pair: a bare MergePr with no preceding RunPrCi latches an unverified tip under the live policy and is refused under PerPrGateOnly and KeyedReceipt; plus a strict inequality on the window-4 counts, so an arm that merely aliased the old one keeps both positive counts and still fails.
  • gunbc.rung_drop merge_admission_absent_required_context, TypedDeclaration, previous MechanicallyPreventable, temporary Mitigatable. The trigger names the capability: no head lands on main without a terminal verdict from every required context on the content being merged. Terminal, because heal-generated-artifacts FAILED on XL-0T-CUTOVER: build Y — one exact declaration binding per TypeOccurrence from the containment authority — and retire #9813's module-wide precedence at the root. AUTHORING AUTHORIZED by ruling, MERGE HELD for root-cut receipts. Local use-line/qualification repairs are DEAD. #10236's pull_request run naming those duplicates and was SKIPPED on the main run of identical content — so a trigger reading "every required context reported non-failure" is satisfied by a roster whose catching lane never runs on the branch the defect lands on. The merge queue is named as the expected supplier and explicitly not as the trigger; zero merge_group runs of witnesses.yml exist today.
  • gunbc.recurring_failure_mode required_evidence_absent_reads_as_evidence_of_pass: a gate whose admission arm keys on observed failure rather than observed success, so the empty enumeration admits.

The two claims compose

A floor that refuses on a basis that is not a property of the tree teaches its readers that a red required floor is noise. An admission path that merges before the report means acting on that belief costs nothing. Neither half alone lands a broken tree on main. Together they did — and the lanes are cleanly separable in the evidence: on the post-merge main run at cfe19ea7 the duplicates reddened required-witnesses-build while required-witnesses-floor was green.

Not done here, and not a session-level omission

Enabling the merge queue, or making an unreported required context blocking, is a repository setting. The branch-protection and rule-suites endpoints answer 403 to this session's token. It is escalated to the operator and it is declared rather than left silent.

🤖 Generated with Claude Code

https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob

… on it: model ReportedContextsAtMergeInstant and declare the rung

Both halves of the main flake were measured; only one of them was already
declared, and the model was actively wrong about the other.

CLAIM 1 -- the required floor's verdict is a property of the runner. Confirmed
and NOT re-fixed. Of the 25 most recent witnesses.yml runs on main, five
reported verdict=FloorRefused with claims_failed=0 and unexpected_failures=0:
the whole refusal carried by interrupted_cpu_deadline and
completed_over_cost_requirement. Nine required-witnesses-floor jobs read by
runner: six failed (srv1-02/07/10/16/17 and srv4-11) and three passed
(srv3-02/04/10), so srv3 is the only host observed clearing the ceiling --
specifically NOT "srv1 is defective", a reading refuted by srv4-11 within the
hour. gunbc.rung_drop floor_cost_claim_qualification_unavailable already
declares this class thoroughly and names its own two missing items; four lanes
have closed on shaving the claim and it fired again tonight, so a fifth shave
is redundant by construction and a new row would be a second authority for one
fact. This commit adds the verdict-grain and host-grain evidence to the
standing row and discharges nothing.

CLAIM 2 -- a PR can merge before its required context reports. Confirmed, and
it is the current main break rather than a hypothetical. gunbc#10236 pushed
head d8cd303 at 19:49:33Z, GitHub created its witnesses run at 19:49:40Z, and
the merge completed at 19:49:43Z -- three seconds after run creation, before
any job reported. That run concluded with required-witnesses-build and
required-witnesses-floor both FAILURE. It landed as cfe19ea, which is the
commit that added two duplicate declarations to gunbc.recurring_failure_mode
and refused main at resolve. Over the 40 most recently merged PRs, six had no
witnesses run that completed successfully on their own head before merged_at.

Ruleset 16178731 reads back with ZERO divergence from gunbc.repo_ruleset
desired state. The converged desired state admits the merge: GitHub's
required-status-checks rule decides on the check runs that have REPORTED at the
instant of the merge call, and a context with no check run yet is expected
rather than failing.

WHAT THE MODEL SAID INSTEAD. gunbc.merge_lifecycle named PerPrGateOnly "the
live policy", and PerPrGateOnly as modeled REFUSES a merge at a head with no
receipt -- merge_enabled folded policy_admits from init: false, so a
caller-local constant answered the absent-receipt question for every policy.
The live behavior was literally unwritable, which is why no witness could go
red on it. So:

  - AdmissionPolicy gains ReportedContextsAtMergeInstant, the live arm, which
    differs from PerPrGateOnly on exactly one input and no other.
  - policy_admits_absent_receipt moves the absent-receipt verdict onto the
    policy; the three receipt-derived policies still answer false, so no
    existing arm's behavior moves.
  - the interleaving witness carries the discriminating pair: a bare MergePr
    with no preceding RunPrCi latches an unverified tip under the live policy
    and is refused under PerPrGateOnly and KeyedReceipt, plus a strict
    inequality on the window-4 counts so an arm that merely aliased the old one
    would fail.
  - gunbc.rung_drop merge_admission_absent_required_context, TypedDeclaration,
    previous MechanicallyPreventable, temporary Mitigatable. The trigger names
    the CAPABILITY: no head lands on main without a TERMINAL VERDICT from every
    required context on the content being merged. Terminal, because
    heal-generated-artifacts FAILED on #10236's pull_request run naming those
    duplicates and was SKIPPED on the main run of identical content -- so a
    trigger reading "every required context reported non-failure" is satisfied
    by a roster whose catching lane never runs on the branch the defect lands
    on. The merge queue is named as the expected supplier and explicitly NOT as
    the trigger; zero merge_group runs of witnesses.yml exist today.
  - gunbc.recurring_failure_mode required_evidence_absent_reads_as_evidence_of_pass:
    a gate whose admission arm keys on observed failure rather than observed
    success, so the empty enumeration admits.

THE TWO CLAIMS COMPOSE. A floor that refuses on a basis that is not a property
of the tree teaches its readers that a red required floor is noise; an
admission path that merges before the report means acting on that belief costs
nothing. Neither half alone lands a broken tree on main.

NOT DONE HERE, AND IT IS NOT A SESSION-LEVEL OMISSION: enabling the merge queue
or making an unreported required context blocking is a repository setting. The
branch-protection and rule-suites endpoints answer 403 to this session's token.
It is escalated, and it is declared rather than left silent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Witness receipt, executed rather than described. claim_batch --source-root dag --source-root src/v2 --entry dag/test/claim/merge_lifecycle_interleaving_witness_test.dag, all nine witnesses of the module — the four new ones and the five that were already there as regression controls:

PASS a_merge_before_any_run_lands_an_unverified_tip_under_the_live_policy
PASS a_merge_before_any_run_is_refused_under_per_pr_gate_only
PASS a_merge_before_any_run_is_refused_under_keyed_receipt
PASS the_live_policy_admits_strictly_more_unverified_tips_than_per_pr_gate_only
PASS per_pr_gate_only_admits_unverified_tips_in_window_4
PASS keyed_receipt_admits_no_unverified_tip_across_window_4
PASS window_4_enumerates_all_1296_sequences
PASS incident_trace_reds_main_under_per_pr_gate_only
PASS require_up_to_date_base_misses_the_roster_axis_in_window_4

The four pre-existing counts are unchanged, which is the check that policy_admits_absent_receipt moved no existing arm's behavior: the three receipt-derived policies still answer false on the absent receipt, exactly as the fold seed did.

Why the new pair is not green by construction. The two assertions take the same input — a one-event [MergePr { pr: pr_a }], no preceding RunPrCi — and assert opposite verdicts. A policy_admits_absent_receipt that answered true for everything greens the first and reds the second; one that answered false for everything does the reverse. The strict inequality on the window-4 counts is the third leg: an arm that merely aliased PerPrGateOnly would keep both positive counts and still fail there.

Base note. This branch is based on cfe19ea7, which is the broken main — so required-witnesses-build will red on the two duplicate declarations in gunbc.recurring_failure_mode until #10278 lands. That is the same commit this PR's evidence is about. I will merge main once the repair is in and re-run.

…mission decision, total over an optional receipt

codex review 59477 flagged `policy_admits_absent_receipt` as a substrate `Bool`
predicate matching the `AdmissionPolicy` coproduct directly, and asked for the
canonical fold/query surface or a dissolution disposition. The finding is right,
and this repository's own doctrine already says so: `gunbc.rung_drop`
`standing_rung_drops` records exactly this objection against a reusable
`RungDropStanding -> Bool` accessor -- a named predicate beside a coproduct is a
second, weaker spelling of the variant, and every later caller reaches for the
Bool instead of the arm it came from.

So the predicate is deleted rather than given a disposition. The repair is a
TYPE:

  - `latest_receipt_for` returns `MergeAdmissionReceipt?` instead of a
    `List<MergeAdmissionReceipt>`. It already kept AT MOST ONE receipt -- it
    folded to `[r]` or `[]` -- so the list was carrying an optional's job and
    the caller paid for it with an emptiness test.
  - `policy_admits` takes `MergeAdmissionReceipt?`. The absent case is now an
    arm of the one admission decision rather than an accessor standing beside
    the policy coproduct. There is no second predicate to dispose of.
  - `merge_enabled` collapses to a single `policy_admits` call: no fold, no
    `init:` seed, no emptiness branch, and the `list_length` import is gone.

Behavior is unchanged from the previous head: the three receipt-derived
policies still refuse an absent receipt and `ReportedContextsAtMergeInstant`
still admits one.

TWO CALL SITES UPDATED, both in test.claim.merge_admission_witness, which now
pass `Present { value: scenario_pr_x_receipt }`.

NEW STATIC-GRAIN EVIDENCE, because `policy_admits` gained an input domain and a
reader auditing it should not have to run a lifecycle to learn what it answers
on `Absent`: `the_live_policy_admits_an_absent_receipt` and
`the_three_receipt_derived_policies_refuse_an_absent_receipt` take the same
input and assert opposite verdicts, so an arm answering one constant for every
policy greens exactly one of them.

EXECUTED, both modules, after the change:

  merge_lifecycle_interleaving  9/9 PASS  (the 4 pre-existing counts unchanged,
                                           which is the check that no existing
                                           arm's behavior moved)
  merge_admission               5/5 PASS

ONE DEFECT IN THE FIRST SPELLING OF THIS REWORK, caught locally before pushing:
`if receipt_is_for_pr_head(...) { Present { value: r } } else { acc }` fails to
typecheck -- "if branches resolve to incompatible types: Product(...) vs
Coproduct(Optional)". The corpus idiom for folding into an Optional
(extdeps.uri, extdeps.llm.claude_setup_token_cli) uses `match`, not `if`, and
that is what this uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

review 59477 — reworked, not argued

The finding is right, and this repository's own doctrine already says so: gunbc.rung_drop standing_rung_drops records exactly this objection against a reusable RungDropStanding -> Bool accessor — "a named predicate beside a coproduct is a second, weaker spelling of the variant the row already carries, and every later caller reaches for the Bool instead of the arm it came from."

So I did not supply a disposition for policy_admits_absent_receipt. I deleted it. The repair is a type, not a second declaration:

  • latest_receipt_for now returns MergeAdmissionReceipt? instead of List<MergeAdmissionReceipt>. It already kept at most one receipt — it folded to [r] or [] — so the list was carrying an optional's job, and the caller paid for it with an emptiness test.
  • policy_admits now takes MergeAdmissionReceipt?. The absent case is an arm of the one admission decision rather than an accessor standing beside the policy coproduct. There is no second predicate left to dispose of.
  • merge_enabled collapses to a single policy_admits call — no fold, no init: seed, no emptiness branch, and the list_length import is gone.

This is a better answer than routing the predicate through a fold, because the fold seed was the thing hiding the verdict in the first place: init: false was one caller-local constant answering the absent-receipt question for all four policies.

Two call sites updated, both in test.claim.merge_admission_witness, now passing Present { value: scenario_pr_x_receipt }.

New static-grain evidence, since policy_admits gained an input domain and a reader auditing it should not have to run a lifecycle to learn what it answers on Absent. The pair takes the same input and asserts opposite verdicts, so an arm answering one constant for every policy greens exactly one of them.

Executed, both modules, after the change:

merge_lifecycle_interleaving   9/9 PASS   (4 pre-existing counts unchanged)
merge_admission                5/5 PASS
  PASS the_live_policy_admits_an_absent_receipt
  PASS the_three_receipt_derived_policies_refuse_an_absent_receipt

The unchanged pre-existing counts are the check that no existing arm's behavior moved.

One defect in my first spelling of this rework, caught locally before pushing: if receipt_is_for_pr_head(...) { Present { value: r } } else { acc } does not typecheck — if branches resolve to incompatible types: Product(MergeAdmissionReceipt) vs Coproduct(Optional). The corpus idiom for folding into an Optional (extdeps.uri, extdeps.llm.claude_setup_token_cli) uses match, and that is what this uses.

on the failing check

heal-generated-artifacts fails, and it is inherited rather than introduced. Reproducing the job's exact command locally (gunbc run --entry dag/gunbc/instruments/generated_artifact_gate.dag --function main_wet) names the cause outright:

error: resolve failed for dag/gunbc/instruments/generated_artifact_gate.dag
  cause: dag/gunbc/recurring_failure_mode.dag:291:1: error: duplicate declaration
         'absence_classifier_default_bucket' in module 'gunbc.recurring_failure_mode'
         dag/gunbc/recurring_failure_mode.dag:293:1: error: duplicate declaration
         'green_reported_over_a_population_the_instrument_does_not_own'

Both names are cfe19ea7's — the head this PR's evidence is about, landed by the very merge-admission gap being modeled here. Neither is the row this PR adds (required_evidence_absent_reads_as_evidence_of_pass). A whole-corpus regen cannot pass on any branch carrying that main, so I am holding the push until #10278 lands, then merging main and re-running rather than pushing a speculative fix.

gunbc-ci-auto-heal and others added 3 commits September 3, 2026 21:02
…ping only this branch's new row

#10278 repaired main by DELETING the two duplicate second declarations
cfe19ea added -- `absence_classifier_default_bucket` and
`green_reported_over_a_population_the_instrument_does_not_own` -- each of which
still exists exactly once on main, verified against origin/main rather than
assumed. This branch's side of the conflict carried those two duplicates
(inherited) plus its own new row, so the resolution keeps only
`required_evidence_absent_reads_as_evidence_of_pass` and takes main's deletion
of the other two.

Checked after resolving, at identity grain rather than by eyeballing the hunk:
zero duplicate `data` declarations in the module, zero duplicate roster
entries, every roster entry has a declaration, and every declaration is
rostered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
…ured interval, and fix two quoting defects of my own

THE RETRACTION. An earlier revision of this branch said the lane that caught
gunbc#10236's duplicate declarations was `heal-generated-artifacts`, and that
it was event-conditional because heal FAILED on the pull-request run and was
SKIPPED on the main run of identical content. THE JOB GRAPH REFUTES IT, checked
directly rather than taken from a report: heal's step record shows step 2
`Checkout triggering branch head` FAILED at 19:52:01Z with `Regenerate every
committed generated artifact` SKIPPED. The regenerator never executed, so heal
detected nothing -- it failed because the merge had deleted the branch head it
wanted, three seconds after the run was created. A downstream consequence of
the merge was being read as a detection of the defect.

THE CORRECTED STATEMENT IS STRONGER AND SIMPLER. A required lane detected it
correctly and reported too late: `required-witnesses-build` refused with
`generated-artifact CarrierRefused cause=resolve` and its job completed at
20:04:14Z against a merge at 19:49:43Z -- TWENTY MINUTES AND THIRTY-ONE SECONDS
of unadjudicated interval. No routing question, no conditional lane, just the
window. Verified independently and unchanged: the main run at cfe19ea reddens
`required-witnesses-build` while `required-witnesses-floor` is GREEN, so the
two main flakes stay cleanly separable in the evidence.

The rung drop's RESTORATION TRIGGER still asks for a TERMINAL VERDICT per
required context, but is now grounded on that interval rather than on a skipped
lane: during those twenty minutes nothing had reported anything, so a trigger
reading "every required context reported non-failure" is satisfied by it.

THE RETRACTION IS KEPT IN SOURCE rather than edited out, because the misreading
is an instance of a rostered class. It is
`green_reported_over_a_population_the_instrument_does_not_own` inverted -- a RED
reported over a population the instrument never reached -- and the recognition
rule transfers: A JOB'S CONCLUSION IS NOT EVIDENCE ABOUT THE SUBJECT IT IS
NAMED FOR UNTIL ITS STEP RECORD SHOWS IT REACHED THE STEP THAT JUDGES.

TWO QUOTING DEFECTS OF MY OWN, caught by running the regen locally rather than
by CI. Prose I added to `gunbc.rung_drop` used literal double quotes inside a
double-quoted `.dag` string, terminating the literal ~53KB into a single-line
`data` row. The diagnostics landed as `undefined variable 'A'` and `field 'A'
not found in type 'AuthoredProse'` -- type errors far from their cause, because
the remainder of the paragraph then parsed as field syntax. Both instances
fixed and every `data` row in the two edited files swept for an odd quote
count.

WORTH RECORDING: the 14 witnesses were green while `rung_drop.dag` did not
resolve, because they do not import it. A witness module passing says nothing
about whether the modules it does not reach still parse in a whole-corpus
resolve.

PROJECTIONS REGENERATED by tools.generated_artifact_gate main_wet:
docs/design-failure-modes.md and docs/design-rung-drops.md, which are the only
two artifacts that drifted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
…ng regressed, so there is no rung to drop from

OPERATOR RULING (2026-09-03), on the escalation of claim 2: "Leave the hole
open for now - i know merging is not sound." That is option three of three --
no merge queue, no change to required-context blocking -- so the declaration is
the deliverable rather than the fallback, and getting its CARRIER right matters
more than it did when it was a placeholder.

IT IS NOT A RUNG DROP. §4b(3) governs REGRESSIONS: "a change may lower a rung
only by declaring previous rung, temporary rung, reason, bounded population and
restoration trigger". Nothing here lowered anything. GitHub's
required-status-checks rule has evaluated reported check runs the same way
since ruleset 16178731 was created on 2026-05-09, so the capability was NEVER
HELD and declaring `previous: MechanicallyPreventable` invents a rung to drop
from -- precisely what the neighbouring row refuses to do for its own subject:
`floor_cost_claim_qualification_unavailable` says "PREVIOUS RUNG: none for
environment-independent claim-cost qualification -- that guarantee was never
held, and saying it was would be inventing a rung to drop from."

WHAT ACTUALLY EXISTED WAS §4b(1) INFLATION -- this repository's "required lane"
vocabulary, and `gunbc.merge_lifecycle`'s own prose naming `PerPrGateOnly` the
live policy, describing a wall that does not stand for an unreported context.
Inflation is corrected by making the live policy representable, which the
`AdmissionPolicy` change does. What remains is a class below its ceiling, which
is a §4b(2) stall.

SO: `gunbc.rung_drop merge_admission_absent_required_context` is DELETED, along
with its roster entry, and both citations that pointed at it are swept --
`gunbc.merge_lifecycle` and `gunbc.recurring_failure_mode` now name the stall.
Zero references remain, checked corpus-wide rather than assumed.

NEW: `gunbc.guarantee_stall merge_admission_terminal_verdict_stall`.
  current Mitigatable, ceiling StructurallyGuaranteed, blocker
  ClimbableButUnbuilt -- climbable now, deliberately not built, with the ruling
  quoted verbatim and dated as INFORMED ACCEPTANCE by the principal who can
  actuate. A row reading "we could not fix this" ages into an excuse; one
  recording a decision taken with the population in view stays revisitable.

  POPULATION IS A PREDICATE, NOT A COUNT: UncountedNotEnumerable, because every
  future merge into main is exposed. The instrument is "for a merged PR, did a
  required witnesses run on ITS OWN head reach a terminal verdict before its
  merged_at" -- decidable per merge and re-measurable. The 6-of-40 reading is
  recorded AS a reading on a date, explicitly not the population: a set
  selected by a measurement is a view whose membership is a property of the
  measurement, and a frozen count is a change detector.

  TRIGGER IS THE CAPABILITY: no head lands on main without a TERMINAL VERDICT
  from every required context on the content being merged. Terminal rather than
  non-failing, because a context with NO verdict satisfies "reported
  non-failure" VACUOUSLY -- the hole restated inside the trigger. Both
  candidate artifacts are named (merge queue; blocking unreported contexts) and
  neither IS the trigger: any future claim citing one must state what it was
  SUFFICIENT FOR.

#9981 CAME THROUGH THE OTHER HOLE, and the line is added to
`gunbc.merge_lifecycle` as that module's standing instruction directs rather
than escalated. Its witnesses run on its own head COMPLETED SUCCESSFULLY at
20:26:54Z and it merged at 20:29:53Z -- it HAD its receipt, so it is not the
absent-receipt class. That run was CREATED at 19:37:37Z, twelve minutes before
cfe19ea landed, so it carried a green receipt against a base that had ceased
to be the tip and squashed onto a tree already refusing at resolve: stale-base,
admitted under PerPrGateOnly, refused under KeyedReceipt as
MergeDeniedStaleBase.

TWO HOLES, ONE COMMIT EACH, FORTY MINUTES APART. Separating them is the point:
a merge queue closes both, blocking unreported contexts closes only #10236, a
current-base rerun closes only #9981. A reader who counts two broken merges and
reaches for one cause gets one of the two remedies wrong.

EXECUTED: guarantee_stall 8/8 PASS with the new row enrolled (including
every_live_stall_is_below_its_ceiling and
every_live_stall_names_a_next_rung_trigger); regen clean and at a FIXED POINT --
round 2 produced no drift; projections regenerated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
@gunbai-bot

gunbai-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Operator ruled; the declaration is now the deliverable — and it is a stall, not a rung drop

Ruling (2026-09-03), on the escalation of claim 2: "Leave the hole open for now - i know merging is not sound." No merge queue, no change to required-context blocking. That makes the declaration the deliverable rather than the fallback, so its carrier matters more than when it was a placeholder — and the carrier I first used was wrong.

Why it is not a rung drop

§4b(3) governs regressions — "a change may lower a rung only by declaring previous rung, temporary rung…". Nothing here lowered anything: GitHub's required-status-checks rule has evaluated reported check runs the same way since ruleset 16178731 was created on 2026-05-09. The capability was never held, so previous: MechanicallyPreventable invents a rung to drop from. That is exactly what the neighbouring row refuses to do for its own subject — floor_cost_claim_qualification_unavailable: "PREVIOUS RUNG: none … that guarantee was never held, and saying it was would be inventing a rung to drop from."

What existed was §4b(1) inflation: this repo's "required lane" vocabulary, and merge_lifecycle's own prose naming PerPrGateOnly the live policy, describing a wall that does not stand for an unreported context. Inflation is corrected by making the live policy representable — which the AdmissionPolicy change does. What remains is a class below its ceiling: a §4b(2) stall.

So gunbc.rung_drop merge_admission_absent_required_context is deleted with its roster entry, and both citations to it swept (zero references remain, checked corpus-wide).

gunbc.guarantee_stall merge_admission_terminal_verdict_stall

  • current: Mitigatable, ceiling: StructurallyGuaranteed, blocker: ClimbableButUnbuilt — climbable now, deliberately not built, with the ruling quoted verbatim and dated as informed acceptance by the principal who can actuate. A row reading "we could not fix this" ages into an excuse; one recording a decision taken with the population in view stays revisitable.
  • Population is a predicate, not a count. UncountedNotEnumerable — every future merge into main is exposed. The instrument: for a merged PR, did a required witnesses run on its own head reach a terminal verdict before its merged_at. The 6-of-40 is recorded as a reading on a date, explicitly not the population; a set selected by a measurement is a view whose membership is a property of the measurement, and a frozen count is a change detector.
  • Trigger is the capability: no head lands on main without a terminal verdict from every required context on the content being merged. Terminal rather than non-failing, because a context with no verdict satisfies "reported non-failure" vacuously. Both candidate artifacts are named (merge queue; blocking unreported contexts) and neither is the trigger — any future claim citing one must state what it was sufficient for.

#9981 came through the other hole

Its witnesses run on its own head completed SUCCESS at 20:26:54Z and it merged at 20:29:53Z — it had its receipt, so it is not this class. That run was created at 19:37:37Z, twelve minutes before cfe19ea7 landed, so it carried a green receipt against a base that had ceased to be the tip and squashed onto an already-refusing tree: stale-base, admitted under PerPrGateOnly, refused under KeyedReceipt as MergeDeniedStaleBase. The line is added to merge_lifecycle as that module's standing instruction directs, rather than escalated.

Two holes, one commit each, forty minutes apart. Separating them is the point: a merge queue closes both, blocking unreported contexts closes only #10236, a current-base rerun closes only #9981.

Executed

guarantee_stall                8/8 PASS  (new row enrolled; below-ceiling and
                                          names-a-trigger both green)
merge_lifecycle_interleaving   9/9 PASS  (4 pre-existing counts unchanged)
merge_admission                5/5 PASS
regen (generated_artifact_gate main_wet)  clean, and at a FIXED POINT —
                                          round 2 produced no drift

heal-generated-artifacts should now pass: its failure was cfe19ea7's duplicate declarations, and main is merged in with that conflict resolved (keeping only this branch's new row and taking main's deletion of the two duplicates, checked at identity grain).

gunbc-ci-auto-heal and others added 6 commits September 3, 2026 21:53
…closure warrant, and a buildability constraint on missing item (b)

All three are evidence for `floor_cost_claim_qualification_unavailable`. The
do-not-fix disposition is unchanged and nothing here discharges either of that
row's missing items.

A SECOND srv4 FAILURE, so the host table is now ten jobs: seven failed
(srv1-02, srv1-07, srv1-10, srv1-16, srv1-17, srv4-11, srv4-14) and three
passed (srv3-02, srv3-04, srv3-10). THE TWO STATEMENTS THE SAMPLE SUPPORTS ARE
DELIBERATELY WEAKER THAN A CAUSAL ONE: the failing set is not confined to one
host family, and every passing observation is confined to a single host. A
family-shaped hypothesis has now been falsified twice by widening the sample,
which is why the surviving claim is not "srv1 is slow" or "srv3 is fast".

EVIDENCE GRADES ARE NOT FLATTENED. Six of the seven failures had their
`claims_failed=0` / `unexpected_failures=0` signature READ from run logs;
srv4-11 is taken on report. "Failed" and "failed with this signature" are
different facts, and a carrier whose subject is a verdict attributed to the
wrong thing should say which one it holds -- a floor job can redden on a phase
that is not the floor.

A ONE-SUBJECT CROSS-ENVELOPE READING, RECORDED AS BEARING ON MISSING ITEM (b)
AND NOT AS DISCHARGING IT.
`v2.test.emit.rust_produced_decl_emit.produced_decl_unwired_target_still_refuses`
measured 165802 eval_steps at 346 cpu-ms on run 33802603168 and 165802
eval_steps at 514 cpu-ms on run 33806159353 -- identical to the digit against a
1.49x cpu move -- with log-line controls of 3472 and 3465 ruling out an empty
capture on either side.

WHY IT IS NOT (b), ON THREE COUNTS. (i) (b) asks for CORPUS grain; this is one
subject. (ii) (b) asks for TWO ATTEMPTS OF ONE IDENTICAL TREE; these are two
different trees -- 8b2323f is an ANCESTOR of 07f81df, verified rather than
assumed. (iii) the warrant that the work did not change cannot come from the
step count itself, since constant steps are equally consistent with a measure
insensitive to the change.

(iii) IS NOW ANSWERED, by two arguments that do not depend on each other and
that were re-derived here rather than relayed. A SYMBOL-GRAIN JOIN: the diff
touches three files and adds or removes six declarations, and the module
declaring the measured claim references none of them, with a positive control
on the same grep finding tt_emit / tt_emits / tt_refuses in that file. SYMBOL
GRAIN RATHER THAN IMPORT CLOSURE IS LOAD-BEARING: names resolve by global
uniqueness here, so an import-closure argument would unsoundly exclude modules
that can still supply a binding. AND A DIRECTION ARGUMENT that holds even if
that join is not exhaustive: the diff is NET NEGATIVE, 32 insertions against 60
deletions, so any corpus-scale work effect predicts this claim gets CHEAPER
while the observation is 1.49x more expensive.

A CONSTRAINT ON HOW (b) CAN EVER BE DISCHARGED, which is a property of the
column rather than of tonight. An INTERRUPTED row is unmeasured in `eval_steps`
BY CONSTRUCTION -- the poll fires before a count exists -- so a corpus-grain
identity join over this column has a STRUCTURALLY EXCLUDED SUBPOPULATION, and
the excluded rows are precisely the expensive ones the join most needs. A later
lane that builds it over completed rows and reports coverage would be reporting
over a population it does not own, which is exactly the failure mode this
branch files. The honest discharge must state the exclusion in its result or
reach interrupted rows by a different measure.

TWO DEFECTS OF MY OWN IN THIS EDIT, both caught before pushing and both in
prose I had just written: the double-quote-inside-a-double-quoted-string bug
reintroduced, and -- the one a quote sweep cannot see -- RAW NEWLINES embedded
in a single-line string literal, which had silently split the `data` row across
seven lines. The corpus escapes those as `\n`. Row rejoined to one line and
regen re-run, because balanced quotes prove balance and not that the row
resolves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
…e-per-row shape, and record the same-head control that decides claim 1's subject

TWO INDEPENDENT THINGS LANDED IN THIS MERGE.

1. THE #10206 MIGRATION. Main restructured the failure-mode carrier one row per
module file, with `authored: String` becoming `receipts: List<String>`. Its
stated motive is the exact collision this branch hit: every row PR appends at
the same two points, so they conflict BY CONSTRUCTION. This is therefore a
MIGRATION and not a textual resolution -- main's `recurring_failure_mode.dag`
is taken wholesale, and `required_evidence_absent_reads_as_evidence_of_pass` is
rebuilt as its own module with its prose split into EIGHT receipts at its
section boundaries, which is the structure's purpose rather than decoration.
Import and roster entry appended AT THE END, because roster order is
load-bearing: the projection renders in roster order and sorting would destroy
the empty-diff oracle.

`docs/design-failure-modes.md` was NOT resolved by hand. The generated-artifact
merge driver refused it -- both sides changed the projection since the merge
base, so neither side's bytes are the projection of the MERGED authorities and
taking either side silently drops the other's content. Reset to main's bytes
and REGENERATED from the merged authorities, which is step 1 of the recipe the
driver itself printed. The driver worked, and it caught a case where --ours or
--theirs would have lost content with no conflict markers.

2. THE SAME-HEAD CONTROL, which is now the LEAD EVIDENCE on
`floor_cost_claim_qualification_unavailable` and demotes every host-correlation
sentence beneath it. Run 33806159353 was re-run at an unchanged head: attempt 1
`required-witnesses-floor` FAILURE on srv4-14, attempt 2 SUCCESS on srv4-19.
ONE TREE, TWO ATTEMPTS, OPPOSITE VERDICTS. The verdict is demonstrably not a
property of the tree -- shown by construction, needing no closure warrant
because nothing changed.

THE HOST-FAMILY READINGS ARE REFUTED, twice in the same direction, and the row
now names no family: srv1-is-the-bad-host died to srv4-11, srv3-is-the-only-
passer died to srv4-19. Eleven jobs, seven fail four pass. THE ACTUAL VARIABLE
IS UNIDENTIFIED and the row says so.

MISSING ITEM (b) IS DISCHARGED OVER THE MEASURABLE POPULATION AND THE ROW STILL
STANDS. An identity join over the two attempts: 338 shared-fill per-claim rows
each side, ZERO unmatched either direction, `marginal_eval_steps` and
`measured_eval_steps` identical for all 338, while cpu moved >10% on 124 and
ranged 0.627-1.217. Denominator stated: 338 of 3585 executed claims, 9.4%, NOT
whole-floor coverage.

THE EXCLUSION IS THE FINDING. Interrupted rows are unmeasured in steps by
construction, so the join covers completed rows only -- and the excluded rows
are EXACTLY THE ROWS THAT DECIDED THE VERDICT. Attempt 1: passed=3507,
interrupted_before_verdict=2, completed_over_cost_requirement=1, FloorRefused.
Attempt 2: passed=3510, both counters 0, FloorClean. 3507+2+1=3510, so the
three are precisely the difference between the attempts and precisely the rows
no step measurement can reach. THE MORE A CLAIM IS AFFECTED, THE LESS
MEASURABLE IT BECOMES -- which is also the first constraint this row has been
able to state on missing item (a): a step-denominated line built on this
instrument would be blind in its own subject's direction.

EVIDENCE GRADES KEPT SEPARATE. Both attempt summaries and their arithmetic were
read FIRST-HAND at two different times; the 338-row join is taken from its
builder and was not re-derived, because the attempt-1 log archive returns a
truncated response that will not open.

A CITATION TRAP OBSERVED WHILE VERIFYING, recorded in the row: a bare job id
serves the LATEST attempt, so job 100817014187 -- own conclusion `failure` --
now serves attempt 2's FloorClean summary. Only an attempt-level citation is
stable.

Regen clean after every prose edit; projections regenerated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
…the same roster point

`dag/gunbc/guarantee_stall.dag` conflicted because both sides added a row at
the head of `all_guarantee_stalls`: origin/main's
`pre_resolve_entry_closure_module_identity_stall` (#10267) and this branch's
`merge_admission_terminal_verdict_stall`. BOTH ARE KEPT, main's first. Picking
a side would have silently deleted a declared §4b(2) stall, and nothing joins
the roster to the declarations, so the deletion would not have refused
anywhere.

VERIFIED AT IDENTITY GRAIN RATHER THAN BY READING THE HUNK: each of the two
rows is declared exactly once and rostered exactly once, and every roster entry
has a declaration. One apparent orphan, `guarantee_rung_label`, was my own grep
matching an import line rather than a roster entry -- checked instead of filed.

EXECUTED after resolving: regen clean with ZERO drift, and the four roster-wide
stall witnesses pass with both rows enrolled --
`every_live_stall_is_below_its_ceiling` and
`every_live_stall_names_a_next_rung_trigger` are the two that would redden on a
malformed or half-merged row.

AN OBSERVATION FOR THE CARRIER'S OWNER, NOT A CHANGE MADE HERE: this is the
third conflict on this branch and all three had one shape -- two lanes
appending to one roster. gunbc#10206 restructured
`gunbc.recurring_failure_mode` one row per file for exactly this reason,
recording that such PRs conflict BY CONSTRUCTION rather than by bad timing.
`gunbc.guarantee_stall` still carries the old geometry, so the collision will
keep recurring there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
…jection rather than picking a side

Fourth conflict on this branch and the fourth of one shape: two lanes appending
to one roster. Here origin/main added
`live_argument_threaded_past_the_arm_that_decides` (#10274) at the same two
tails this branch appended `required_evidence_absent_reads_as_evidence_of_pass`
to -- the import list and the roster list. BOTH KEPT, main's first in both
places.

VERIFIED AS A JOIN IN BOTH DIRECTIONS rather than by reading the hunk: every
roster entry has an import AND a row-module file on disk, and no import is
unrostered.

`docs/design-failure-modes.md` went to the generated-artifact merge driver
again. Reset to main's bytes and REGENERATED from the merged authorities per
the driver's own recipe; regen is clean with zero residual drift.

THE COLLISION GEOMETRY IS STILL THERE AFTER #10206, WHICH IS WORTH RECORDING
SOMEWHERE A CARRIER OWNER WILL SEE. That change split failure-mode ROWS into
one file each, which removes the declaration-tail collision -- and this
conflict is at the ROSTER tails, which it did not remove. So the per-row split
halves the collision surface rather than closing it, and
`gunbc.guarantee_stall` and `gunbc.rung_drop` still carry the unsplit form
where both surfaces collide. Not fixed here; it is not this branch's subject.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017q3jn4AYgCR2x4zMqSxBob
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
# Conflicts:
#	dag/gunbc/recurring_failure_mode/roster.dag
#	docs/design-failure-modes.md
@gunbai-bot
gunbai-bot Bot merged commit 1349358 into main Sep 4, 2026
7 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/eager-bear-107 branch September 4, 2026 02:13
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
#10280 added required_evidence_absent_reads_as_evidence_of_pass. Distinct from
this branch's identity, so both are kept on BOTH surfaces the conflict touched
-- the import block and the roster list -- theirs first, ours last, so the
projection's paragraph order gains one entry rather than transposing any.

The projection took main's side unread and is regenerated below from the merged
authority: a generated file has no judgement in its resolution, and that is the
half of this merge where authorship cannot be lost. The roster half is two
authors' adjacent lines and was read rather than unioned blindly.

94 row files, 94 imports, 94 list entries; no duplicates, no cross-surface
disagreement; loss arm empty against both parents; subsequence holds both ways.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012imgm3QzXAT6GBn3ifTCDd
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
Two lines on main's rendering; #10280's paragraph intact and this row byte-exact
against the fold of its receipts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012imgm3QzXAT6GBn3ifTCDd
gunbai-bot Bot pushed a commit that referenced this pull request Sep 4, 2026
Held deliberately until #10280 landed rather than racing it. We contended on the
same two paths, so both integrating at once meant the loser paid a second full CI
round for nothing. I had this resolution computed and verified against ca54b2e
and discarded it rather than push into that race; redoing it behind #10280 is the
one round the sequencing was buying.

#10280 amended gunbc.rung_drop.dag, so this is a full RE-CUT and not a conflict
resolution. Split re-derived from 1349358: 30/30 rows, every string literal
byte-for-byte in order plus structure normalized outside strings, zero divergences,
none added, none dropped.

The recurring_failure_mode roster resolved additively for the fifth time -- both
sides' imports and entries, never choosing. 94/94/94 exact bijection, up one from
the 93 the discarded round measured, which is #10280's own row. The count is the
check and not the goal: it is the identity join across files, imports and roster
entries that has to be exact, and it is.

My own carrier: 30 files / 30 imports / 30 roster entries, same join, also exact.

gate resolves with zero errors; design-rung-drops.md 0/0 against the pin, so the
relocation is still structural over #10280's amendment; design-failure-modes.md
+3/-1; seed emitter first_generation_equal=true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VpnmpcnG82KZBgAaRB7cWD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants