Repository navigation
chore(OMN-15181): promote omnibase_infra dev->main — prod deploy-agent bootstrap unblock - #2475
jonahgabriel wants to merge 482 commits into
Conversation
…ion core, read-only) (#2206) * feat(OMN-13942): runner-fleet-maintain workflow — Increment 1 (detection core, read-only) Adds a canonical ONEX node workflow for runner-fleet health detection, closing the OMN-13932 buildx/codeload blind spot. Strictly read-only: no path in this PR restarts a runner, cancels a run, force-recreates a container, or dequeues/re-enqueues a merge-queue entry. New nodes (mirroring the same-repo node_merge_sweep_* trio and the omnimarket node_redeploy_orchestrator gate-then-effect-then-terminal-event topology): - node_runner_fleet_maintain_orchestrator (ORCHESTRATOR_GENERIC, new): coordinates the tick — start -> snapshot-gather -> health-evaluate -> terminal completed event. No I/O. - node_runner_fleet_health_compute (COMPUTE_GENERIC, new): pure/deterministic classifier. Ports collector_runner_health.py's crash-loop/offline logic, OMN-13915's _diag heartbeat-freshness rule, and OMN-13109's SILENT-WEDGE heuristic. Adds two NEW checks (BUILDX_UNAVAILABLE, CODELOAD_THROTTLED) that close the OMN-13932 gap. Emits recommended_actions that are recorded/ surfaced only — nothing here executes them. - node_runner_health_snapshot_effect (EFFECT_GENERIC): completed the OMN-6091 stub in place (same contract/topics declared since OMN-6082) with real gh-api + SSH/Docker gather logic, incl. the two new probes. Trigger: reuses OMN-13915's runner-fleet-canary 15-min GitHub-hosted schedule per design — no new parallel schedule. Also: - Register both new nodes in [project.entry-points."onex.nodes"] and regenerate the dispatch-selection-parity oracle and topic enums. - Add runtime_profiles: [effects] to all three new/completed contracts (ValidatorRuntimeProfiles gate). - Allowlist the 8 new infra-owned handler paths in infra-node-allowlist.txt (runner fleet is infra's domain object, not a market business workflow). - Baseline the orchestrator's inherent 3-hop payload_type_match ARCH-004 finding (same accepted shape as 6 sibling orchestrators already baselined). - Exempt two pattern-validator false positives (workflow_name, target_id — neither is an internal entity/UUID) with documented reasons. - Allowlist the external-trigger start topic in the subscribe-wiring-health script (triggered by the canary schedule, not a Kafka publisher). Increment 2 (recovery effects, FSM reducer, grant/cooldown gate) is design-only per the task — not built here; a follow-up ticket will be filed once this increment is reviewed. Evidence-Ticket: OMN-13942 * fix(OMN-13942): fix Split test failures — baseline frozen-list + runner-image lock - Update ARCH-004 imperative-orchestrator baseline frozen-list tests to accept the new node_runner_fleet_maintain_orchestrator entry (OMN-13942): add it to EXPECTED_OWNER_TICKETS and bump risk-2 count 6->7. - Regenerate docker/runners/runner-image.lock.json: the two new node entry-points in pyproject.toml changed the manifest_digest (and shared_env_digest), so the bound runner-image identity was stale. Fixes Split 1/15 identity tests and runner-image-build-smoke. Evidence-Source: OCC#3607 Evidence-Ticket: OMN-13942 * fix(OMN-13942): update frozen runner-identity digest in backmerge test test_release_backmerge_preserves_runner_identity_lock froze the pre-regen identity/shared_env digests. The two new node entry-points in pyproject.toml rebind the runner-image identity (binding-not-label by design), so update the frozen values to the regenerated, build-proven (runner-image-build-smoke pass) digests bc29a1.../d11587... Evidence-Source: OCC#3607 Evidence-Ticket: OMN-13942 * test: tolerate docker daemon latency
…t/orphan defects (#2208) The 2026-07-04 runner-fleet non-convergence incident traced to three compounding defects in auto_bounce(): (1) no lock, so the */10 cron could dispatch a second force-recreate while a prior one was still running, producing daemon-level "removal ... already in progress" races; (2) a fixed 120s timeout that SIGTERM'd docker compose mid-batch under host load, leaving containers Status=created but never started (36% of recreate attempts never completed during the incident); (3) no re-targeting for stragglers left at Status=created, since they matched neither crashloop nor wedge detection and were therefore invisible to future remediation cycles. Adds a flock mutex around the bounce dispatch, scales the timeout with batch size (floor/per-container-budget/ceiling instead of one fixed cap), and adds a verify-start + bounded-retry pass plus new stuck_created detection so a straggler is retried by the next cycle instead of orphaned forever. New behavioral tests drive the real script end-to-end via mock docker/gh/curl binaries and assert on the fix directly (stuck-created flagging, actual compose+retry dispatch, and lock-contention skip).
…superseded/zombie runs (SAT1) (#2209) * ci(OMN-13949): concurrency cancel-in-progress + job timeouts to kill superseded/zombie runs (SAT1) Fleet-load reduction (Track 1, OMN-13932 §5.2). Superseded CI runs were holding saturated self-hosted runners. - Add top-level concurrency { group: workflow-<pr#|ref>, cancel-in-progress: true } to PR-triggered check/test/gate workflows (24 workflows). merge_group entries carry a unique github.ref so distinct queue entries never cross-cancel; the required contexts still report on merge_group. - Normalize 5 workflows that kept superseded PR runs alive (ci.yml, compose-config-lint, env-parity, lane-census-staleness, runner-disk-preflight) from cancel:false / merge_group-only to cancel-in-progress: true. - Deploy/release/prod-mutation/tag workflows deliberately NOT given cancel-in-progress: release.yml, release-python-reusable.yml, build-and-push-*, auto-tag-on-merge, runtime-rebuild-trigger, prod-promotion-lineage stay serialized (cancel:false) or untouched — never cancel an in-flight prod build/tag/deploy. - Add safety-net timeout-minutes to every job lacking one (37 jobs across 21 workflows; reusable 'uses:' jobs skipped) so a hung job cannot hold a runner indefinitely. Verified: tests/ci/test_ci_workflow_resilience.py + test_runner_disk_preflight.py (51 passed); actionlint clean (only pre-existing shellcheck/secret findings); pre-commit clean on changed files. * ci: skip docker integration tests on PRs * ci: retrigger merge sweep checks
…ofile-aware teardown gate) (#2211) * feat(OMN-13886): guard against bare compose down of runtime lanes The ONEX runtime services are gated behind compose profiles ["runtime","full"], so a bare `docker compose ... down` (no --profile runtime/full and no --remove-orphans) tears down the un-profiled core deps while orphaning the profile-gated runtime containers — the '2 hits in 24h' teardown defect (WS-2). Enforcement, not detection (CLAUDE.md Operating Rule #5): - tests/test_compose_profile_teardown_policy.py — self-contained scanner+test (mirrors omni_home's no-raw-prod-bypass gate). Flags a `down` at a runtime lane (docker-compose.infra.yml / lane overlay / -p lane project) that carries neither --profile runtime|full nor --remove-orphans. Doubles as a standalone pre-commit entrypoint via __main__. - .github/workflows/no-bare-compose-teardown.yml — CI gate (pull_request + merge_group + push dev/main). - .pre-commit-config.yaml — local no-bare-compose-teardown hook. Scoped to `down` only: a bare `up` of docker-compose.infra.yml is a documented, non-destructive core-only bring-up (dozens of legit recipes) — flagging it would be pure false-positive noise. Escape hatch: `# compose-profile-ok: <reason>`. Corpus made green by adding --remove-orphans to the full-teardown docs it flags (docker/README.md, docker/docker-compose.infra.yml header, quickstart.md) so the documented teardown actually removes the profile-gated runtime containers; the historical 2026-05-04 keycloak plan checklist is path-allowlisted (the no-planning-docs gate forbids editing it inline). * ci(OMN-13886): run standalone scanner (not pytest) to avoid conftest deps The gate ran `python -m pytest`, which auto-loads tests/conftest.py (pulls python-dotenv etc., absent in the minimal CI env → ModuleNotFoundError, not a real violation). Run the module's standalone __main__ scanner instead — same path the pre-commit hook uses, zero conftest, stdlib-only corpus scan. The self-tests still run in the full `uv run pytest tests/` suite + pre-commit. * ci(OMN-13886): route teardown gate on trusted runners
…istries (omnibase_infra) (#2212) Clears all 80 hardcoded-topics aislop-sweep findings in omnibase_infra to 0 without changing any wire topic string value. Changes: - event_bus/topic_constants.py: doctest continuation lines showing topic literals converted to RST double-backticks (docstring example only, testpaths is tests/ only so src/ doctests are never executed). - runtime/models/model_projector_notification_config.py, runtime/models/model_transition_notification_publisher_metrics.py, runtime/publisher_topic_scoped.py, runtime/transition_notification_publisher.py: same backtick treatment for docstring/doctest examples showing "onex.fsm.state.transitions.v1". - topics/contract_topic_extractor.py: YAML-shaped docstring examples converted to backticks. - services/cost_api/snapshot_cache.py: added `# onex-topic-sot` file-level marker — this module IS the canonical registry for the three cost-snapshot projection topic constants it defines. - services/observability/agent_actions/tests/{test_consumer.py, test_hardening.py, test_routing_decision_schema_handshake.py}: true relocation — imported the existing SUFFIX_OMNICLAUDE_* constants from omnibase_infra.topics.platform_topic_suffixes and replaced 57 duplicate inline topic literals with references to them (no more test-fixture markers needed since canonical constants already existed for every literal used). dod_evidence (OMN-13944): - hardcoded-topics scanner: 80 findings -> 0 findings (self-verify replica of node_aislop_sweep._check_hardcoded_topics) - ruff format + ruff check --fix: clean on all 10 changed files - mypy --strict on 7 changed non-test src files: Success, no issues - pytest targeted: 94/94 passed (test_consumer.py + test_routing_decision_schema_handshake.py), 120/124 passed in test_hardening.py (4 pre-existing failures reproduced identically on unmodified dev HEAD — missing OMNIBASE_INFRA_AGENT_ACTIONS_KAFKA_BOOTSTRAP_SERVERS env var in this shell, unrelated to this change) - pytest tests/unit (full unit suite, 21109 tests): 21071 passed, 9 failed (pre-existing perf-benchmark timing flakiness + unrelated test_provision_infisical.py failures, none touching changed files), 29 skipped - pre-commit run --files <changed>: all hooks passed, including "Check for AI-slop patterns" and "No hardcoded ONEX topic strings"
* fix(OMN-13947): recreate missing runner containers * ci(OMN-13947): make receipt honesty checkout idempotent * ci(OMN-13947): route sibling lock refresh on trusted runners
…ad of Unknown node (#2215) `onex skill dep_cascade_dedup` hard-failed from the canonical infra venv with "Unknown skill" even though the backing node node_dep_cascade_dedup_orchestrator is registered in the omnimarket onex.nodes catalog and both request + result models exist. The only gap was a missing skill_mapping.yaml row, so the post-release dep-bump dedup sweep was unrunnable headless. Same regression class as OMN-13511 / OMN-13712 (node exists, skill unmapped). Additive mapping row only (mirrors merge_sweep shape); args mirror ModelDepCascadeDedupRequest (repos/dependency-type/label/close-comment/dry-run). Tests: - dep_cascade_dedup registered + wired to node + typed result model - payload validates against ModelDepCascadeDedupRequest (repos = the sweep's roots/repos it scans); dry-run boolean default wiring - registered in the node-backed dogfood catalog-resolution gate - CLAUDE.md rule #8 fail-fast guard: the sweep-repo-fallback _resolve_root in BOTH node_integration_sweep_orchestrator and node_dod_sweep_orchestrator raises RuntimeError when the repo-registry env is unset and no explicit root is supplied — never a silent default. Closes OMN-13995
…edger-append ingress (#2232) * feat(OMN-14134): add handle() adapter to HandlerLedgerAppend — wire ledger-append ingress node_ledger_write_effect's contract declares operation_match routing with no event_model, so handler_wiring._make_dispatch_callback dispatches via handle(envelope) directly rather than execute(). HandlerLedgerAppend exposed append()/execute() but no handle(), so auto-wiring bound the _missing_handle sentinel and every dispatched ledger-append command raised at runtime (WI-14 keystone gap). Mirrors the shipped HandlerBuildLoopProjection.handle() precedent: extracts the payload via getattr(envelope, "payload", envelope), coerces to ModelPayloadLedgerAppend, delegates to append(), and wraps the result with ModelHandlerOutput.for_compute() the same way execute() already does. * chore(OMN-14134): bump node_ledger_write_effect contract version for handle() adapter Wave C contract-sync gate requires contract.yaml to move alongside any handler change in the same node directory.
…o auto-wiring resolver (#2234) * fix(OMN-14139)(OMN-14140): wire node_ledger_write_effect handlers into auto-wiring resolver Two defects blocked the ledger-append pipeline from ever running: - OMN-14139: contract.yaml's handler_routing.handlers[] used the flat handler_class:/handler_module: fields, which ModelHandlerRoutingEntry does not parse (nested handler: {name, module} required) -- both entries silently dropped, wiring ZERO handlers. Fixed to the nested schema, plus an explicit topic: per entry so the two operation_match handlers don't hit the multi-handler topic-assignment ambiguity guard. - OMN-14140: HandlerLedgerAppend/HandlerLedgerQuery required a db_handler constructor argument the auto-wiring resolver cannot supply (its known-injectable set is container/event_bus/ ownership_query only), so even with routing fixed the handlers were unconstructable (quarantined). Both now compose HandlerDb internally from `container` alone, connecting lazily on first real use via `_ensure_db_ready()` since the resolver never calls initialize() on auto-wired handlers. Also fixed, discovered during live verification: HandlerLedgerAppend's OMN-14134 handle() adapter (and the mirrored one added here for HandlerLedgerQuery) extracted payload/correlation_id via getattr(envelope, "payload", ...), which silently no-ops on the DICT envelope MessageDispatchEngine._materialize_envelope_with_bindings actually delivers on the live dispatch path -- only object-shaped test doubles worked. Both now use a dict-or-attribute extraction helper mirroring HandlerBuildLoopProjection._coerce_event_message. Verified live on .201 dev lane: wire_from_manifest resolves both handlers with zero quarantine and registers both topic routes; a synthetic ledger-append event produced to onex.cmd.platform.ledger-append.v1 landed a durable row in event_ledger (count 0 -> 1) with the lazily-connected HandlerDb and a published onex.evt.platform.ledger-appended.v1 confirmation. * fix(OMN-14139): remove ledger handler env reads * test(OMN-14139): regenerate ledger dispatch parity oracle
… dev candidate runtime image can build (#2214) * fix(OMN-13985): install pydantic before sibling-lock-pin preflight so dev candidate runtime image can build The 'Stage workspace sibling trees into the build context' step runs scripts/runtime_build/stage_workspace.sh, which invokes scripts/runtime_build/check_sibling_lock_pins.py. That script imports pydantic (BaseModel, ConfigDict, Field) at module top level, but the workflow only sets up Python via actions/setup-python and installs no project deps before this step. The preflight died with ModuleNotFoundError: No module named 'pydantic' -> stage_workspace.sh exit 3, so the docker build / ECR push / digest steps never ran. Only pydantic is third-party; everything else the script imports is stdlib. Insert a minimal 'pip install pydantic>=2' step against the setup-python interpreter immediately before the failing staging step. The script is invoked via bare 'python3', matching this install target. Evidence: run 28748861432 failed at the staging step with the above ModuleNotFoundError. Locally reproduced (clean venv): import fails before install, and after installing pydantic the script reaches argparse (exit 2), proving the import is resolved. * ci(OMN-13985): route sibling refresh on trusted runners * ci(OMN-13985): clean receipt honesty sibling checkout * ci(OMN-13985): extend contract compliance timeout * chore(OMN-13985): retrigger lint CI
…ns the OMN-13888 grandfather validator (#2231) * fix(OMN-14130): bump omnibase-core 0.46.3->0.46.5 (OMN-13888 OCC grandfather validator) omnibase_infra pinned omnibase-core==0.46.3, which predates OMN-13888 (per-entry OCC receipt hashing + append-only + supersession + dual-accept / grandfather, shipped in 0.46.5). occ-preflight installs the caller repo's pinned core version, so infra PRs were evaluating OCC eligibility with the pre-grandfather 0.46.3 validator. That validator re-applies the old 'all receipts must equal the current whole-file contract hash' rule and rejects any PR whose ticket contract received an append after merge (e.g. OMN-14127 shared between omniclaude #1870 and infra #2230 → contract_hash_mismatch on the legacy dod-omniclaude-pr-1870 receipt). Bump to ==0.46.5 (both dependency groups) + regenerate uv.lock + resync _FALLBACK_MATRIX in version_compatibility.py. Verified clean on 0.46.5: 25,453 tests collect with zero import/API breaks; full unit suite 21,076 passed (0 real failures); test_version_compatibility 25 passed. Unblocks OMN-14127 (#2230) once merged + rebased. See also OMN-14131 (harden occ-preflight so the built main wheel wins over a CWD pin). * fix(OMN-14130): refresh runner identity for core pin bump
…osted fail-closed poller so it never wedges under self-hosted saturation (#2230) * ci(OMN-14127): convert CI Summary to no-needs GitHub-hosted fail-closed poller Port the proven omniclaude #1870 wedge fix to omnibase_infra. The required branch-protection context "CI Summary" was a needs-gated aggregator over ~20 self-hosted jobs; under fleet saturation those jobs never terminalized, so the required check-run was ABSENT (not failing/pending) and PRs wedged BLOCKED with no auto-recovery. - ci-summary is now a NO-needs, runs-on: ubuntu-latest, if: always(), fail-closed bounded-deadline poller. Its check-run instantiates immediately (the required context can never be absent) and it polls the current run's job conclusions via the GitHub jobs API. Zero self-hosted/LAN dependency. Name 'CI Summary' preserved byte-for-byte (rename would re-wedge every PR). - scripts/ci/ci_summary_gate.py: default-deny, fail-closed verdict (exit 0/1/2). Reproduces infra's exact original semantics (13 strict == success gates + 4 success||skipped gates as the completeness anchor) and adds a strictly-stronger default-deny sweep that catches detect-changes / plugin-env-service-completeness / compose-required-env-coverage / contract-path-preflight failures the old tests-gate greened on 'skipped'. Small soft-allowlist of genuinely-non-gating jobs (advisory / not-required), prefix-aware for reusable-workflow callers. - tests/ci/test_ci_summary_gate.py: 18 unit tests pinning the fail-closed verdict (strict-skip=fail, sweep catches leaves, allowlist ignored, empty run != vacuous green, docs-only success). - Removes the (unset, no-op) OMNI_REQUIRED_CI_RUNS_ON_JSON merge_group override from the ci-summary runs-on selector; the poller is runner-independent. * fix(OMN-14127): allow hosted ci summary aggregator * fix(OMN-14127): route ci process changes to ci tests * fix(OMN-14127): fail closed on duplicate summary jobs
* ci(OMN-14104): gate all PR workflows on OCC preflight * ci(OMN-14104): re-arm OCC preflight after evidence merge * ci(OMN-14104): target core dev for OCC preflight callers * ci(OMN-14104): pin infra OCC preflight reusable workflow * ci(OMN-14104): pin infra OCC preflight to workflow-sha fix * ci(OMN-14104): correct OCC preflight workflow pin * ci(OMN-14104): use working OCC preflight core pin * ci(OMN-14104): pin OCC preflight to dev-validator workflow * ci(OMN-14104): pin OCC preflight to isolated wheel build * ci(OMN-14104): pass explicit OCC preflight core ref * ci(OMN-14104): pin infra OCC preflight to compat-dev core fix * ci(OMN-14104): fail CI Summary explicitly when OCC preflight is red CodeRabbit flagged that gating the required CI Summary aggregate with `if: needs.occ-preflight.result == 'success' && (always())` turns a RED occ-preflight into a SKIPPED CI Summary. A skipped required branch-protection check reports as success, so a failed OCC preflight could be merged. Keep `if: always()` and enforce OCC eligibility as the first step, failing explicitly when preflight did not succeed so the required check stays RED. CI Summary is the single umbrella required gate (OMN-4497, .github/required-checks.yaml), so a red CI Summary blocks the merge even though the runner-heavy fanout is (intentionally) skipped on preflight failure. * ci(OMN-14104): re-trigger CI after transient startup_failure batch The 06:58Z run batch on the prior push hit a transient GitHub Actions startup_failure across all workflows (zero jobs, name==path, no diff cause — untouched workflows failed too). Infra recovered by 07:01Z (sibling branch runs queuing/running normally). startup_failure runs are non-retriable, so this empty commit re-triggers a fresh CI cycle. No code change. * ci(OMN-14104): re-pin occ-preflight reusable to merged omnibase_core dev SHA The 43 workflow callers pinned the occ-preflight reusable (and its core-ref input) to 7975803283 — a commit on the omnibase_core OMN-14104 PR branch (#1396, 'ci: use dev for OCC preflight compat checkout'). That PR squash-merged to omnibase_core dev (8a47e092), deleting the branch and ORPHANING 7975803283. GitHub Actions can no longer resolve the reusable at an unreachable SHA, so every caller on this branch hit startup_failure ('workflow file issue', zero jobs) — all 43 workflows red. Re-pin all 86 references (43 uses:@ + 43 core-ref) to 8a47e092002dd1338599fa0733feda469436acbf, the merged commit that last defined occ-preflight.yml on omnibase_core dev (ancestor of dev HEAD, reachable). Input interface is identical (contracts-dir/receipts-dir/core-ref, all optional) — verified against both SHAs. Also rebased onto origin/dev to pick up the 4 missing commits (incl. OMN-14130 core 0.46.5 bump for the grandfather validator). * ci(OMN-14104): refresh dispatch parity fixture * ci(OMN-14104): restore routed dispatch parity fixture * ci(OMN-14104): refresh parity fixture metadata * ci(OMN-14104): allow reusable occ preflight in webhook tests * ci(OMN-14104): run plugin lifecycle guard in uv env
…s (WS-F) (#2219) * fix(OMN-14017): set UV_HTTP_TIMEOUT=600 on merge_group validator gates Three merge_group required-status validators (Runtime Profiles, URL Authority Gate, Validate Validator Requirements) run a raw `uv sync` via astral-sh/setup-uv directly, bypassing the hardened ./.github/actions/setup-python-uv composite. That path inherits uv's 30s default timeout with zero retries, so it fails HARD on the first PyPI download timeout under fleet egress saturation (WS-F) — while the 16 composite-using workflows retry through the same contention. Observed: the Runtime Profiles / validate merge_group check at the omnibase_infra queue HEAD (run 28775491973) failed on `virtualenv==20.36.1` with 'network timeout ... current value: 30s'. Set UV_HTTP_TIMEOUT=600 at the workflow env level of all three (matches the composite's ${UV_HTTP_TIMEOUT:-600} and ci.yml/omni-standards precedent). It propagates to every uv sync and uv run --with git+https call in the job. Minimal, uniform, no step restructuring. Related: OMN-13932 (WS-F fleet epic; systemic mirror decision is separate). * ci(OMN-14017): retrigger stale canceled checks * fix(OMN-14017): route sibling lock refresh runner * ci(OMN-14017): widen saturated validator gate budgets
* feat(OMN-14029): scale runner fleet to 56 * ci(OMN-14029): refresh cancelled status rollup * fix(OMN-14029): preserve runner script executable bits * fix(OMN-14029): trust local runner listener health during api flaps * fix(OMN-14029): reconcile runner fleet target to 64 * ci(OMN-14029): narrow stale todo checkout fetch * ci(OMN-14029): route sibling lock refresh on trusted runners
…lows (Lever 1 fan-out) (#2224) * ci(OMN-14078): remove merge_group triggers from 15 non-required workflows (Lever 1 fan-out) Lever 1 fan-out from docs/plans/2026-07-06-ci-streamlining-logjam-reduction-plan.md (sibling of OMN-14076 core canary). The merge queue only waits on required status contexts; these 15 workflows carry none, so their merge_group runs burn shared self-hosted runner slots and gate nothing. Removes only the merge_group: trigger from each on: block. pull_request and push triggers untouched -- nothing un-enforced. No logic changes. Verified against the LIVE required_status_checks: every required-context carrier keeps its merge_group trigger; no cut workflow produces a required context. * ci(OMN-14078): refresh gates after OCC evidence binding * ci(OMN-14078): route sibling lock refresh on trusted runners * ci(OMN-14078): raise uv timeout on required install gates * ci(OMN-14078): align runner disk preflight trigger test * ci(OMN-14078): retrigger checks after runner reset * ci(OMN-14078): fix url authority workflow env block
…ice 2, the §1 fix) (#2217) * feat(OMN-13997): verification-receipts raw ledger projection (WS-L slice 2, the §1 fix) Second migration slice of the event-sourced ledger substrate (epic OMN-13989, plan §2.5 / §6 Phase 1). Replicates the proven slice-1 receiving-end pattern. verification-receipts (.onex_state/verification-receipts/*.yaml) is THE ledger the initiative exists to fix: plan §1.1 names it the direct doctrine §1 contradiction (completion-evidence ledger on local disk); the hostile review re-ordered it to Phase 1 "delivered early". Higher current-gap value than dispatch-log. Pure DB projection over the existing ProjectorShell + ModelProjectorContract engine: ZERO new node, ZERO bespoke class (rule 7a). Reference: overseer_tick_ledger (088), decision_store (046). Artifacts (omnibase_infra): - docker/migrations/forward/089_create_verification_receipt_ledger.sql (089 — 088 reserved by in-flight #2216) — append-only verification_receipt_ledger; envelope_id PK idempotency; single_partition ordering; queryable NULLABLE core columns + phases JSONB + receipt_body JSONB (lossless full-fidelity capture). - rollback + restamped schema_fingerprint.sha256. - src/omnibase_infra/projectors/contracts/verification_receipt_projector.yaml — consumes onex.evt.omniclaude.verification_receipt.v1, append mode. - tests/unit/runtime/test_verification_receipt_projector.py. Doc-discrepancy reconcile (verified on-disk): - On-disk receipts are the payload shape, not full ModelEventEnvelopes (as slice-1). - HETEROGENEOUS shapes: ticket receipts + overseer-verify-tick share a core; one legacy baseline snapshot omits ticket_id/phases. Handled by nullable core columns + lossless receipt_body JSONB. - ticket_id nullable (1/9 files lack it); overseer_verdict on only 2/9. - Plan §6 topic onex.evt.omniclaude.verification-receipt.v1 differs from the existing node_verification_receipt_generator topic (onex.evt.omnimarket.verification-receipt-completed.v1) — that node is not this skill-written flat-file ledger. Event-type uses underscore per contract pattern. Net-negative: adds only the target projection surface (no new flat-file writer). Deferred (follow-up children of OMN-13989): emit-side dual-write (WS-6 MSK-IAM cutover, not this lane); golden-chain replay-equivalence (T15); cutover of the receipt-gate reader onto the projection. dod_evidence: 4/4 new tests pass; 457 projector suites unaffected; ruff + SPDX + migration-sequence + writer-coupling + schema-fingerprint green. Closes OMN-13997 * ci(OMN-13997): refresh stuck checks * ci(OMN-13997): refresh stale PR checks * ci(OMN-13997): refresh duplicate cancelled guard contexts * fix(OMN-13997): require raw receipt body projection * ci(OMN-13997): isolate receipt honesty validator checkout * ci(OMN-13997): route sibling lock refresh via runner selector * ci(OMN-13997): retrigger stale canceled checks * ci(OMN-13997): refresh wedged docker build gate * ci(OMN-13997): retry receipt honesty core clone
…schema silent-zero-parse (#2235) * fix(OMN-14141): fail-closed guard + CI gate for handler_routing flat-schema silent-zero-parse The flat handler_class:/handler_module: schema silently parsed to zero handlers, then auto-wiring reported WIRED with zero dispatchers while still subscribing to and committing Kafka offsets on the topic — silent phantom-wiring (the WI-14 root cause, OMN-14139/OMN-14135). Enforcement (CLAUDE.md Rule #5 — gate ships WITH the fixes): - Guard A (parse-time): discovery._parse_handler_routing raises on a flat/ malformed handlers[] entry instead of silently skipping it. Legacy top-level handler: fallback preserved (empty handlers list never raises). - Guard B (wire-time): _commit_contract_wiring reports FAILED (not WIRED) and does NOT subscribe when a contract declares subscribe topics but registers zero dispatchers. Never fires on legacy fallbacks (>=1 dispatcher) or resolver-ownership/quarantine skips. - CI gate + pre-commit hook: handler_routing_schema validator rejects flat entries across all node contracts (SYNC'd ci.yml step + pre-commit hook). Contract fixes (7 infra contracts the gate would reject; ledger done in #2234): node_savings_estimation_compute, node_build_loop_write_effect, node_session_state_effect, node_pattern_lifecycle_effect, node_validation_executor, node_decision_store_query_compute, node_baseline_comparison_compute. Verified: 111/111 contracts discover with zero errors; Guard B fires on zero real contracts; 354 auto-wiring/kernel tests + 11 new guard tests green. Follow-up (separate PR): 3 omnimarket flat-schema contracts + omnimarket-side gate. * test(OMN-14141): refresh dispatch parity oracle
* ci(OMN-14078): remove duplicate validator workflow env * ci(OMN-14078): retrigger after OCC evidence merge
…t + repair tick (#2223) * fix(OMN-14060): omnimarket venv drift guard — dynamic ref + pre-flight + repair tick Closes the OMN-13829 recurrence: install-node-skill-package.sh baked in a hand-edited omnimarket SHA that went stale within days, and nothing re-asserted the venv's install state afterward, so it silently reverted to a stale PyPI install (missing the operation: field fix, OMN-13530). - install-node-skill-package.sh now resolves OMNIMARKET_REF dynamically from omnimarket's live dev HEAD (git ls-remote), falling back to the local canonical clone at $OMNI_HOME/omnimarket when offline. An explicit OMNIMARKET_REF override still wins outright (pinned/offline use). Kills the stale-pin-layer-two problem the OMN-14060 investigation surfaced. - New src/omnibase_infra/cli/omnimarket_drift_guard.py: a cheap, LOCAL-ONLY (no network) pre-flight check wired into `onex skill <name>` that compares the current interpreter's installed omnimarket commit against the already-checked-out $OMNI_HOME/omnimarket clone. Fails open whenever either side can't be determined locally (CI, fresh machines); raises a clear, actionable error pointing at the repair command on a real mismatch. Never re-installs anything itself (detect only). - New scripts/check-omnimarket-venv-drift.sh: the repair half, meant for a session/cron tick. Refreshes the canonical clone from origin/dev, compares against the target venv, and with --repair re-runs install-node-skill-package.sh pinned to the fresh SHA. Verified locally end-to-end: installed a deliberately stale SHA, confirmed `onex skill aislop_sweep` hard-fails with the STALE message, ran check-omnimarket-venv-drift.sh --repair, confirmed it fixed the venv and the skill dispatches again. 21 new tests (drift guard unit tests + hermetic script tests using a local bare-repo remote and a fake python shim, no network); all pre-existing cli/scripts tests still pass (582 total in tests/unit/cli/ + tests/scripts/); ruff format/check, mypy, and pre-commit all clean on the touched files. Companion to OMN-14064 (separate lane: the release-side gate for the PyPI-uninstallable omnimarket 0.4.6 pin) — this PR is the venv-side guard only. * ci(OMN-14060): refresh cancelled gate rollup
) * fix(OMN-13992): inject _topic into projection dispatch input_data HandlerProjectionLiveEvents.handle() requires a non-empty input_data['_topic'] (docstring: "Expects input_data to contain ... _topic: source Kafka topic string"), but _make_projection_dispatch_callback computed topic locally (for logging only) and never injected it into input_data alongside _db/_event_type. Every real dispatch on the .201 dev lane raised ValueError and the event was dropped, non-fatally but silently, because the contract also had no DLQ topic declared. The 6 subscribed topics all hit this; node-heartbeat is the only one with steady traffic on the idle dev lane, producing the ~30s drop cadence observed in OMN-13992. Fix: inject input_data["_topic"] = topic next to the existing _db/ _event_type injection. Other projection handlers tolerate a missing _topic via a topics[0] fallback, so they are unaffected; this closes a real correctness gap for any handler (now or future) that requires the actual dispatched topic rather than a same-node guess. Companion fix in omnimarket adds event_bus.dlq_topics to node_projection_live_events/contract.yaml so any future malformed event is dead-lettered instead of dropped. * ci(OMN-13992): retry runtime npm CLI install * ci(OMN-13992): refresh cancelled node migration check * ci(OMN-13992): retrigger stuck node migration workflow * ci(OMN-13992): refresh cancelled required gate contexts * fix(OMN-13992): preserve npm retry failure status * ci(OMN-13992): refresh kafka boundary gate after runner install casualty
* fix(OMN-14028): raise hot runtime service memory caps * ci(OMN-14028): refresh cancelled status rollup * ci(OMN-14028): refresh cancelled required gates * ci(OMN-14028): refresh cancelled runner contexts * ci(OMN-14028): refresh cancelled lightweight gates * ci(OMN-14028): refresh kafka boundary gate after runner install casualty
* chore(OMN-14030): consolidate host cleanup installer * ci(OMN-14030): refresh cancelled status rollup * fix(OMN-14030): consolidate host cleanup and redpanda volume gc * ci(OMN-14030): refresh cancelled runner checks * ci(OMN-14030): refresh cancelled node migration sync * chore(OMN-14030): retrigger cancelled CI
…-only bypass leak) (#2225) Shift defect detection left by closing the dominant bypass leak found in the OMN-14099 audit: the local pre-commit git hook was never installed in 6 of 7 canonical clones under $OMNI_HOME, so every repo's .pre-commit-config.yaml was pure decoration. No --no-verify needed -- the hook simply never ran, so every commit silently skipped ALL local enforcement (hardcoded IPs/topics, banned constructs, URL/model-literal authority, skip tokens, PEP-604 unions, ...) and CI became the first (most expensive) catch point. Fix: wire an idempotent `pre-commit install` (+ best-effort `install-hooks`) into scripts/pull-all.sh -- the sync entrypoint every session already runs before ticket work. It activates the already-written, correctly-scoped hooks across every repo that ships a config, at commit time. Guarantees: - Idempotent: skips repos whose hook is already pre-commit-managed (fast no-op). - Scoped: only touches repos that ship a .pre-commit-config.yaml. - Fail-soft: a hook-install problem never fails the pull; left out of FAILED. - Offline-safe: writing the hook script is the load-bearing step (no network); env pre-build is best-effort and envs otherwise install lazily at first commit. This is NOT a new pattern check -- it closes a leak so already-existing gates (URL-authority, canonical-inference, topic/IP/path guards, skip-token rejection) fire pre-commit instead of first failing in CI/CodeRabbit/merge-sweep. Net-negative surface: adds no new CI gate; instead it makes CI the BACKSTOP for ~400 already-written hooks that were previously CI-only on this machine. Tests: TestPreCommitHookInstall (install-when-config-present, idempotent-noop, no-config-no-hook) drive the real script via subprocess against real git repos; all 28 tests in the module pass. E2E-verified that the installed hook blocks a deliberately-bad commit. Relates OMN-13979 (CI audit), OMN-13981 (validator telemetry).
* build(deps): bump omnibase-core from 0.46.3 to 0.46.5 Bumps [omnibase-core](https://github.com/OmniNode-ai/omnibase_core) from 0.46.3 to 0.46.5. - [Release notes](https://github.com/OmniNode-ai/omnibase_core/releases) - [Changelog](https://github.com/OmniNode-ai/omnibase_core/blob/dev/CHANGELOG.md) - [Commits](OmniNode-ai/omnibase_core@v0.46.3...v0.46.5) --- updated-dependencies: - dependency-name: omnibase-core dependency-version: 0.46.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): refresh runner image identity for core 0.46.5 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jonah Gray <jonah@omninode.ai>
…rd-drift in workspace builds (OMN-14138) (#2233) * fix(OMN-13902): stop sibling-pin guard false-blocking registry forward-drift in workspace builds (OMN-14138) The workspace-build sibling-pin preflight (check_sibling_lock_pins.py) treated ANY version mismatch as fatal. But OMN-13929's post-publish release-identity disarm bumps a sibling's DEV pyproject version to N+1 the instant version N is published, so every registry-sourced sibling's dev clone is PERMANENTLY one version ahead of the last-published pin a consumer's uv.lock can carry. A workspace build vendors the clone (newer by design), so the guard reported [DRIFT/forward] and aborted EVERY workspace runtime build from dev. Fix: in workspace mode, a registry-sourced pin (git_rev is None) whose clone version is strictly FORWARD of the lock is recorded as a non-fatal forward_drift_allowed note -- the registry-sourced analogue of the OMN-13403 git-rev clone_ahead exemption. Backward drift (stale clone -- the 2026-06-11 crash shape), non-comparable versions, and git-sourced drift all stay FATAL, and release-mode (the strict default) stays fully strict. The workspace callers (stage_workspace.sh, deploy-runtime.sh) pass --build-source workspace; any other caller fails closed to strict. Proven behavior (unit + CLI): core lock=0.46.5 clone=0.46.6 (registry forward) PASSES in workspace / FAILS in release; spi lock=0.23.1 clone=0.23.0 (registry backward) FAILS in both; git-sourced forward stays fatal. The in-build re-checks (compute_workspace_provenance _load_pin_comparison drift_count + resolve_workspace_pins.compare_pin, which already classified forward as allowed "ahead") are consistent with the fix. OMN-13902 OMN-14138 * chore(OMN-13902): retrigger OCC preflight after core workflow fix
…32.0,<0.51.0 (#2227) * build(deps): update uvicorn requirement Updates the requirements on [uvicorn](https://github.com/Kludex/uvicorn) to permit the latest version. - [Release notes](https://github.com/Kludex/uvicorn/releases) - [Changelog](https://github.com/Kludex/uvicorn/blob/main/docs/release-notes.md) - [Commits](Kludex/uvicorn@0.32.0...0.50.2) --- updated-dependencies: - dependency-name: uvicorn dependency-version: 0.50.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): refresh runner image identity for uvicorn bump --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jonah Gray <jonah@omninode.ai>
…ings (#2240) Vendors omnimarket's new node-owned migrations (source of truth: omnimarket#1649) into this repo's forward-migration tree via scripts/sync-node-migrations.sh, so a clean redeploy picks them up: - docker/migrations/forward/nodes/node_projection_delegation/ 0022_delegation_events_tenant_id.sql - docker/migrations/forward/nodes/node_projection_savings/ 080_savings_estimates_tenant_id.sql Both are ALTER TABLE ... ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'omninode', closing a HIGH-severity defect found by independent adversarial verification of the OMN-14058 interim tenant_id stamp (omnibase_core#1404 / omnimarket#1648): neither delegation_events nor savings_estimates had a tenant_id column, so PostgresSyncProjectionAdapter. upsert() raised `column "tenant_id" does not exist` against real Postgres the moment ONEX_TENANT_ID was set. Verified in sync with the omnimarket dev tip's node migration source via `scripts/sync-node-migrations.sh --check` (0 drift beyond these 2 files); node-scoped migrations under nodes/ are excluded from the flat schema_fingerprint.sha256 (non-recursive glob), so no fingerprint restamp is required. Sequencing: this repo's node-migration-sync CI check (and local onex-check-node-migration-sync pre-commit hook) resolves against omnimarket's dev tip, so it will read as OUT OF SYNC until omnimarket#1649 merges to dev -- expected, same pattern as the existing omnibase_core#1404 -> omnimarket#1648 dependency. Do not merge this PR before omnimarket#1649. Closes OMN-14058 (infra vendoring half; see omnimarket#1649 for the source-of-truth migration + real-Postgres regression test).
…0.120.1,<0.140.0 (#2228) * build(deps): update fastapi requirement Updates the requirements on [fastapi](https://github.com/fastapi/fastapi) to permit the latest version. - [Release notes](https://github.com/fastapi/fastapi/releases) - [Commits](fastapi/fastapi@0.120.1...0.139.0) --- updated-dependencies: - dependency-name: fastapi dependency-version: 0.139.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * build(deps): refresh runner image identity for fastapi bump * fix: refresh runner identity after fastapi merge * fix: align build loop append wiring * fix: sync vendored node migrations * fix: refresh fastapi gate evidence * fix: refresh dispatch parity fixture --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jonah Gray <jonah@omninode.ai>
…mount cache builds no longer fail (#2452) * fix(OMN-15141): runner image ships docker buildx plugin — BuildKit --mount cache builds no longer fail The omninode-deploy-runner image installed docker-ce-cli + docker-compose-plugin (OMN-14966) but not docker-buildx-plugin. docker/Dockerfile.runtime uses BuildKit-only RUN --mount=type=cache syntax; without buildx, docker compose build has no BuildKit backend and falls back to the legacy builder, which dies with "the --mount option requires BuildKit" (deploy run 30178195370, stability release-train deploy hop iteration N+4). Add docker-buildx-plugin to the same apt-get install line as docker-ce-cli / docker-compose-plugin (same Docker apt repo, package add only, identity-neutral per runner-image.lock.json). * chore(OMN-15141): retrigger occ-preflight after Evidence-Source amendment --------- Co-authored-by: Jonah Gray <jonah.g.gray@gmail.com>
Verifies OMN-15094 (#663)\047s workflow_receipt.json terminal_event_hash by replaying the recorded delegation-terminal Kafka event via the real node_kafka_replay_compute kafka.replay operation and diffing the reconstructed hash against the receipt. Re-verified the ticket\047s seam assumptions against #663\047s actual landed implementation before building (per the ticket\047s own instruction) and found two real deviations, documented inline in verifier.py: 1. node_kafka_replay_compute lives in omnibase_infra, not co-located with OMN-15094\047s renderer (omninode_infra docker/onex-api). Adding omnibase-infra as a pip dependency of onex-api is not viable -- omnibase-infra 0.36.1 requires fastapi<0.137/redis<8.0/uvicorn<0.50, all three violated by onex-api\047s live pins. This verifier therefore lives here and consumes the rendered workflow_receipt.json as a durable artifact rather than importing the renderer. 2. HandlerKafkaReplay.handle() (ModelKafkaReplayOutput) exposes only correlation_id_chain/offsets/counts, not decoded payload content. Its envelope_deserializer extension point is used to capture the decoded terminal fields into a side-channel this verifier owns. Acceptance tests (all RED-then-GREEN driven against the real HandlerKafkaReplay through its documented consumer_factory test seam): 1. No replay/verify wrapper existed before this change. 2. Replay reproduces byte-identical terminal_event_hash -> PASS. 3. A mutated replay input -> FAIL with a named field diagnostic. Seams: - kafka.replay: node_kafka_replay_compute contract.yaml handler_routing, operation kafka.replay, HandlerKafkaReplay -- driven directly, not reimplemented. - Wire shape: wire_shape.parse_delegation_terminal_envelope mirrors omninode_infra workflow_terminal_consumer.parse_terminal_envelope field-for-field (cross-repo, no shared package available -- see wire_shape.py docstring). Pinned by test_wire_shape_matches_terminal_consumer.py. - Hash: receipt_hash.sha256_of/canonical_json mirrors workflow_receipt_renderer._sha256/_canonical_json byte-for-byte. Pinned by test_receipt_hash_matches_renderer.py. - Topic constants: DELEGATION_COMPLETED_TOPIC/DELEGATION_FAILED_TOPIC resolve from the canonical omnibase_infra.topics.platform_topic_suffixes registry (SUFFIX_DELEGATION_COMPLETED/SUFFIX_DELEGATION_FAILED), never hardcoded. Follow-up (not done here, out of scope): the wire-shape/hash mirrors above are exactly the class of thing omnibase_compat exists to solve -- moving both into that shared package is real follow-up work. Evidence-Source: OMN-15095, blocked-by OMN-15094 (omninode_infra#663, merged 2026-07-25T22:25:23Z as f262cfe8) Co-authored-by: jonahgabriel <jonahgabriel@users.noreply.github.com>
…olidate DEPLOY_RUNNER_* var docs (#2453) merge sweep: landing OMN-15142 after deploy-gate/OCC evidence repair and fresh clean CI.
…t catalog, T0/T1 readback, dev gotchas, prod pointer (#2454) Extends docs/runbooks/release-train-lab.md (existing mechanism doc, not a new file) with the operator-facing procedure proven live on run 30180376657 (2026-07-26, tag lab/stability/20260725T235956Z-87ec5b3165ce, overall: PASS) — the terminal success of the six-iteration OMN-14900 hardening chain. - Copy-paste tag-cut + watch procedure with expected output and a tag-content WARNING (never reuse a parked tag name). - Preflight catalog: what each of the 6 landed fixes (#2450/#2446/#2444/ #2452/#2434/#2448) catches, with pre-fix failure signatures. - T0/T1 readback discipline: health 18085/18086, contract-count floor vs. regression, discovery_errors baseline, consumer groups, vcs_ref ancestry; FAILED_ROLLED_BACK equality-proof discipline. - Dev-lane gotchas: stale workspace-build config YAML, OMN-14968 false FAILED on runtime-worker; pointer (not duplicate) to cold-lane-full-bringup.md for cold bring-up. - Prod: pointer-only section citing CLAUDE.md rules 2a/12 and the onex_change_control#4892 prep-only grant-PR pattern; explicit raw-docker-mutation prohibition citing the no-raw-prod-bypass gate. - Verification checklist + rollback section. Co-authored-by: jonahgabriel <jonahgabriel@users.noreply.github.com>
Refs OMN-14936
Refs OMN-14894
Refs OMN-15181
Refs OMN-15181
Refs OMN-15181
Refs OMN-15181
Refs OMN-15185
Refs OMN-15181
…loys Refs OMN-15181
… repo Refs OMN-15179
Merged by Codex merge sweep after OCC#4991 companion landed and branch protection reported CLEAN.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Live gate readback (2026-07-26T17:20Z)
No prod mutation, no deploy-agent/lane touch. proof_class=receipt-bound (live gh api evidence above). |
Merged by Codex merge sweep after OCC#4992 companion landed and rerun CI Summary passed.
Merged by Codex merge sweep after OCC#4993 landed and required CI Summary passed; backmerge unblocks omnibase_infra dev-to-main promotion.
|
Correction to my prior comment (2026-07-26T17:20Z): the backmerge did NOT resolve the conflict. infra#2476 merged (17:35Z) but as a squash (repo is squash-only: Real scope, verified via This PR stays open, correctly shaped (head= proof_class=receipt-bound (live gh api + git merge-tree/merge-base evidence above, all reproducible). |
OMN-15181 — promote omnibase_infra dev → main (prod-bootstrap unblock)
Promotes
dev(@cc013670) tomain(@e3c43206, ~480 commits behind). Contentis dev's tree verbatim — infra
mainisstrict=false, so no mainback-merge is required.
Driver (Finding 15, ledger 2026-07-26T17:40Z)
The prod deploy-agent self-updates from
origin/mainon every job(
git pullagainstmain, notdev, before rebuilding/redeploying). All oftoday's OMN-15181 prod-bootstrap fixes are dev-only today — the
operator-worded prod bootstrap (grant landed at onex_change_control#4926,
1be82bc9) cannot proceed to a real redeploy attempt until
maincarriesthem. This promotion is the critical path item blocking that retry.
Fix-family riding along (OMN-15181, all merged to dev today)
operation_matchhandlers (Finding 4:
AttributeError: 'dict' object has no attribute 'event_type'crash in the deployedHandlerRedeployOrchestrator)local-presence-first pull (round 2)
pinned-digest deploys (round 3)
deploy-agent executor (round 4, Finding 11):
resolve_stability_ready_digest/
verify_running_image_digest/resolve_prod_target_servicenow key offa shared
SERVICE_HEALTH_TARGET_INDEXinstead of a single lane-wide digestF14 contract correction riding along (no new commit — already on dev)
contracts/llm_endpoints.yamlondevalready declaresembeddings-201at:8002(landed 2026-07-01, PR#2170/OMN-13807).origin/main— the ancestryanchor
check_prod_promotion_lineage.pyuses for prod release builds — stilldeclares it at the stale
:8100. Live dual-probe evidence (ledger2026-07-26T16:30Z):
:8002returns HTTP 200 (vllm text-embedding-qwen3serving),
:8100unreachable. This promotion closes that drift as a sideeffect of bringing main current with dev; no separate contract edit is
needed or included here.
Scope / non-goals
omninode-pc.
review/gate-clearing only.
Refs: OMN-15181, OMN-13418 (parent epic)
promotion-receipt: OCC-PENDING