Skip to content

CI A1: infra-vs-structural classifier + green-on-main merge-blocking verdict (single authority, fail-closed) - #5615

Merged
briansrls merged 9 commits into
mainfrom
session/warm-dove-372
Jun 23, 2026
Merged

briansrls merged 9 commits into
mainfrom
session/warm-dove-372

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jun 23, 2026 •

Copy link
Copy Markdown
Contributor

CI lockdown A1 — green-on-main-at-merge classifier (construction-first, by-execution)

The killer this targets: the floor-skew / merge-skew that lets a green-on-branch PR go red-on-main. Requiring a PR's floor be green against current main is only viable if a red can be told apart from flake — otherwise the requirement blocks merges on the reds that are environmental (sccache/EAGAIN/runner contention). This PR builds that classifier and the merge-blocking verdict; the freshness mechanism (re-run vs current main) stays the operator merge-queue per docs/plans/ci-merge-freshness.md §3 — this PR produces the verdict that mechanism consumes.

Grounded in cited extdeps (not coined strings)

The infra signatures are upstream artifacts, so each substring is sourced from its real extdep, cited/anchored; ci_failure_class (workflow) keeps only the Infra | Structural partition policy and inherits the fragments:

  • extdeps/runtime/errno.dag (NEW) — POSIX errno EAGAIN/ENOMEM modeled structurally (errno_number 11/12 + errno_strerror); EAGAIN strerror = Resource temporarily unavailable.
  • extdeps/rust/std_process.dag (NEW) — StdProcessSpawnOutcome; SpawnFailed ⇒ failed to spawn.
  • extdeps/github/ci_runner.dag (NEW) — RunnerLifecycleSignal; ShutdownReceived ⇒ The runner has received a shutdown signal.
  • extdeps/cache/sccache.dag — cited fatal-error fragment (existing mozilla/sccache anchor).

ci_failure_class.InfraSignature folds these inherited fragments — the unambiguous single-exit infra set.

  • SignatureSite = BuildLog | JobSignal — names the observation axis; build_retry_infra_signatures derives the build-log subset by site (no Bool predicate).
  • FloorFailureClass = Infra | Structural; classify_floor_exit / classify_failure_reason are fail-closed — anything not matching an unambiguous infra signature classifies Structural.
  • floor_exit_blocks_merge — the green-on-main blocking predicate: ExitSuccess / Infra ⇒ non-blocking; Structural ⇒ blocks merge.

§5 fail-OPEN guard (the dangerous direction)

A real structural red mislabeled as infra would retry-pass — the single worst outcome. Two defenses:

  • OOM / exit-137 is NOT auto-classified infra. A lone exit-137 is ambiguous (co-residence OOM vs a structural memory-runaway defect). Per deep-otter-528's cited rule, OOM is infra only when clustered (multi-job death + host-uptime reset) — which a single ProcessExit can't establish — so a bare exit-137 fails closed (⇒ Structural ⇒ blocks). Confident-OOM-infra is deferred to the cross-run clustering consumer that has the evidence.
  • witness_structural_not_swallowed_as_infra feeds real compile-error / inference-deficit / assertion / gate-violation / panic strings and a bare exit-137, asserting each ⇒ Structural ⇒ blocks.

§3 de-fork (the heart)

ci_spec.dag hard-coded the infra-signature alternation twice with hand-drift — the BUILD_LOG grep used the precise sccache: encountered fatal error, the RETRY_LOG grep used an over-broad bare sccache:. Both now derive from infra_retry_grep_alternation(), narrowing the RETRY_LOG sites to the precise fail-closed form. ci.yml regenerated (drift gate green); the only ci.yml change is those 3 grep sites.

Verified by execution (local)

  • ci_failure_class_witnesses GREEN: real EAGAIN/spawn/sccache/runner-disconnect ⇒ Infra (non-blocking); compile/inference/assertion/gate-violation/panic/unknown/bare-exit-137 ⇒ Structural (blocks); every signature carries a grounded origin.
  • Discriminating RED proven (fail-open perturbation flips the witness true→false).
  • Existing ci_spec_witnesses, generated_artifact_drift_gate, dsl_compile_clean_gate all GREEN; full floor-plan import graph resolves clean.

Ships DORMANT (enable-gate written down)

The verdict surface lands dormant — nothing consumes floor_exit_blocks_merge to block any merge yet (the freshness mechanism is out of scope). Per docs/plans/ci-merge-freshness.md §6, flipping it to enforcing is gated on BOTH (a) the cross-run clustering-reclassification consumer landing (else a co-residence OOM livelocks on green-on-main re-runs) AND (b) cap-recovery reclaiming session slots. A §6 scaffold-with-dissolution-trigger; do not flip it live early.

Coordination

infra_retry_grep_alternation() / gunbc.ci_failure_class is the single authority for the infra-signature alternation — B3 (#5617) consumes it rather than re-hardcoding. #5615 lands first; B3 rebases onto the merged authority.

🤖 Generated with Claude Code

briansrls and others added 3 commits June 23, 2026 05:18
…verdict (single authority, fail-closed)

Model the infra-vs-structural failure partition as a single authority
(gunbc.ci_failure_class) and DERIVE both consumers from it:

1. infra_retry_grep_alternation() now drives the ci_spec.dag build-retry
   grep at BOTH sites — dissolving a §3 hand-drift (BUILD_LOG site precise
   'sccache: encountered fatal error' vs RETRY_LOG site over-broad bare
   'sccache:'). Both now narrow to the precise grounded signature.
2. floor_exit_blocks_merge() — the green-on-main-at-merge blocking predicate:
   ExitSuccess / Infra-classified red => non-blocking; Structural red => blocks.
   FAIL-CLOSED: an unknown reason classifies Structural => blocks merge.

Grounded InfraSignature rows: EAGAIN ('Resource temporarily unavailable'),
process spawn failure, sccache fatal, OOM-kill (exit 137), runner-lost —
the last two from deep-otter-528's cited classifier (single-exit-observable).

By execution: dsl/test/claim/ci_failure_class_witness_test.dag classifies real
EAGAIN/spawn/sccache/OOM/runner-lost reasons => Infra (non-blocking), real gate
diagnostics + unknown reasons => Structural (blocks); discriminating RED proven
(fail-open classify flips the witness false). ci.yml regenerated (drift gate
green). compile-clean + ci_spec witnesses green locally.

Scope: the freshness *mechanism* (re-run vs current main) stays the operator
merge-queue per docs/plans/ci-merge-freshness.md §3; this PR produces the
verdict that mechanism consumes. infra_retry_grep_alternation() is the single
authority for B3's retry-ladder hardening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title CI lockdown A1 - GREEN-ON-MAIN-AT-MERGE gate WITH infra-vs-structural classifier (one atomic PR, by-execution, construction-first). A PR's floor must be green against CURRENT main before it is merge-ready (the floor-skew/merge-skew killer that lets a green-on-branch PR go red-on-main). Build on the CI A1: infra-vs-structural classifier + green-on-main merge-blocking verdict (single authority, fail-closed) Jun 23, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review June 23, 2026 05:33
briansrls and others added 3 commits June 23, 2026 05:43
Operator §5 fail-OPEN guard (ratification-contingent): a LONE exit-137 is
ambiguous — co-residence OOM (infra) vs a structural memory-runaway defect.
Per deep-otter-528's cited rule OOM is infra ONLY when CLUSTERED (simultaneous
multi-job death + host-uptime reset), which a single ProcessExit cannot
establish. So the unconditional code-137 => Infra shortcut was a fail-open: a
real defect that OOMs would retry-PASS. Removed it (and OutOfMemoryKill from the
single-exit verdict set); OOM classification is deferred to the cross-run
clustering consumer that has the evidence to justify it. Single-exit Infra set
is now only the unambiguous signatures: EAGAIN, spawn-failure, sccache-fatal,
runner-disconnect; everything else (incl. bare exit-137) fails closed =>
Structural => blocks.

Added the explicit structural-not-swallowed-as-infra control the operator asked
for: real compile-error / inference-deficit / assertion / gate-violation strings
AND a bare exit-137 all classify Structural and block merge (the broad-match
direction, not just the lens-fires direction).

Review nit (claude-opus-4-7, non-blocking): replaced the signature_appears_in_build_log
Bool predicate with a named SignatureSite = BuildLog | JobSignal axis; the
build-retry grep subset now derives by site, not a yes/no helper.

Grep alternation unchanged (EAGAIN|spawn|sccache); ci.yml unchanged; witness
green by execution.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Record the dormancy + flip-to-enforcing gate so a future worker can't wire the
green-on-main verdict live early (a loaded mechanism left unwired on purpose).
Enforcing is gated on BOTH (a) the cross-run clustering-reclassification consumer
landing (else co-residence OOM => Structural => block => re-run => OOM livelock)
AND (b) cap-recovery reclaiming session slots (green-on-main re-runs increase
floor memory load in the contention window). §6 scaffold-with-dissolution-trigger;
decidable trigger => wall-after-grounding, not a forever-ratchet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
briansrls and others added 3 commits June 23, 2026 08:14
…strings

Operator §3 direction: the infra error-strings are upstream artifacts, not ours
to coin — so they ground in CITED extdeps and ci_failure_class (workflow) keeps
only the Infra/Structural partition POLICY, inheriting each fragment:

- extdeps/runtime/errno.dag (NEW) — POSIX errno EAGAIN/ENOMEM, modeled
  STRUCTURALLY (errno_number 11/12 + errno_strerror), anchored to POSIX.
  EAGAIN strerror = 'Resource temporarily unavailable'.
- extdeps/rust/std_process.dag (NEW) — StdProcessSpawnOutcome; SpawnFailed log
  fragment 'failed to spawn', anchored to doc.rust-lang.org/std/process.
- extdeps/github/ci_runner.dag (NEW) — RunnerLifecycleSignal; ShutdownReceived
  'The runner has received a shutdown signal', anchored to GitHub runner docs.
- extdeps/cache/sccache.dag — cited fatal-error fragment, existing mozilla anchor.

ci_failure_class.infra_signature_match_substring now folds these inherited
fragments; infra_signature_origin points at each extdep home. DFS-confirmed no
pre-existing errno/process-error concept to extend (§2/§6, not a re-coin).

Surface stable: infra_retry_grep_alternation() byte-identical (B3 consumes it
unchanged); ci.yml unchanged. Verified by execution against the LIVE tree:
ci_failure_class + ci_spec witnesses, extdeps_external_authority gate,
corpus_live_clean_tree_holds (+ discriminating: deleting an anchor reds it,
proving the scan sees the new files; no backfill entry needed), layering_imports,
compile-clean — all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@briansrls
briansrls merged commit 4fceebf into main Jun 23, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/warm-dove-372 branch June 23, 2026 13:51
briansrls added a commit that referenced this pull request Jun 23, 2026
…locking verdict (single authority, fail-closed) (#5615)" (#5627)

This reverts commit 4fceebf.

Co-authored-by: Brian Searls <briansrls@gunb.ai>
briansrls added a commit that referenced this pull request Jun 24, 2026
… keystone; operator+parent SIGNED). CONTEXT: A1 (#5615, the Infra/Structural CI-failure classifier + floor_exit_blocks_merge verdict surface) was REVERTED by #5627 to clear an outage — its closure expansion poisoned EqualsClaim res (#5651)

* Revert "Revert "CI A1: infra-vs-structural classifier + green-on-main merge-blocking verdict (single authority, fail-closed) (#5615)" (#5627)"

This reverts commit c7962ab.

* WIP: A1 RE-LAND on #1 with merge-freshness verdict LIVE (CI-lockdown ARM-A ke

* WIP: A1 RE-LAND on #1 with merge-freshness verdict LIVE (CI-lockdown ARM-A ke

* WIP: A1 RE-LAND on #1 with merge-freshness verdict LIVE (CI-lockdown ARM-A ke

* WIP: A1 RE-LAND on #1 with merge-freshness verdict LIVE (CI-lockdown ARM-A ke

* Merge fix: §6 is single-authority in the .dag plan (doc is generated)

main's batch-B fanned docs/plans/ci-merge-freshness.md INTO a structured .dag
plan (gunbc.plans.ci_merge_freshness) enrolled as a generated artifact
(generated_artifact.dag: committed doc must == expected_plan_md(plan), checked
by the floor's generated_artifact_drift_gate). My §6 honest-marking landed only
in the doc during conflict resolution -> would drift-red post-merge (semantic
merge-skew). Fix: add §6 to ci_merge_freshness_body() (the authority) and
regenerate the doc from expected_plan_md so committed == rendered.

Verified by execution: generated_artifact_drift_witnesses + plan_lens witnesses
both true; doc now byte-equals the rendered plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* WIP: A1 RE-LAND on #1 with merge-freshness verdict LIVE (CI-lockdown ARM-A ke

* Restore dsl-v2-defork-audit.md §2A (do not ship the regen-deletion)

main_wet regen deleted §2A (the .dag authority lacks it); that content is #5652's
Q2 resolver-wall analysis and must not be lost. Restore the doc to origin/main so
my branch is faithful. The §2A-in-.md-not-in-.dag drift is a pre-existing fleet
main-red (escalated to lockdown mgr), NOT mine to fix by deletion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant