Repository navigation
feat(OMN-16001): enforce-everything CI gate — L4 external-context assertion - #2084
Conversation
…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.
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. 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. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
Comment |
✅ Architectural Review — PASSEDErrors: 0 What this checks
No architectural violations found. Static architectural lint — no model inference (OMN-14176). |
✅ Hostile Reviewer — PASSEDBlocking findings (critical/error): 0 Gate semantics
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524) |
…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>
Summary
Extends
scripts/ci/ci_summary_gate.py'sCI Summarypoller (already the required umbrella context on bothdevandmain) with a 4th layer,EXPECTED_EXTERNAL_CONTEXTS, that asserts jobs produced by OTHER workflow files against the PR head SHA'scommits/{sha}/check-runs— fail-closed (missing/skipped/non-success all block; present+success required). This is theenforce-everythingbuild for OmniNode-ai/omnimarket per the fleet CI-enforcement plan.No branch-protection mutation was needed or made —
CI Summaryis already required on bothdev(33 contexts) andmain(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)fsm-handler-driftskill-mapping-input-coverage-gatenode-migration-vendor-parity-gatepaths:filter — the job already had the correct in-job short-circuit)node-drift-gatecontract-validationdeploy-gate / deploy-gatevalidate(validator-runtime-profiles.yml)Runtime Profiles / validate, which is factually false: the job has no job-leveluses:, so GitHub names its check-run barevalidate, same as the siblingstate-coverage-gatejob)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: theci-summaryjob now additionally fetchescommits/{sha}/check-runsfor the PR head SHA (not the run's own merge-commit SHA) each poll cycle and passes--check-runs-file/--actorto the gate script..github/workflows/security-scan.yml: added apull_requesttrigger (previously schedule/push/workflow_dispatch only, so PR content was never scanned —dependency-scan'sif: github.event_name == 'pull_request'step was dead code); dropped the|| truefrom the enforcing Safety Check invocation (kept|| trueonly 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 apull_requestevent 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 theCI Summaryrow's stalebranch: 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"). Addingmode: REQUIREDrows for contexts branch protection does not carry would desync the manifest from its ownreconcile_manifest_vs_live.pycheck. 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_CONTEXTSin 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-gatePhase 1,product-readiness-shadowPhase-3 canary), duplicate-name internal precondition-wait jobs (OCC Preflight Dependencyproducers 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-triggeredsecurity-scan.ymljobs pending proof. Full list + reasons intests/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 currentdev), including:test_every_pr_triggered_job_is_classified— parses every.github/workflows/*.yml, derives every job reachable fromon.pull_requesttargetingdev, asserts full coverage bySTRICT | SKIPPABLE | EXTERNAL | EXEMPT_CONTEXTS.test_falsification_control_each_external_entry_is_load_bearing— deleting any oneEXPECTED_EXTERNAL_CONTEXTSentry 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