Repository navigation
feat(OMN-20298): shape-gate detectors run on every PR, whatever the preflight says - #4429
Conversation
Moves canonical handler-shape, flip-bundle seam, and Plugin* lifecycle guards out of the lint job into independent CI jobs to prevent skip-on-failure via `needs: [occ-preflight, route]`. Adds canonical-handler-shape-gate, no-plugin-daemon-classes-gate, and shape-gate-independence jobs in .github/workflows/ci.yml. The latter validates detector independence using pinned omnibase_core commit 5220ecf1758b4475c2963ec13171b6431fdc2224 (PR 1833 head). Updates STRICT_GATE_JOBS in scripts/ci/ci_summary_gate.py and config/runner_routing_policy.yaml. Adds pre-commit hook check-shape-gate-independence and new test tests/ci/test_shape_gate_jobs_independent_omn20298.py. Adjusts tests/ci/test_lint_validator_runner.py for the new job structure.
| @@ -672,15 +674,70 @@ jobs: | |||
| --baseline scripts/ci/canonical_handler_shape_baseline.py \ | |||
| --receipts-dir scripts/ci/adequacy_receipts | |||
|
|
|||
| - name: Run mypy type checking | |||
| # OMN-18640: scripts/deploy-agent/deploy_agent is IN the scope. It is | |||
| # the code that runs every deploy on the lab lane and it sat outside | |||
| # the type gate carrying ten errors, three of which were functions | |||
| # declared to return `str` while returning `Any`. Its tests have their | |||
| # own workflow because it is a standalone uv sub-project; its TYPES are | |||
| # checked here, with the root project's mypy, because that is where | |||
| # this repository declares type scope. | |||
| run: uv run mypy src/omnibase_infra scripts/deploy-agent/deploy_agent | |||
| no-plugin-daemon-classes-gate: | |||
| name: No Plugin Daemon Classes Gate (OMN-20298) | |||
| runs-on: >- | |||
| ${{ | |||
| (github.event_name == 'pull_request' && | |||
| github.event.pull_request.head.repo.full_name != github.repository) | |||
| && fromJSON(vars.OMNI_PUBLIC_PR_RUNS_ON_JSON || '["ubuntu-latest"]') | |||
| || fromJSON((github.event_name == 'merge_group' && vars.OMNI_REQUIRED_CI_RUNS_ON_JSON) || vars.OMNI_TRUSTED_CI_RUNS_ON_JSON || '["self-hosted","omnibase-ci"]') | |||
| }} | |||
| timeout-minutes: 30 | |||
| steps: | |||
| - name: Checkout code | |||
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |||
| with: | |||
| fetch-depth: 2 | |||
|
|
|||
| - name: Setup Python and uv | |||
| uses: ./.github/actions/setup-python-uv | |||
| with: | |||
| python-version: ${{ env.PYTHON_VERSION }} | |||
| uv-version: ${{ env.UV_VERSION }} | |||
| cache-version: ${{ env.CACHE_VERSION }} | |||
| cache-enabled: "false" | |||
|
|
|||
| # OMN-19613: the guard is an AST check on each file's own classes, so a | |||
| # file the PR did not touch cannot turn it red. On pull_request it scans | |||
| # only the PR's files; it scans the whole tree on push (which proves the | |||
| # merged union on dev, OMN-18835), merge_group and dispatch, when the PR | |||
| # changes .pre-commit-config.yaml or this workflow, when the PR moves the | |||
| # omnibase-core pin in uv.lock (the validator's code lives in core), and | |||
| # whenever the base cannot be resolved. The step always runs; only the | |||
| # file list narrows, so the check never goes missing from a PR. | |||
| - name: Check Plugin* lifecycle class guard (OMN-13284, relocated to omnibase_core) | |||
| env: | |||
| EVENT_NAME: ${{ github.event_name }} | |||
…12154) * evidence(OMN-20298): author OCC companion for OmniNode-ai/omnibase_infra#4429 OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head 639752d1bdc9969e3857b5c06feb1e3be46fa741. * evidence(OMN-20298): self-bind OCC#12154 + rebind contract_sha256 --------- Co-authored-by: omnimarket-bot <bot@omninode.ai>
There was a problem hiding this comment.
Hostile Reviewer — adversarial findings (OMN-17492)
Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 0
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 10
Nit-level findings suppressed: 0
The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.
Below quorum: 10 finding(s) raised by one model only (OMN-18479)
These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.
- [CRITICAL]
.github/workflows/ci.yml(qwen3-review) — Unpinned external repository checkout in CI job | The new 'canonical-handler-shape-gate' job checks out 'OmniNode-ai/omnibase_core' using 'ref: dev'. This is a moving target. An attacker with write ac - [MAJOR]
.pre-commit-config.yaml(qwen3-review) — Pre-commit hook uses unpinned repository URL | The new pre-commit hook 'check-shape-gate-independence' is sourced from 'https://github.com/OmniNode-ai/omnibase_core'. While 'rev' is pinned to a SHA, t - [MAJOR]
tests/ci/test_shape_gate_jobs_independent_omn20298.py(qwen3-review) — Test assertion for strict gate is fragile | The test 'test_detector_job_is_a_strict_ci_summary_gate' checks if the display name is present in the 'ci_summary_gate.py' file by reading the file as text - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — Full repository checkout replaces shallow fetch | The checkout step in the main CI job no longer specifiesfetch-depth: 2, causing a full repository clone. This increases network I/O and storage usa - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — Removal of Plugin* lifecycle class guard eliminates validation | The step that runspre-commit run no-plugin-daemon-classeshas been deleted. Without this guard, prohibited plugin daemon classes can - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — Shape‑gate‑independence job lacks repository checkout | Theshape-gate-independencejob runs a Python module that expects the repository source tree, but the job does not perform an `actions/checkou - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — New canonical‑handler‑shape‑gate job adds CI latency | Introducing thecanonical-handler-shape-gatejob adds an extra CI stage that performs a full checkout (fetch-depth: 0) and runs a classifier - [MINOR]
.github/workflows/ci.yml(qwen3-review) — Duplicated runner routing logic in three jobs | The 'runs-on' expression for 'canonical-handler-shape-gate', 'no-plugin-daemon-classes-gate', and 'shape-gate-independence' is identical and complex. Th - [MINOR]
.github/workflows/ci.yml(qwen3-review) — Missing error handling for external dependency failure | The 'canonical-handler-shape-gate' job depends on the 'omnibase_core' repository. If the repository is unavailable or the checkout fails, the j - [MINOR]
.github/workflows/ci.yml(gpt-oss-review) — Fallback to GITHUB_TOKEN grants write permissions | Thecanonical-handler-shape-gatejob usestoken: ${{ secrets.OMNIBASE_CORE_TOKEN || secrets.GITHUB_TOKEN }}. If the secret is absent, the job fa
✅ Hostile Reviewer — REVIEWEDCritical findings: 1
Semantics (OMN-17492 — the model finds, thread resolution gates)
Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review: qwen3-review (Qwen3.8-27B), gpt-oss-review (gpt-oss-120b) (OMN-8468/OMN-8524/OMN-17492) |
There was a problem hiding this comment.
Hostile Reviewer — adversarial findings (OMN-17492)
Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 2
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 9
Nit-level findings suppressed: 0
The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.
Below quorum: 9 finding(s) raised by one model only (OMN-18479)
These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.
- [CRITICAL]
.github/workflows/ci.yml, canonical-handler-shape-gate job, 'Checkout omnibase_core validator source' step(qwen3-review) — Unpinned omnibase_core checkout via mutable 'dev' ref in new CI job | The new 'canonical-handler-shape-gate' job checks out OmniNode-ai/omnibase_core at 'ref: dev'. A branch ref is mutable; the commit - [MAJOR]
.github/workflows/ci.yml, lint job, Checkout code step(qwen3-review) — Removed fetch-depth: 2 from lint job breaks precommit_diff_scope.py scoping | The diff removes 'fetch-depth: 2' from the 'lint' job's checkout step. The comment that was removed explicitly states that - [MAJOR]
.github/workflows/ci.yml, canonical-handler-shape-gate job, 'Canonical handler-shape ratchet' step(qwen3-review) — New shape-gate jobs lack error handling for missing omnibase_core checkout | The 'canonical-handler-shape-gate' job checks out omnibase_core into '.ci/omnibase_core' and then runs 'uv run python .ci/o - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — Shape‑gate jobs not tied to branch protection | The newly added detector jobs (canonical‑handler‑shape‑gate, no‑plugin‑daemon‑classes‑gate, shape‑gate‑independence) are registered as STRICT CI Summary - [MAJOR]
.github/workflows/ci.yml(gpt-oss-review) — Potential package name mismatch in uv dependency spec | The "shape‑gate‑independence" job installs a dependency using "omnibase-core" (hyphen) while the repository name is "omnibase_core" (underscore) - [MINOR]
.github/workflows/ci.yml, runs-on expressions in canonical-handler-shape-gate, no-plugin-daemon-classes-gate, shape-gate-independence(qwen3-review) — Duplicated runner routing logic across three new jobs | The three new jobs ('canonical-handler-shape-gate', 'no-plugin-daemon-classes-gate', 'shape-gate-independence') each contain an identical, compl - [MINOR]
.github/workflows/ci.yml, canonical-handler-shape-gate job, Checkout code step(qwen3-review) — fetch-depth: 0 in canonical-handler-shape-gate may be slower than necessary | The 'canonical-handler-shape-gate' job uses 'fetch-depth: 0' (full history) for the main repository checkout. The comment - [MINOR]
.github/workflows/ci.yml(gpt-oss-review) — Full history checkout increases CI duration | The "canonical‑handler‑shape‑gate" job checks out the repository with fetch‑depth: 0, pulling the entire git history. This can significantly increase chec - [MINOR]
.github/workflows/ci.yml(gpt-oss-review) — Fallback to GITHUB_TOKEN may grant excessive permissions | The checkout of the omnibase_core validator source uses "token: ${{ secrets.OMNIBASE_CORE_TOKEN || secrets.GITHUB_TOKEN }}". If OMNIBASE_CORE
Findings demoted from threads (anchor rejected)
-
[MINOR] hostile-reviewer (qwen3-review)
Test for shape-gate independence does not verify the actual validator logic | The new test file 'tests/ci/test_shape_gate_jobs_independent_omn20298.py' checks that the jobs have no 'needs' or 'if' and that their names appear in ci_summary_gate.py. It does not verify that the 'shape-gate-independence' job actually runs the validator correctly or that the validator's logic is sound. The test is a structural check, not a functional one. This is acceptable for a CI workflow test, but it means the actual validat
Resolve this thread when addressed — the
Hostile Review Thread Gateblocks while hostile-reviewer threads are unresolved (OMN-17492). -
[MINOR] hostile-reviewer (gpt-oss-review)
Missing test for shape‑gate‑independence job behavior | The new shape‑gate‑independence job is intended to refuse detector jobs that depend on the preflight, but there is no test verifying that it correctly detects and rejects such dependencies. Absence of coverage may allow regressions. | Evidence: Added tests cover detector job definitions and lint job steps, but no test exercises the "shape-gate-independence" job’s logic. | Fix: Add a unit test that simulates a detector job with a preflight dependency an
Resolve this thread when addressed — the
Hostile Review Thread Gateblocks while hostile-reviewer threads are unresolved (OMN-17492).
What was wrong
In
omnibase_infra, shape-gate detectors were steps of thelintjob (needs: [occ-preflight, route]). When preflight failed, these gates were skipped and produced no detection. The audit (knowledge-base-internal/reports/2026-10-01-gates-and-delegation-readiness-audit.mdsection 2) found that every shape-gate failure in the 30 days before 2026-10-01 in other repositories was caused by the preflight failing first.What this changes
.github/workflows/ci.ymlwith noneedsand noif:canonical-handler-shape-gate: runs the handler-shape ratchet and flip-bundle seam gate.no-plugin-daemon-classes-gate: runs the Plugin* lifecycle class guard.lintjob.shape-gate-independencejob runningomnibase_core.validators.shape_gate_independenceto refuse any detector job behind the preflight.check-shape-gate-independence.STRICT_GATE_JOBS(scripts/ci/ci_summary_gate.py) andconfig/runner_routing_policy.yaml.tests/ci/test_shape_gate_jobs_independent_omn20298.py; updatedtests/ci/test_lint_validator_runner.pyto read the plugin-daemon step from its new job.Pin
The pin is the head commit of the still-open
omnibase_corePR 1833 (5220ecf1758b4475c2963ec13171b6431fdc2224) and is bumped to the merged commit after it lands.Tests
8424 passed, 19 failed and 4 errors. All 19 failures and 4 errors are in
tests/ci/test_canonical_clone_ref_guard.py,test_canonical_clone_registry_roots.pyandtest_canonical_clone_guard_chains_hook_chain.py, which depend on the lab host git setup and do not touch this change.Out of scope
omnidash(a different owner's lane).Positive control
Bad sample:
.github/workflows/planted-shape-gate.ymlwith anocc-preflightjob and a detector jobcanonical-inference-gatewithneeds: occ-preflight.Hook, bad sample refused at
git commit(no commit created, HEAD stayed at 639752d):CI command on the bad sample (
python -m omnibase_core.validators.shape_gate_independence): exit=1, same finding.CI, bad sample refused: scratch draft PR #4428 (planted file committed through the GitHub API, because the local hook refuses the commit). Check-run
Shape-Gate Independence (OMN-20298)concluded failure: https://github.com/OmniNode-ai/omnibase_infra/actions/runs/36870290538/job/110396021988 . On the same runCanonical Handler-Shape Gate (OMN-20298)andNo Plugin Daemon Classes Gate (OMN-20298)concluded success. The scratch PR #4428 is closed and its branch deleted.Clean sample accepted: this PR's own commit passed the hook locally:
The CI result of the clean sample is this PR's own
Shape-Gate Independence (OMN-20298)check-run.Evidence-Ticket: OMN-20298
Evidence-Source: OCC#12154