Skip to content

feat(OMN-20578): vendor the routing-feedback and alert-channel liveness projection migrations ahead of omnimarket#3416 and #3417 - #4573

Merged
jonahgabriel merged 4 commits into
devfrom
jonah/omn-20578-vendor-routing-feedback-alert-liveness
Oct 5, 2026
Merged

jonahgabriel merged 4 commits into
devfrom
jonah/omn-20578-vendor-routing-feedback-alert-liveness

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Ticket: OMN-20578

Summary

omnimarket PRs omnimarket#3416 and omnimarket#3417 add projection nodes whose tables omnibase_infra neither vendors nor grants. This change vendors the four migration files byte-identically under docker/migrations/forward/nodes/node_projection_routing_feedback and docker/migrations/forward/nodes/node_projection_alert_channel_liveness. It adds application-migrations ledger rows and migration classes. It adds interim bridge declarations in LEGACY_MIGRATION_TABLE_DECLARATIONS for the two tables and their entries in the expiry test's _INTERIM_ENTRIES. It regenerates the topology instances and the nine rendered catalogs with scripts/generate_application_database_table_grants.py. It adds assertions to the live ACL gate test. It adds a new test file tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py.

Changes

  • Vendors the four migration files byte-identically under docker/migrations/forward/nodes/node_projection_routing_feedback (0000 create, 0001 grant to tenant_projection_writer) and docker/migrations/forward/nodes/node_projection_alert_channel_liveness (0000 create, 0001 grant to omninode_runtime).
  • Adds application-migrations ledger rows for tenant and omninode_internal domains with sha256 pins.
  • Adds migration classes; the liveness 0000 is forward-only because it creates a unique index; the others are expand-only.
  • Adds interim bridge declarations in LEGACY_MIGRATION_TABLE_DECLARATIONS for the two tables and their entries in the expiry test's _INTERIM_ENTRIES (omnimarket#3416, omnimarket#3417).
  • Regenerates the topology instances (local, onex-dev, onex-prod) and the nine rendered catalogs with scripts/generate_application_database_table_grants.py.
  • Adds assertions to the live ACL gate test.
  • Adds new test tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py with 30 cases covering bytes and ledger binding, classes, grants, topology presence, the application-database SQL gate on four profiles, and a positive control.

Proof

  • generate_application_database_table_grants.py --check --prove against the pinned omnimarket contract set (91b8bb1b8c7f) shows 3 instances in sync, 90 PASS and 0 FAIL on each of the 9 profiles.
  • The new test file passes with 30 cases.
  • pre-commit passed on commit.
  • tests/scripts/test_node_migration_fence_parity.py::test_virgin_database_applies_the_full_real_vendored_tree fails on this Mac at the existing migration 0040 with "unrecognized parameter security_invoker" because the local Postgres is older than 15; it fails before this change too and is not caused by it.

Lab readback

On dev-202 on omni-202, h202, 2026-10-05: with omnimarket#3416 and #3417 installed in omninode-dev-202-runtime and the topology instance from before this change, the runtime exited at start with ModelOnexError "Auto-wiring failed for 2 contract(s): projection_routing_feedback ... Projection binding 'tenant_projection' principal 'tenant_projection_writer' lacks declared ...; projection_alert_channel_liveness ... Projection binding 'omninode_runtime_serv...' ..." and restarted in a loop. With src/omnibase_infra/topology/instances/local.yaml from this change copied into the container, the same runtime auto-wired both writers with DB injection, subscribed both topics, and wrote rows: three cumulative routing-feedback events gave one delegation_routing_feedback row with total_count 3; a LIVE and a DEAD checked event gave two alert_channel_liveness_verdicts rows. The lane was then restored (hot-patch removed, tables dropped).

Left

Re-pair to omnimarket#3420 (OMN-20578)

  • CI run 37288260456 on head 1d31e2e was red on tests/ci/test_node_migration_shape_reconciliation.py and Migration Integration Test test_whole_corpus_converges_from_drifted_shapes (routing feedback create had no ADD COLUMN IF NOT EXISTS block); Application Database Domain Enforcement (alert_channel_liveness_verdicts and alert_channel_liveness_verdicts_projection_cursor_seq had no ownership declaration in the omnimarket manifest); Test-Failure Ratchet Gate, CI Tests Gate and CI Summary followed from those.
  • omnimarket#3420 now carries both prerequisites; the trailers below pair this PR with omnimarket#3420 at 58182a328bd1ad297dcb3f6675a89cedf91c2ffa instead of omnimarket#3416.
  • Re-vendored 0000_create_delegation_routing_feedback.sql from omnimarket#3420; sha256 pin now 43803f20610fb1ddeed49046f6c04656c5a27dfe976f0212ecfa5614f06e60f0; config/migration_classes.yaml declares it forward-only (ALTER COLUMN; ADD CONSTRAINT), as node_projection_delegation_disposition is.
  • Proof: test_node_migration_shape_reconciliation failed on the old bytes and passed on the new (385 passed with tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py); a lab run on h200 at 653c5cb caught the vendor test still expecting expand-only for that file, fixed in 8a67465; check_application_database_sql.py passed against omnimarket#3420's manifest and failed against omnimarket dev's (control); the drift integration test needs psql; the lab refused placement (exit 75, the psql hosts were over the load bar), so hosted CI is its proof.
  • Landing order: this PR lands first while omnimarket#3420 is open, then omnimarket#3420, then omnimarket#3416 and fix(OMN-18162): fold the microbenchmark nightly into nightly-tests.yml, drop the env gate, date the doctrine #3417 rebase and drop their duplicate hunks.
  • delegation-health-check is red on omnimarket delegation-regression-nightly run 37280996100, which this PR does not touch.

Node-Migration-Source-PR: omnimarket#3420
Node-Migration-Source-SHA: 58182a328bd1ad297dcb3f6675a89cedf91c2ffa

Evidence-Ticket: OMN-20578
Evidence-Source: OCC#12885

…ss projection migrations ahead of omnimarket#3416 and #3417

omnimarket adds node_projection_routing_feedback (a public platform table written by the tenant projection writer) and node_projection_alert_channel_liveness (an omninode_internal table written by the runtime principal). The node-migration vendor-parity gate refuses both PRs until these byte-identical copies are on dev, and a runtime that installs the nodes without the declared table grants exits at wiring, which the dev-202 lab runtime showed on 2026-10-05. Ledger rows, migration classes, interim bridge declarations with their expiry entries, the regenerated topology instances and catalogs, and a vendor test are included.
@jonahgabriel

Copy link
Copy Markdown
Collaborator Author

Lab: host=omni-202 (h202) lane=dev-202 (omninode-dev-202-runtime) head=1d31e2e9dfe44bcf1baafb4cdb0f58dd30bc8874 command=installed omnimarket#3416 and #3417 in the runtime, first with the existing topology instance, then with src/omnibase_infra/topology/instances/local.yaml from this PR observed=with the old instance the runtime exited at start with ModelOnexError "Auto-wiring failed for 2 contract(s): projection_routing_feedback ... principal 'tenant_projection_writer' lacks declared ...; projection_alert_channel_liveness ..." and restarted in a loop; with the instance from this PR the runtime auto-wired HandlerRoutingFeedbackWriter and AlertChannelLivenessProjectionWriter, subscribed both topics and wrote rows (three cumulative routing-feedback events gave one delegation_routing_feedback row with total_count 3; a LIVE and a DEAD checked event gave two alert_channel_liveness_verdicts rows). generate_application_database_table_grants.py --check --prove: 3 instances in sync, 90 PASS 0 FAIL on each of 9 profiles. The lane was restored and both tables dropped after the run (2026-10-05 09:06Z).

jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Oct 5, 2026
…12885)

* evidence(OMN-20578): author OCC companion for OmniNode-ai/omnibase_infra#4573

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

* evidence(OMN-20578): self-bind OCC#12885 + rebind contract_sha256

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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): 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] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0001_grant_omninode_runtime_alert_channel_liveness_verdicts.sql (qwen3-review) — Missing GRANT on BIGSERIAL sequence breaks all writes | The migration 0001_grant_omninode_runtime_alert_channel_liveness_verdicts.sql grants USAGE on the sequence 'omninode_internal.alert_channel_live
  • [MAJOR] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0000_create_alert_channel_liveness_verdicts.sql (qwen3-review) — ALTER TABLE ADD COLUMN IF NOT EXISTS without NOT NULL on existing rows | The migration 0000_create_alert_channel_liveness_verdicts.sql uses 'CREATE TABLE IF NOT EXISTS' followed by a series of 'ALTER
  • [MAJOR] docker/migrations/forward/nodes/node_projection_routing_feedback/0000_create_delegation_routing_feedback.sql (qwen3-review) — GRANT SELECT on public.delegation_routing_feedback to app_dashboard without RLS | The migration 0000_create_delegation_routing_feedback.sql creates the table in the 'public' schema and grants SELECT t
  • [MAJOR] docker/catalog/database-topology/*yaml (gpt-oss-review) — Topology entries omit schema for omninode_internal table | The new table alert_channel_liveness_verdicts is created in the omninode_internal schema, but all topology YAML files list it under object_ty
  • [MAJOR] docker/catalog/database-topology/*yaml (gpt-oss-review) — SHA256 hashes updated without verification | Multiple topology files have their source.sha256 values changed from a58dbd... to 8206b4... (or other values) but there is no evidence that the new hashes
  • [MINOR] docker/migrations/forward/nodes/node_projection_routing_feedback/0000_create_delegation_routing_feedback.sql (qwen3-review) — Missing index on delegation_routing_feedback for common query patterns | The table 'delegation_routing_feedback' has a PRIMARY KEY on (model_id, task_type). The migration does not create any additiona
  • [MINOR] tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py (qwen3-review) — Test does not verify the sequence grant for alert_channel_liveness_verdicts | The test 'test_alert_liveness_table_and_runtime_grant_are_present' in 'tests/unit/migrations/test_vendor_routing_feedback_
  • [MINOR] docker/migrations/forward/nodes/node_projection_routing_feedback/0000_create_delegation_routing_feedback.sql (qwen3-review) — Inconsistent schema placement: public vs omninode_internal | The migration creates 'delegation_routing_feedback' in the 'public' schema and 'alert_channel_liveness_verdicts' in the 'omninode_internal'
  • [MINOR] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0000_create_alert_channel_liveness_verdicts.sql (gpt-oss-review) — Potential exposure of Slack error tokens | The column slack_error in alert_channel_liveness_verdicts stores raw Slack error strings. If these contain authentication tokens or sensitive identifiers, th
  • [MINOR] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0001_grant_omninode_runtime_alert_channel_liveness_verdicts.sql (gpt-oss-review) — Division‑by‑zero pattern for grant assertions is brittle | The grant migration 0001_grant_omninode_runtime_alert_channel_liveness_verdicts.sql uses "SELECT 1 / count(*)" to assert grant existence. If

Findings demoted from threads (anchor rejected)

  • [MINOR] hostile-reviewer (qwen3-review)

    BIGSERIAL on alert_channel_liveness_verdicts may cause sequence contention | The table 'alert_channel_liveness_verdicts' uses 'projection_cursor BIGSERIAL NOT NULL' as a monotonic boundary. BIGSERIAL creates a sequence that is incremented on every INSERT. If the table is written to by multiple concurrent processes, the sequence may become a contention point. However, PostgreSQL sequences are lock-free and use atomic increments, so contention is minimal. The real issue is that the sequence is not cached, whi

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (gpt-oss-review)

    Redundant ALTER TABLE statements after CREATE TABLE | The migration 0000_create_alert_channel_liveness_verdicts.sql creates the full table schema, then immediately issues a series of ALTER TABLE ADD COLUMN IF NOT EXISTS for every column. These ALTER statements are unnecessary and add overhead during migration. | Evidence: Lines in 0000_create_alert_channel_liveness_verdicts.sql after the CREATE TABLE block, e.g., "ALTER TABLE omninode_internal.alert_channel_liveness_verdicts ADD COLUMN IF NOT EXISTS correla

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

✅ Hostile Reviewer — REVIEWED

Critical findings: 0
Major findings: 4
Total findings: 13
Models succeeded: qwen3-review,gpt-oss-review
Models unavailable: none

Action required: findings were posted as review threads. Address or reject each one, then resolve its thread — the Hostile Review Thread Gate fails while hostile-reviewer threads are unresolved (OMN-17492).


Semantics (OMN-17492 — the model finds, thread resolution gates)

Surface Meaning Blocks merge?
Review threads Per-finding, posted by the reviewer No (informational)
Hostile Review Thread Gate Deterministic: unresolved hostile-reviewer threads exist Fails until resolved (not yet a required context)
degraded verdict Fewer than 2 models succeeded (infra) Fails this job with a named reason

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)

…ion block

Re-vendors the SQL from the omnimarket source on branch jonah/omn-20578-routing-feedback-alert-liveness-prereqs (commit 58182a328bd1).
The migration adds ALTER TABLE ADD COLUMN IF NOT EXISTS for all 11 columns, SET NOT NULL, and a guarded primary key.
The sha256 pin moves to 43803f20610fb1ddeed49046f6c04656c5a27dfe976f0212ecfa5614f06e60f0 in the ledger and test files.
This fixes test_node_migration_shape_reconciliation.py and test_whole_corpus_converges_from_drifted_shapes.
sync-node-migrations.sh keeps the file frozen, so bytes were copied and the checksum re-pinned by hand.config/migration_classes.yaml now declares the file forward-only, as delegation_dispositions is.
…ack create

The reconciliation block adds ALTER COLUMN and a guarded primary key, so config/migration_classes.yaml now declares it forward-only.
test_migration_classes_match_the_classifier in tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py now expects forward-only for 0000_create_delegation_routing_feedback.sql.
The PR body trailers now name omnimarket#3420 at 58182a328bd1ad297dcb3f6675a89cedf91c2ffa, and pull_request CI reads the body from the synchronize event, so the previous head's run still paired with omnimarket#3416.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hostile Reviewer — adversarial findings (OMN-17492)

Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 7
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 5
Nit-level findings suppressed: 1

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: 5 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.

  • [MAJOR] docker/migrations/forward/nodes/node_projection_routing_feedback/0000_create_delegation_routing_feedback.sql (qwen3-review) — delegation_routing_feedback in public schema lacks RLS and tenant isolation | The delegation_routing_feedback table is created in the public schema with a composite primary key of (model_id, task_type
  • [MINOR] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0000_create_alert_channel_liveness_verdicts.sql (qwen3-review) — BIGSERIAL projection_cursor with UNIQUE INDEX creates a redundant constraint | The alert_channel_liveness_verdicts table defines projection_cursor as BIGSERIAL NOT NULL and then creates a UNIQUE INDEX
  • [MINOR] tests/integration/migrations/test_omninode_internal_live_acl_gate_omn17886.py (qwen3-review) — Missing DELETE grant assertion for alert_channel_liveness in integration test | The integration test asserts that alert_channel_liveness_verdicts has exactly {SELECT, INSERT, UPDATE} for omninode_runt
  • [MINOR] src/omnibase_infra/topology/table_grant_derivation.py (gpt-oss-review) — Legacy migration entries duplicate future contracts in table_grant_derivation | The diff adds two ContractTableDeclaration entries for legacy_migration:delegation_routing_feedback and `legacy_migr
  • [MINOR] docker/migrations/forward/nodes/node_projection_alert_channel_liveness/0000_create_alert_channel_liveness_verdicts.sql (gpt-oss-review) — Potential exposure of Slack error tokens via SELECT privilege | The alert_channel_liveness_verdicts table includes a slack_error TEXT column that may contain sensitive Slack error tokens. The gran

Findings demoted from threads (anchor rejected)

  • [MAJOR] hostile-reviewer (qwen3-review)

    Shape reconciliation ALTER COLUMN SET NOT NULL will fail on drifted tables with NULL rows | The migration 0000_create_delegation_routing_feedback.sql executes ALTER COLUMN ... SET NOT NULL on all columns after the guarded ADD COLUMN IF NOT EXISTS block. The comment in the sibling alert_channel_liveness migration explicitly acknowledges that 'NOT NULL is absent from ADDs without defaults because existing rows cannot satisfy it.' However, this migration unconditionally applies SET NOT NULL to all columns incl

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MAJOR] hostile-reviewer (gpt-oss-review)

    ALTER COLUMN SET NOT NULL may fail on pre‑existing rows | The migration docker/migrations/forward/nodes/node_projection_routing_feedback/0000_create_delegation_routing_feedback.sql adds columns to public.delegation_routing_feedback with IF NOT EXISTS and then immediately issues ALTER TABLE ... ALTER COLUMN ... SET NOT NULL without providing defaults or populating existing rows. If the table already contains data, the SET NOT NULL statements will raise an error, causing the migration to abort. | Ev

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MAJOR] hostile-reviewer (gpt-oss-review)

    Primary‑key addition may fail due to duplicate rows | The same migration (0000_create_delegation_routing_feedback.sql) conditionally adds a primary‑key constraint on (model_id, task_type) via a DO block. If the table pre‑exists with duplicate (model_id, task_type) pairs, the ALTER TABLE ... ADD CONSTRAINT ... PRIMARY KEY will error, breaking the migration. | Evidence: DO $$ BEGIN IF NOT EXISTS (SELECT 1 FROM pg_catalog.pg_constraint WHERE conrelid = 'public.delegation_routing_feedback'::regclass AND

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (qwen3-review)

    Index on (status, checked_at DESC) may be suboptimal for the stated query pattern | The comment states the index supports 'Recent measurements by status, including failures of the probe itself.' A composite index on (status, checked_at DESC) is appropriate for queries filtering by status and ordering by checked_at. However, if the common query pattern is 'latest N verdicts regardless of status,' this index is not useful. Additionally, the DESC ordering on checked_at within the composite index means the inde

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (qwen3-review)

    Unit test does not verify the NOT NULL constraint behavior on drifted tables | The unit test test_vendor_routing_feedback_and_alert_liveness.py verifies byte-identity and manifest binding but does not test the migration's behavior on a pre-existing table with NULL values. Given the concern about ALTER COLUMN SET NOT NULL failing on drifted tables, an integration test that creates a table with NULL rows and then applies the migration would catch this issue. The current test suite only validates the static SQ

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (gpt-oss-review)

    Index creation without CONCURRENTLY may block writes | The migration 0000_create_alert_channel_liveness_verdicts.sql creates idx_alert_channel_liveness_status_time and a unique index on projection_cursor using plain CREATE INDEX. On a live table with ongoing inserts, this can acquire exclusive locks, temporarily blocking writes. | Evidence: CREATE INDEX IF NOT EXISTS idx_alert_channel_liveness_status_time ON omninode_internal.alert_channel_liveness_verdicts (status, checked_at DESC); and `CREATE U

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (gpt-oss-review)

    Missing integration test for tenant writer operations on routing‑feedback table | The added unit test verifies vendor byte‑parity and manifest bindings, but there is no integration test that exercises the tenant_projection_writer role inserting and updating rows in public.delegation_routing_feedback. Absence of such a test leaves the write path unvalidated. | Evidence: New file tests/unit/migrations/test_vendor_routing_feedback_and_alert_liveness.py contains only parity checks; no integration test exe

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

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.

1 participant