Skip to content

fix(OMN-19833): projection writers report rows_upserted and route no pure fold, and a gate keeps it so - #3100

Merged
jonahgabriel merged 3 commits into
devfrom
jonah/omn-19833-projection-writers-rows-upserted
Sep 30, 2026
Merged

jonahgabriel merged 3 commits into
devfrom
jonah/omn-19833-projection-writers-rows-upserted

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • The runtime counts a projection write only under rows_upserted. The ci attempt outcome and worktree reconcile writers reported rows_written, so every real write counted as zero: a zero-row error per message, no terminal event, and the projection_apply_divergence health dimension degraded. Both now report rows_upserted. (Same defect omnimarket#3098 fixed for pr landing.)
  • Nine projection contracts routed a pure fold beside the in-process writer (board probe results, ci attempt outcome, consumer flow, lab container memory, lab lane health, prod promotion gate, runner fleet, session content, worktree reconcile). The runtime hands the fold the raw event, so it can never report a write, and where its request wraps the event it fails. Each contract now routes the writer only; the writer calls the fold in process (rule 7a).
  • New gate omnimarket.validators.projection_writer_contract: refuses an in-process writer that never reports rows_upserted and a routed fold beside an in-process writer. Wired as a pre-commit hook and as tests/validators/test_projection_writer_contract_omn19833.py, which runs in CI over the real tree, with synthetic positive controls and a check that the key and routing agree with the runtime's own _extract_rows_upserted and _topics_for_handler_entry. A vacuity floor fails a scan that sees fewer than 12 writers (15 today).

Stacking

This branch sits on the head of omnimarket#3098 (its commit is the first in this PR). Once that merges, this rebases to the two-file-class delta above.

Audit

All 15 in-process projection writers were read. The other 13 already report rows_upserted. Writers that are standalone runners (no in-process declaration) are out of scope by design.

Test plan

  • Golden-chain tests for both writers assert the runtime's _extract_rows_upserted reads their count.
  • Contract routing tests updated for the nine nodes.
  • Focused run of 55 node test files plus the new gate: 651 passed. pre-commit on the changed files passed.
  • Ticket: OMN-19833. Dev-lane readback is added below after the hot-patch proof.

Evidence-Ticket: OMN-19833
Evidence-Source: OCC#11871

Dev lane readback (hot-patched into omninode-runtime, warm restart, 2026-09-30)

  • The 13 changed node files were copied into the runtime's installed omnimarket, originals kept as .bak-omn19833 beside them, then the container was restarted (warm, no cold path).
  • Synthetic worktree-reconcile completion published to its topic: the writer stored the row, and the applied topic carried rows_upserted: 1, projected: true. Before, that count read as zero.
  • Synthetic PR lifecycle inventory with one failing check: a ci_attempt_outcome row stored, applied event carried rows_upserted: 1. No zero-row error line for either handler after the restart. Probe rows deleted afterwards.
  • Health after the restart window: overall HEALTHY, projection_apply_divergence HEALTHY, all ten dimensions HEALTHY.
  • Not exercised: the seven other contracts whose fold routing was removed (no traffic on the lab bus for them in the window). Their change is the same contract edit, covered by the new gate and the runtime-routing test.

…es the way the runtime expects

Measured on the .201 dev lane 2026-09-30T03:27Z-03:39Z when the landing
orchestrator's events first reached the bus (OMN-20127 hot-patch): the
runtime went DEGRADED on projection_apply_divergence, failing every
compose-dev lab pass, although the writer had landed 9 state rows and 34
transition rows in omnidash_analytics.omninode_internal.

Three causes, each pinned by a test that fails on the previous code:

1. The writer reported its count as rows_written. The runtime reads only
   rows_upserted (omnibase_infra _extract_rows_upserted) and reads any
   other key as 0, so every real write counted as zero. The count now sits
   under rows_upserted, and a stale-write refusal under the runtime's
   refusal key, so a redelivery logs as a refusal, not a silent zero.
2. The pure fold was routed beside the writer. It was handed the raw event,
   failed nine extra_forbidden errors per message, and its zero upserts
   also counted toward the divergence. Only the writer is routed now, as
   OMN-19721 did for its siblings; the writer calls the fold in process.
3. One writer instance is routed on four topics and the runtime runs it in
   worker threads, so a transitioned and an agent-needed event of the same
   transition overlapped on the one adapter's pool
   (PoolConnectionHolder.wait_until_released). Each message now opens its
   own adapter, on its own loop, with the DSN the runtime bound.

The tables were never absent: database_ref application resolves to
omnidash_analytics on the dev lane, which the first diagnosis did not read.

Onex-Lane: landing-projection-0510
Onex-Session: 5634e1aad3db43d594e27f74df90c7c9
…pure fold, and a gate keeps it so

The runtime counts a projection write only under rows_upserted. The ci attempt
outcome and worktree reconcile writers reported rows_written, so every real
write counted as zero (omnimarket#3098 fixed the same for pr landing).

Nine contracts also routed a pure fold beside the in-process writer; the
runtime hands the fold the raw event, so it can never report a write. Each now
routes the writer only, which calls the fold in process.

New gate omnimarket.validators.projection_writer_contract (pre-commit hook and
a pytest over the real tree plus positive controls) refuses a writer that never
reports rows_upserted and a routed fold beside an in-process writer.
@jonahgabriel
jonahgabriel enabled auto-merge (squash) September 30, 2026 07:06
@github-actions

Copy link
Copy Markdown

⚠️ Architectural Review — WARNINGS

Errors: 0
Warnings: 1

What this checks

Rule Description
ARCH-TOPIC-001 No hardcoded Kafka topic strings in handler code
ARCH-DI-001 No event_bus=None bypass
ARCH-DI-002 No direct Handler instantiation outside workflow_runner/adapters
ARCH-DI-003 No reinvented DI containers
ARCH-TOPIC-002 contract.yaml topics follow `onex.{cmd

ARCH-DI-002: Direct Handler instantiation (warning)\n\n```\nsrc/omnimarket/nodes/node_projection_ci_attempt_outcome/handlers/handler_ci_attempt_outcome_writer.py:123: self._derive = HandlerProjectionCiAttemptOutcome()

src/omnimarket/nodes/node_projection_metering_summary/handlers/handler_metering_summary_writer.py:96: result = HandlerProjectionMeteringSummary().handle(request)
src/omnimarket/nodes/node_projection_metering_summary/handlers/handler_projection_metering_summary.py:54: summary = HandlerMeteringSummary().handle(
src/omnimarket/nodes/node_projection_pr_landing/handlers/handler_pr_landing_writer.py:223: self._derive = HandlerProjectionPrLanding()
src/omnimarket/nodes/node_projection_worktree_reconcile/handlers/handler_worktree_reconcile_writer.py:49: self._derive = HandlerProjectionWorktreeReconcile()
src/omnimarket/projection/sqlite_metering_summary.py:42: result = HandlerProjectionMeteringSummary().handle(\n```\n\nHandler classes should be wired only in workflow_runner.py or adapter modules. Direct instantiation elsewhere bypasses the contract system.\n\n

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

onexbot-occ-writer Bot pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 30, 2026
…mniNode-ai/omnimarket#3100

OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head f0b55b603032b6e3ff160a91760cda734272cafd.
onexbot-occ-writer Bot added a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 30, 2026
…nimarket#3100

The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited.

Ticket: OMN-16859 (AC3b)
Onex-Workflow: OCC Receipt Runner
Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36681848018
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

✅ Hostile Reviewer — PASSED

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


Gate semantics

Verdict Meaning Blocks merge?
passed >=2 models succeeded, no critical/error findings No
blocked CRITICAL or ERROR findings found Yes
degraded Fewer than 2 models succeeded (infra unavailable/timeout) Yes (OMN-15110)

Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)

def _dispatch(event: dict[str, Any]) -> None:
try:
results.append(writer.handle(dict(event)))
except BaseException as exc:
pytestmark = pytest.mark.unit

_NODES_ROOT = Path(gate.__file__).resolve().parent.parent / "nodes"
_TOPIC = "onex.evt.test.thing-happened.v1"
…e Evidence-Source on f0b55b6

Local readback on lab host h202: 82 passed, 11 skipped over the nine test files
this PR touches. No code change.
onexbot-occ-writer Bot added a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 30, 2026
…nimarket#3100

The declared checks were executed for real in the OmniNode-ai/omnimarket checkout at the PR head by the product-repo OCC receipt runner, and the results written append-only into this companion. Producer-minted PENDING receipts are superseded by a net-new record; no existing receipt was edited.

Ticket: OMN-16859 (AC3b)
Onex-Workflow: OCC Receipt Runner
Onex-Run: https://github.com/OmniNode-ai/omnimarket/actions/runs/36684098258
@jonahgabriel
jonahgabriel merged commit 2261421 into dev Sep 30, 2026
191 of 200 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-19833-projection-writers-rows-upserted branch September 30, 2026 09:35
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.

2 participants