Skip to content

feat(OMN-16001): enforce-everything CI gate — L4 external-context assertion - #2084

Merged
jonahgabriel merged 3 commits into
devfrom
jonah/omn-16001-ci-gate-enforcement-omnimarket
Aug 17, 2026
Merged

jonahgabriel merged 3 commits into
devfrom
jonah/omn-16001-ci-gate-enforcement-omnimarket

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Extends scripts/ci/ci_summary_gate.py's CI Summary poller (already the required umbrella context on both dev and main) with a 4th layer, EXPECTED_EXTERNAL_CONTEXTS, that asserts jobs produced by OTHER workflow files against the PR head SHA's commits/{sha}/check-runs — fail-closed (missing/skipped/non-success all block; present+success required). This is the enforce-everything build for OmniNode-ai/omnimarket per the fleet CI-enforcement plan.

No branch-protection mutation was needed or made — CI Summary is already required on both dev (33 contexts) and main (28 contexts), so the L4 layer flips every entry below to blocking transitively.

Gaps closed (live-verified 2026-08-13 via gh api repos/OmniNode-ai/omnimarket/branches/{dev,main}/protection/required_status_checks)

Context Was required on Now enforced via
fsm-handler-drift neither branch L4
skill-mapping-input-coverage-gate neither branch L4
node-migration-vendor-parity-gate neither branch (never tracked) L4 (+ removed its paths: filter — the job already had the correct in-job short-circuit)
node-drift-gate main only L4
contract-validation main only L4
deploy-gate / deploy-gate main only L4
validate (validator-runtime-profiles.yml) neither — and its own header claimed the wrong required-status-check name (Runtime Profiles / validate, which is factually false: the job has no job-level uses:, so GitHub names its check-run bare validate, same as the sibling state-coverage-gate job) L4

The 7th entry (validate) was not in the source plan's named target list — it was found mechanically by the new completeness test (test_every_pr_triggered_job_is_classified), which is exactly the point of that test.

Other changes

  • .github/workflows/ci.yml: the ci-summary job now additionally fetches commits/{sha}/check-runs for the PR head SHA (not the run's own merge-commit SHA) each poll cycle and passes --check-runs-file/--actor to the gate script.
  • .github/workflows/security-scan.yml: added a pull_request trigger (previously schedule/push/workflow_dispatch only, so PR content was never scanned — dependency-scan's if: github.event_name == 'pull_request' step was dead code); dropped the || true from the enforcing Safety Check invocation (kept || true only on the diagnostic JSON-capture line feeding the uploaded artifact). The three resulting jobs (Dependency Security Scan, Secret Scanning, CodeQL Security Analysis) are deliberately NOT yet asserted in L4 — they are unproven PR-event reporters (never posted a check-run on a pull_request event before this PR), and promoting an unproven reporter straight into an asserted/required layer is the documented wedge trap. Follow-up PR after one observed green run.
  • .github/required-checks.yaml: corrected the CI Summary row's stale branch: main — live state (re-verified today) is required on both dev and main.
  • .github/workflows/validator-fsm-handler-drift.yml, skill-mapping-input-coverage-gate.yml, validator-runtime-profiles.yml: corrected false in-file "required status check" claims.

Deliberate deviation from the source plan

The plan asked to "re-add rows for fsm-handler-drift, skill-mapping-input-coverage-gate, node-migration-vendor-parity-gate" to .github/required-checks.yaml. I did not do this: none of the three is live-required directly on branch protection, and the manifest's own header explicitly documents a Migration Safety procedure ("flip branch protection first... then update this file, so the reconcile job never observes a divergence window"). Adding mode: REQUIRED rows for contexts branch protection does not carry would desync the manifest from its own reconcile_manifest_vs_live.py check. These three stay enforced via L4 only; the manifest rows are a follow-up gated on an actual branch-protection flip (not required — the L4 layer already makes them blocking).

Exemptions (all EXEMPT_CONTEXTS in the test file, one-line reason each)

25 (workflow file, job) pairs are classified EXEMPT — automation/observer jobs (auto-merge enabler, OCC companion author/observer/attestation, post-merge publishers), self-declared staged/deferred promotions (receipt-honesty, shell-hygiene, dep-health-gate Phase 1, product-readiness-shadow Phase-3 canary), duplicate-name internal precondition-wait jobs (OCC Preflight Dependency producers in 5 other workflow files — the real gate, occ-preflight / eligibility, IS asserted), two path-filtered validators explicitly out of this wave's scope (market-skill-baseline, plugin-compat-gate), and the three newly-triggered security-scan.yml jobs pending proof. Full list + reasons in tests/unit/scripts/ci/test_ci_summary_gate.py::EXEMPT_CONTEXTS.

Gate evidence

  • uv run pytest tests/unit/scripts/ci/test_ci_summary_gate.py -v → 41 passed (re-verified on the replacement branch, rebased onto current dev), including:
    • The completeness anchor test_every_pr_triggered_job_is_classified — parses every .github/workflows/*.yml, derives every job reachable from on.pull_request targeting dev, asserts full coverage by STRICT | SKIPPABLE | EXTERNAL | EXEMPT_CONTEXTS.
    • test_falsification_control_each_external_entry_is_load_bearing — deleting any one EXPECTED_EXTERNAL_CONTEXTS entry flips a red fixture from FAILURE to SUCCESS, proving every entry is load-bearing.
    • test_red_replay_deploy_gate_red_now_fails — replays omnimarket#1968's shape (deploy-gate red, CI Summary green on the same head) and proves the L4 layer now evaluates FAILURE.
    • test_no_asserted_external_workflow_has_a_pull_request_paths_filter, actor-conditional (dependabot[bot] / gate / CodeRabbit Thread Check), missing/skipped/failure/pending semantics, dedup tie-breaking.
  • pre-commit run --all-files → all hooks green on the replacement branch.

Replaces #2065

This PR supersedes #2065, closed in favor of this replacement. Same two commits (4e1c7f1a, c3ddaa6d), cherry-picked unchanged onto a correctly-named branch. #2065's branch (jonah/omn-ci-gate-enforcement-omnimarket) carries no ticket token and cannot satisfy the F-12 Evidence-Ticket branch-identity gate (scripts/ci/check_branch_identity.py / validator_receipt_gate) for any value of the trailer — live-verified: identity check FAILS against that branch name, PASSES against this one. Renaming #2065's branch in place is forbidden (F-11, branch-rename-on-open-PR prohibition — renaming closes the PR). No content change versus #2065 beyond the branch rebase.

Ticket

OMN-16001

dod_evidence: see Gate evidence above — 41/41 unit tests, pre-commit all-green on the replacement branch.

Evidence-Ticket: OMN-16001
Evidence-Source: OCC#6574

…ertion

Extend the CI Summary poller (scripts/ci/ci_summary_gate.py) with a 4th
layer, EXPECTED_EXTERNAL_CONTEXTS, that asserts jobs produced by OTHER
workflow files against the PR head SHA's commits/{sha}/check-runs,
fail-closed (missing/skipped/non-success all block). CI Summary is
already the required umbrella context on both dev and main, so this
flips every entry to blocking transitively with zero branch-protection
mutation.

Closes six live gaps: fsm-handler-drift, skill-mapping-input-coverage-gate,
node-migration-vendor-parity-gate (never required anywhere), node-drift-gate,
contract-validation, deploy-gate / deploy-gate (main-only, unenforced on
dev). Closes a 7th found mechanically by the new completeness test:
validator-runtime-profiles.yml's "validate" job self-declared a required
context name ("Runtime Profiles / validate") that was both never live and
factually wrong (the job has no job-level `uses:`, so GitHub names its
check-run bare "validate", same as the sibling state-coverage-gate job).

Also: removed node-migration-vendor-parity-gate.yml's paths: filter (the
job already had the correct in-job short-circuit); added a pull_request
trigger to security-scan.yml (previously schedule/push-only, so PR
content was never scanned) and dropped the `|| true` from the enforcing
Safety Check invocation; corrected required-checks.yaml's stale
`branch: main` on the CI Summary row (live: both branches).

tests/unit/scripts/ci/test_ci_summary_gate.py: L4 behavioral tests,
falsification control per asserted entry, a RED-REPLAY fixture for
omnimarket#1968, and the completeness anchor
test_every_pr_triggered_job_is_classified — parses every
.github/workflows/*.yml, derives every job reachable from
on.pull_request targeting dev, and asserts full coverage by
STRICT | SKIPPABLE | EXTERNAL | EXEMPT_CONTEXTS (each exemption
carries a one-line reason). A newly added, unclassified workflow job
now fails CI until triaged.
…ks:read, PR head SHA

L4 is opt-in at the CLI: --check-runs-file defaults to None and main() skips
the entire external-context layer when absent, so ci.yml's invocation is the
single load-bearing wire for all 41 EXPECTED_EXTERNAL_CONTEXTS assertions.
Before this commit a one-line ci.yml refactor could silently revert the gate
to pre-L4 behavior with every unit test still green.

Three falsifiable pins (each verified to fail under mutation of ci.yml):
- test_ci_yml_wires_l4_check_runs_file_and_actor
- test_ci_summary_job_can_read_check_runs (checks: read -> 403 -> empty
  fallback -> permanent wedge)
- test_ci_summary_l4_uses_pr_head_sha_not_merge_sha (merge SHA carries no
  other workflows check-runs)

Test-only; no gate-direction change.
@coderabbitai

coderabbitai Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 48 minutes

Limit details: You’ve used all 1 included review currently available under your plan. You completed 112 included PR reviews in the past 7 days; at that activity level, included reviews refill at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0f9b42d4-084b-4c37-9c2a-4415d88bcd27

📥 Commits

Reviewing files that changed from the base of the PR and between 0b55f22 and 65f8d32.

📒 Files selected for processing (9)
  • .github/required-checks.yaml
  • .github/workflows/ci.yml
  • .github/workflows/node-migration-vendor-parity-gate.yml
  • .github/workflows/security-scan.yml
  • .github/workflows/skill-mapping-input-coverage-gate.yml
  • .github/workflows/validator-fsm-handler-drift.yml
  • .github/workflows/validator-runtime-profiles.yml
  • scripts/ci/ci_summary_gate.py
  • tests/unit/scripts/ci/test_ci_summary_gate.py

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

✅ Architectural Review — PASSED

Errors: 0
Warnings: 0

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

No architectural violations found.

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

@github-actions

github-actions Bot commented Aug 17, 2026 •

Copy link
Copy Markdown

✅ Hostile Reviewer — PASSED

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


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)

jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Aug 17, 2026
…imarket#2084 (#6574)

* evidence(OMN-16001): author OCC companion for OmniNode-ai/omnimarket#2084

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

* evidence(OMN-16001): self-bind OCC#6574 + rebind contract_sha256

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>
@jonahgabriel
jonahgabriel merged commit 183bbc9 into dev Aug 17, 2026
125 of 130 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-16001-ci-gate-enforcement-omnimarket branch August 17, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant