Skip to content

feat(OMN-19888): scheduled heals update release-window reds and re-run vendor-parity reds once their cause is gone - #3026

Merged
jonahgabriel merged 2 commits into
devfrom
jonah/omn-19888-omnimarket-heals-release-window-vendor-parity
Sep 27, 2026
Merged

jonahgabriel merged 2 commits into
devfrom
jonah/omn-19888-omnimarket-heals-release-window-vendor-parity

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

OMN-19888: scheduled heals for release-window and vendor-parity reds

Ticket: OMN-19888 (child of OMN-19852). Source: the omnimarket stall diagnosis, ledger TERMINAL 2026-09-27T16:07:43Z lane=market-armed-stall-83, findings 3 and 4.

What this fixes

Two required reds on omnimarket PRs are caused by something outside the PR, and neither one clears when that cause goes away.

  1. Release window. Every dev merge publishes a release, and the post-release bump PR moves dev off the published version 10-14 minutes later. A PR whose CI starts inside that window fails Release Identity Gate. A rerun replays the same pinned merge ref, so only a branch update clears it (fix(OMN-19234): the bus receipt names the backend key that answered, not uuid5 of the model id #3009, feat(OMN-19513): node_projection_claude_hook_events -- every Claude Code hook, with subagent lineage #2956, feat(OMN-19513): the emit registry routes hook.event and redaction governs nested members by dotted name #2955, feat(OMN-19550): full-content capture topic, a span-scrub capture class and a session_content projection #2905 on 2026-09-27).
  2. Vendor parity. node-migration-vendor-parity-gate fails until omnibase_infra dev vendors the PR's migration. Nothing reruns it afterwards, and CI Summary asserts it as an external context.

What this adds

  • scripts/ci/pr_stale_red_heal.py follows the shape of occ_companion_merge_heal.py (OMN-18812). It has two pure decision functions, a GhPort protocol, and one enumerated outcome per branch. An unreadable open-PR list exits red, and so does a pass where every write fails.
    • Release window: for an open, non-draft, dev-based, non-conflicted PR, the heal runs update-branch pinned to expected_head_sha when all three hold:
      • its newest Release Identity Gate failed naming a version below dev's current one;
      • dev is out of the window (its version is ahead of the newest tag);
      • the pinned update means at most one update per head.
    • Vendor parity: the heal reruns the parity run and, when it is the only red in its run, the CI Summary job, when both hold:
      • every migration the gate named is byte-identical on infra dev;
      • each one reached dev after the gate failed. The landing time is the infra PR's merged_at, not the squash commit's date. On omnibase_infra#4206 the merge queue dated the commit 15:38:41Z, and it merged at 16:01:07Z.
    • A failure after the vendor landed is a real red and is left alone. That same rule is what makes the rerun happen once per head.
  • .github/workflows/pr-stale-red-heal.yml runs every 10 minutes, offset 5 minutes from the companion heal. It also runs on push to dev touching pyproject.toml (the bump PR merging) and on workflow_dispatch (pr-number, heal, dry-run).
    • It has no pull_request trigger and no continue-on-error, and it is not a required context.
    • actions: write is scoped to its one job.
    • The branch update uses an onexbot-occ-writer token scoped to this repository, the same mint release-on-merge.yml uses. An update-branch authored by GITHUB_TOKEN starts no workflow on the new head. Without the token, the update is refused, not issued.
  • tests/ci/test_pr_stale_red_heal_omn19852.py has 54 tests, including the ticket's AC falsifiers:
    • -k release_window: 20 pass
    • -k release_window_refuses: 14 pass
    • -k vendor_parity: 22+ pass
    • -k vendor_parity_refuses: 15+ pass
    • -k workflow: 5 pass

Why not bulk_pr_throttle.py

Lanes route bulk update-branch and rerun through omnibase_infra's bulk_pr_throttle.py. This scheduled workflow cannot use it, for two reasons:

  • Its runner-capacity probe needs an org-read credential this workflow does not hold. CROSS_REPO_PAT is being retired under OMN-16373.
  • Its update-branch cannot pin expected_head_sha.

The script applies the same bound itself: at most 5 branch updates and 10 rerun PRs per pass, with the rest deferred to the next pass.

Controls (live, read-only; no write was issued)

Checks

  • ruff format / ruff check clean on the new files.
  • mypy --strict clean on the module and the test.
  • pre-commit run --files on the three files: rc 0.
  • check_action_pins.py OK. check_workflow_module_refs.py PASS.
  • The workflow-sweeping suites pass: test_ci_summary_gate.py, test_self_hosted_sibling_clone_hygiene.py and the OMN-18812 heal suite (246 tests).

Lab

The change is CI-only: a workflow, a script under scripts/ci/ and a test. It touches nothing under src/, docker or migrations. It is not runtime-affecting, so there is no lab pass to cite. There is also no tenant, RLS or reader path.

No collision with omnimarket#3023, which edits occ_companion_merge_heal.py, its workflow and its test. This PR touches none of those files.

Evidence-Ticket: OMN-19888
Evidence-Source: OCC#11670

…ty reds once their cause is gone

A PR synced inside a release window fails Release Identity Gate and a rerun
replays the same merge ref; a PR whose migration was vendored into
omnibase_infra dev after its parity gate failed stays red because nothing
reruns the gate. pr_stale_red_heal.py decides both from live reads and acts
once per head: a branch update pinned to expected_head_sha (App token, so the
new head gets CI) when the failed version is below dev and dev is out of the
window; a rerun of the parity run plus CI Summary when every named migration
is byte-identical on infra dev and was vendored after the gate failed.

Onex-Lane: market-heals-83
Onex-Session: 73ed3d50de9e420c9d831fe17a2275a3
…its merge-queue commit date

omnibase_infra#4206's squash commit is dated 15:38:41Z and reached dev at
16:01:07Z; a parity gate that failed at 15:53:01Z ran before the bytes landed.
Reading the committer date misclassified it as a real red.

Onex-Lane: market-heals-83
Onex-Session: 73ed3d50de9e420c9d831fe17a2275a3
@github-actions

Copy link
Copy Markdown

⚠️ Architectural Review — WARNINGS

Errors: 0
Warnings: 1

What this checks

Rule Description
ARCH-TOPIC-001 No hardcoded Kafka topic strings in handler code
ARCH-DI-001 No event_bus=None bypass
ARCH-DI-002 No direct Handler instantiation outside workflow_runner/adapters
ARCH-DI-003 No reinvented DI containers
ARCH-TOPIC-002 contract.yaml topics follow `onex.{cmd

ARCH-DI-002: Direct Handler instantiation (warning)\n\n```\nsrc/omnimarket/nodes/node_projection_delegation/handlers/handler_delegation.py:1909: row.update(HandlerDelegationCohortKeyFold().handle(event).row_columns())

src/omnimarket/nodes/node_projection_delegation/handlers/handler_delegation.py:1914: ticket = HandlerDelegationTicketFold().handle(event)
src/omnimarket/nodes/node_projection_delegation/handlers/handler_delegation.py:1926: caller_lane = HandlerDelegationCallerLaneFold().handle(event)
src/omnimarket/nodes/node_projection_delegation/handlers/handler_projection_delegation.py:993: row.update(HandlerDelegationCohortKeyFold().handle(event).row_columns())
src/omnimarket/nodes/node_projection_delegation/handlers/handler_projection_delegation.py:1011: ticket = HandlerDelegationTicketFold().handle(event)
src/omnimarket/nodes/node_projection_delegation/handlers/handler_projection_delegation.py:1023: caller_lane = HandlerDelegationCallerLaneFold().handle(event)\n```\n\nHandler classes should be wired only in workflow_runner.py or adapter modules. Direct instantiation elsewhere bypasses the contract system.\n\n

Static architectural lint — no model inference (OMN-14176).

onexbot-occ-writer Bot added a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 27, 2026
…nimarket#3026

The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited.

Ticket: OMN-16859 (AC3b)
Onex-Workflow: OCC Receipt Runner
Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36333868449
@jonahgabriel
jonahgabriel enabled auto-merge (squash) September 27, 2026 16:37
@github-actions

Copy link
Copy Markdown

✅ Hostile Reviewer — PASSED

Blocking findings (critical/error): 0
Total findings: 12
Models succeeded: qwen3-review,gpt-oss-review


Gate semantics

Verdict Meaning Blocks merge?
passed >=2 models succeeded, no critical/error findings No
blocked CRITICAL or ERROR findings found Yes
degraded Fewer than 2 models succeeded (infra unavailable/timeout) Yes (OMN-15110)

Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)

class GhPort(Protocol):
"""The GitHub reads and writes both heals need."""

def open_pull_requests(self, *, repo: str) -> tuple[OpenPr, ...]: ...

def open_pull_requests(self, *, repo: str) -> tuple[OpenPr, ...]: ...

def check_runs(self, *, repo: str, head_sha: str) -> list[dict[str, object]]: ...

def check_runs(self, *, repo: str, head_sha: str) -> list[dict[str, object]]: ...

def job_log(self, *, repo: str, job_id: int) -> str: ...

def job_log(self, *, repo: str, job_id: int) -> str: ...

def job(self, *, repo: str, job_id: int) -> dict[str, object]: ...

def job(self, *, repo: str, job_id: int) -> dict[str, object]: ...

def run_jobs(self, *, repo: str, run_id: int) -> list[dict[str, object]]: ...

Any other failure raises :class:`RuntimeError`.
"""
...
The merge time of the PR that landed it when there is one, else the
commit's committer date; ``""`` when unread.
"""
...

def update_branch(
self, *, repo: str, pr_number: int, expected_head_sha: str
) -> None: ...
self, *, repo: str, pr_number: int, expected_head_sha: str
) -> None: ...

def rerun_run(self, *, repo: str, run_id: int) -> None: ...

def rerun_run(self, *, repo: str, run_id: int) -> None: ...

def rerun_job(self, *, repo: str, job_id: int) -> None: ...
jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 27, 2026
* evidence(OMN-19888): author OCC companion for OmniNode-ai/omnimarket#3026

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

* evidence(OMN-19888): self-bind OCC#11670 + rebind contract_sha256

* evidence(OMN-16859): executed test_passes receipts for OmniNode-ai/omnimarket#3026

The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited.

Ticket: OMN-16859 (AC3b)
Onex-Workflow: OCC Receipt Runner
Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36333868449

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>
Co-authored-by: onexbot-occ-writer[bot] <307849072+onexbot-occ-writer[bot]@users.noreply.github.com>
@jonahgabriel
jonahgabriel merged commit fc80fc6 into dev Sep 27, 2026
179 of 192 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-19888-omnimarket-heals-release-window-vendor-parity branch September 27, 2026 17:23
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.

2 participants