Skip to content

fix(OMN-18664): release-train lab premise accepts the nearest runtime-affecting ancestor's receipt - #3745

Merged
jonahgabriel merged 1 commit into
devfrom
jonah/omn-18664-train-lab-premise-nearest-runtime-ancestor
Sep 18, 2026
Merged

jonahgabriel merged 1 commit into
devfrom
jonah/omn-18664-train-lab-premise-nearest-runtime-ancestor

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 18, 2026 •

Copy link
Copy Markdown
Collaborator

Closes OMN-18664. Parent OMN-18595.

The defect

The release train's lab premise asked for a lab-pass-receipt-compose-dev-<sha> naming the EXACT dev head. runtime-rebuild-trigger.yml emits that artifact only when the merge was runtime-affecting — its receipt job is gated on published == 'true' && runtime_lane == 'dev' — so a workflow-only or scripts-only merge landing last has no receipt, at any time, and never will. Seven of the eight dev merges preceding run 35316314098 carried none, by design. The cut premise was unsatisfiable on a head that adds nothing at all to the release it blocked.

Fixed in the TRAIN, not the trigger. Emitting a receipt for a sha the lane never rebuilt would mean fabricating deployed_revision or inventing a "no rebuild needed" verdict — the train's decision relocated, not removed.

What changed

AC1 — nearest runtime-affecting ancestor. The premise resolves the newest commit R at or below the head such that no commit in R..HEAD is runtime-affecting, and asks for R's receipt. The CUT detail names both shas and the count of commits walked past. One runtime-affecting commit in that gap voids the inheritance and the premise refuses, naming that commit. The release is still cut at the head; inheriting a lane proof never moves the commit being released.

AC2 — one classifier. The predicate moved to scripts/runtime_change_classifier.py, and trigger_rebuild_on_merge.py now re-exports every name from it — the same objects, not copies, so all 87 of that file's existing tests pass unchanged. The train reads the same module. A second path list would let the train inherit a lane proof across a commit the trigger thought changed the lane. The move was required: the trigger imports click and pydantic at module scope, while the train is stdlib-plus-pyyaml on bare python3 before any project install. A test greps the train for every literal pattern and fails if one appears.

AC3 — pending is not absent. lab_receipt_pending is returned when a trigger run for the candidate is still in flight. The old detail said the sha "has not been exercised on the compose dev lane", which was false in that state and sent a lane on a four-hour investigation of a working system.

AC4 — the policy note. lab_evidence_note claimed a receipt "for every merge" and printed that on every decision row. Corrected for omnibase_infra and omnimarket; a test asserts the phrase cannot return.

AC5 — keyed on the merge commit. Receipt lookups take a default-branch commit, never a workflow run's head sha. On a squash-only repo those differ by construction, so a query keyed by the run's head is a false zero that reads exactly like a finding. A test proves the pull request head sha is never passed to the artifact query.

Fail-closed, and no override

A classifier that cannot be loaded, a branch listing that raises, an exhausted walk, and a pending probe that raises all fall back to the exact-head premise — the pre-change behaviour, which refuses rather than inherits. The workflow's new sibling checkout is continue-on-error, so a failed fetch degrades the premise instead of failing the decision, and the row says so. There is no force input, no skip input and no way to assert the premise from outside; a test reads the parser's own option strings so adding one is a red test rather than a review catch.

RED first: the new test file failed 10 of 15 against the unmodified train (the 5 passing were the grep-shaped AC2 assertions and the unchanged fallback). Green after: 17/17, and 250 tests across every file touching the train, the trigger, the clean-root validator and the incident replays. pre-commit run --all-files exit 0. ruff check, ruff format --check and mypy clean on all three scripts.

Live proof, against the real clone, the real omniclaude validator and the live artifact API. The imported classifier reproduces the trigger's own published/not-published decision on all eight of the dev commits the diagnosis tabulated: 22745243f runtime-affecting, the other seven not — exactly matching the Verify dev lane applied the redeploy => skipped readback on each of those runs.

Running the train's own plan for omnibase_infra against real dev HEAD:

| omnibase_infra | CUT | 0.38.32 | `22745243f49b` | unreleased_work_lab_proven |

The inheritance path was exercised end to end by replaying the state at 06:40Z, when dev HEAD was the workflow-only 011d3c3ca: the walk skipped 7 non-runtime commits, resolved the runtime-affecting ancestor cf1645ddc, found its receipt (live artifact query, total_count=1), downloaded it, and returned lab_receipt_fail naming the six checks that did not pass. Before this change that same head could only ever have returned lab_receipt_absent — an unactionable reason on a sha that could never carry a receipt.

Rule 24(d) — lab statement

This is a CI decision script, a shared classifier module and a policy note. It runs on the runner, not on the dev lane: nothing here is in the runtime image, no compose service changes, and no tenant-scoped path is touched. The lab pass therefore does not cover this change and none is claimed. The premise it decides was instead proven directly against the live lab-pass receipt surface and the real dev history, as above.

Not dispatched, deliberately

A workflow_dispatch of the train on this branch would run the cut job, and omnibase_infra currently verdicts CUT — that would open a real release PR on unreviewed logic. The local run above exercises the identical code path; the workflow supplies two arguments and nothing else. The first dispatched run is the scheduled 07:11 UTC one after this merges.

Concurrency

Inventoried before starting: open PRs #3741 (scripts/deploy-runtime.sh, lane omn18656), #3742, #3743, #3410, #3247, #2658 touch none of these files, and neither does the omn18662 tagger lane. CLAIM row appended via scripts/ledger_lock.py, token LCT1-4189480-4000-feaf8ee20c47-2026-09-18T07:00:30Z.

Evidence-Ticket: OMN-18664
Evidence-Source: OCC#10173

…-affecting ancestor's receipt

The train's lab premise asked for a compose-dev lab-pass receipt naming the
EXACT dev head. runtime-rebuild-trigger.yml emits that artifact only for a
runtime-affecting merge, so a workflow-only or scripts-only merge landing last
has no receipt, at any time, and never will -- seven of the eight dev merges
before run 35316314098 carried none, by design. The cut premise was therefore
unsatisfiable on a head that adds nothing to the release it blocks.

Fixed in the train, not the trigger. Emitting a receipt for a sha the lane never
rebuilt would mean fabricating deployed_revision or inventing a "no rebuild
needed" verdict, which relocates the train's decision rather than removing it.

The premise now resolves the newest commit R at or below the head such that no
commit in R..HEAD is runtime-affecting, and asks for R's receipt. One
runtime-affecting commit in that gap voids the inheritance and the premise
refuses, naming that commit.

One classifier. The runtime-affecting predicate moved to
scripts/runtime_change_classifier.py, which trigger_rebuild_on_merge.py now
re-exports every name from -- the same objects, not copies. The train reads the
same module. A second path list would let the train inherit a lane proof across
a commit the trigger thought changed the lane. The move was needed because the
trigger imports click and pydantic at module scope while the train is
stdlib-plus-pyyaml on bare python3 before any project install.

A pending rebuild is no longer reported as an absent receipt. lab_receipt_pending
is returned when a trigger run for the candidate is still in flight; the old
detail string said the sha had never been exercised, which sent a lane on a
four-hour investigation of a working system.

Receipt lookups stay keyed on the branch commit. On a squash-only repo a run
carries the pull request head and the receipt is named for the merge commit, so
a query keyed by the run's head is a false zero that reads as a finding.

Fails closed throughout: a classifier that cannot be loaded, a branch listing
that raises, an exhausted walk and a pending probe that raises all fall back to
the exact-head premise, which refuses rather than inherits. No force input, no
skip input, and a test reads the parser's own option strings so adding one is a
red test.

The policy file's lab_evidence_note claimed a receipt "for every merge" and
printed that on every decision row for the repo. Corrected for omnibase_infra
and omnimarket, and a test asserts the phrase cannot return.
@jonahgabriel
jonahgabriel enabled auto-merge (squash) September 18, 2026 07:25
jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 18, 2026
…ibase_infra#3745 (#10173)

* evidence(OMN-18664): author OCC companion for OmniNode-ai/omnibase_infra#3745

OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head b93c0e4051107259b155a79e5f478a8f56e07030.

* evidence(OMN-18664): self-bind OCC#10173 + rebind contract_sha256

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>
@github-actions

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Hostile Reviewer — DEGRADED (informational)

Critical findings: 0
Major findings: 0
Total findings: 0
Models succeeded: glm-review

Note: Fewer than 2 reviewer models succeeded. Degraded results are informational (OMN-8468/OMN-8524) and do not block merge. Error: cli_review exit 2 (fewer than 2 models succeeded — partial/total outage)


Semantics (OMN-17492 — the model finds, thread resolution gates)

Surface Meaning Blocks merge?
Review threads Per-finding, posted by the reviewer No (informational)
Hostile Review Thread Gate Deterministic: unresolved hostile-reviewer threads exist Fails until resolved (not yet a required context)
degraded verdict Fewer than 2 models succeeded (infra) No

Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review: qwen3-review, qwen3-review-b, glm-review (OMN-8468/OMN-8524/OMN-17492)

@jonahgabriel
jonahgabriel merged commit 0dfbf89 into dev Sep 18, 2026
190 of 200 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-18664-train-lab-premise-nearest-runtime-ancestor branch September 18, 2026 08:07
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