Skip to content

feat(OMN-20738): a typed read node for the database work ledger - #3630

Merged
jonahgabriel merged 5 commits into
devfrom
omn20738-work-ledger-query-node
Oct 9, 2026
Merged

jonahgabriel merged 5 commits into
devfrom
omn20738-work-ledger-query-node

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Ticket OMN-20738 adds a typed read node for the database work ledger.
The node is node_work_ledger_query_effect.
It uses contract.yaml with command topic onex.cmd.omnimarket.work-ledger-query-requested.v1 and terminal topic onex.evt.omnimarket.work-ledger-query-completed.v1.
HandlerWorkLedgerQuery has handle(request: ModelWorkLedgerQueryRequest) -> ModelWorkLedgerQueryResult.
A read-only lazy Postgres reader reads omninode_internal.work_ledger_rows.
The DSN env is OMNINODE_INTERNAL_DB_URL, declared in the contract.
Shared request and answer models are in omnimarket.models.work_ledger_query.

What it answers

Queries cover rows by window, kind, lane, ticket, PR, row id or term.
Every row in an answer carries its full text and its first line.
Queries cover open claims.
Queries cover holds in force with checked, released, expired and legacy counts.
Queries cover a lane's inbox (MSG without ACK, HOLD without RELEASE).
Queries cover newest row per lane.
Queries cover rulings and consents.
Every answer carries freshness (newest row_ts, newest projected_at, rows read).
Every answer carries the window's parity status (exact, not-exact or unmeasured) from the newest daily parity receipt (STATUS lane=work-ledger-parity) of each UTC day in the window.
A database error is returned in the error field.
A database error has no answer sections and no freshness.
A caller cannot read a failed read as no rows.

Why it replays raw rows

The node replays raw_row with the markdown ledger read verbs' own rules.
These rules are query, holds, inbox, open-claims.
The node does not read work_ledger_state, whose fold rules differ.
A reader's shadow comparison then differs only where the database and the file hold different rows.
The parity receipts measure these differences.
Rows stamped in the same second are ordered by (row_ts, projected_at, row_id), not file order.
The database holds every row the projection received; a markdown reader sees only the file it opened.

Tests

File is tests/test_golden_chain_work_ledger_query.py with 30 tests.
21 cases are verb calls recorded over a synthetic fixture ledger tests/fixtures/work_ledger_query.
These are replayed through the handler.
Other tests cover parity, freshness, a database error, a reader error reported once, continuation lines, contract topics and real runtime typed dispatch.
Four hand mutations of the replay rules each failed 3 tests.
These are claim close comparison, hold expiry without a surface, inbox release check, inbox action flag.
The runtime sweep import check is clean over 497 entry points.
It reported the node when its import was broken on purpose.

Lab

Lab: host=h201 lane=omn20739-ba01 head=e9a842267333f95b5068c24f0614c18508fadbf7 command="the handler read-only against the dev lane omninode_internal.work_ledger_rows, then the markdown read verbs over an export of the same rows" observed=identical answers on 8 of 8 queries over 42672 rows

  • 24 h window 2026-10-08T08:00:00Z..2026-10-09T08:00:00Z: 3543 rows, freshness newest row_ts 2026-10-09T07:59:52Z, parity not-exact from the 2026-10-08 receipt (missing 3, extra 13) and no receipt yet for 2026-10-09.
  • Same answers, same order, node versus the read verbs over the database's own 42672 rows: holds 32, three lane inboxes 1830, 120 and 58 entries, open claims 203, rulings 28, rows for one ticket 248, rows for one lane 102.
  • Against the markdown file over the database's span (2026-09-28T19:00:03Z..2026-10-09T08:00:00Z): file 44419 rows, database 42672; 2007 file rows are missing from the database (18 of them non-canonical row types) and 260 database rows are not in the file, all with source onex-ledger. These are data differences, not differences in the node's rules.- Focused test run through lab placement (this file, the branch-claim node tests, ruff, mypy strict, the runtime sweep import check): refused twice with exit 75, the one pool host that advertised had its unit slot busy. On h201 in the lane worktree the test file passed 30 of 30; ruff check, ruff format check and mypy strict on the new node and models were clean.

Evidence-Ticket: OMN-20738
Evidence-Source: OCC#13411

codex added 2 commits October 9, 2026 04:27
Adds node_work_ledger_query_effect with contract.yaml defining onex.cmd.omnimarket.work-ledger-query-requested.v1 and onex.evt.omnimarket.work-ledger-query-completed.v1.
HandlerWorkLedgerQuery implements handle(request: ModelWorkLedgerQueryRequest) -> ModelWorkLedgerQueryResult; a read-only lazy Postgres reader reads omninode_internal.work_ledger_rows.
Shared models reside in omnimarket.models.work_ledger_query.
Queries cover rows by window, kind, lane, ticket, PR, row id or term, open claims, holds in force, a lane's inbox, newest row per lane, rulings and consents.
The handler replays raw_row with the markdown ledger read verbs' own rules (query, holds, inbox, open-claims), so a reader's shadow comparison differs only where the two stores hold different rows.
Every answer carries freshness (newest row_ts, newest projected_at, rows read) and the window's parity status from the daily parity receipts (exact, not-exact, unmeasured).
A database error is returned in the error field with no answer sections and no freshness.
Golden-chain test includes 21 recorded verb calls over a synthetic fixture ledger, plus parity, freshness, error and typed-dispatch cases; 29 tests.
The reader raises WorkLedgerReadError with its message already redacted and type-prefixed; the handler reports that message as is and type-prefixes only other exceptions. Found on the lab, where an unset DSN read "RuntimeError: RuntimeError: ...". A regression test covers it.
@github-actions

github-actions Bot commented Oct 9, 2026

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_architecture_discovery_orchestrator/handlers/handler_architecture_discovery.py:109: execute = HandlerCodingAgentBus().execute\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).

@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

✅ Hostile Reviewer — PASSED

Blocking findings (critical/error): 0
Total findings: 13
Models succeeded: qwen3-review,local-studio-planner


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 read_rows(
self, *, since: datetime | None, until: datetime
) -> tuple[ModelWorkLedgerRowRecord, ...]: ...
) -> tuple[ModelWorkLedgerRowRecord, ...]: ...
def read_parity_receipts(
self, *, since: datetime, until: datetime
) -> tuple[ModelWorkLedgerRowRecord, ...]: ...
) -> tuple[ModelWorkLedgerRowRecord, ...]: ...
def freshness(
self, *, until: datetime
) -> tuple[datetime | None, datetime | None]: ...
jonahgabriel and others added 3 commits October 9, 2026 06:50
Adds contracts/OMN-20738.yaml, the DoD contract for ticket OMN-20738 (node_work_ledger_query_effect), with four acceptance criteria bound to selectors over tests/test_golden_chain_work_ledger_query.py (30 tests pass on h201). Fixes repo-evidence / dod-verify, which failed because the PR cited OMN-20738 but carried no contracts/OMN-20738.yaml.
Added node_work_ledger_query_effect to LANE_SCOPED_MAIN_OWNED_NODES to satisfy runtime profile contracts.
Regenerated docs/evidence/OMN-15423-relation-inventory.json using scripts/generate_application_relation_inventory.py.
This updates the inventory to reflect node_work_ledger_query_effect as a reader of omninode_internal.work_ledger_rows.
The four queries in work_ledger_query_reader.py previously interpolated the relation name into SQL using f-strings. This change replaces that with a quoted psycopg2 sql.Identifier to prevent SQL injection. The regex validation on the relation field remains in place. Verified against Postgres 16 that rows and receipts read back correctly and missing relations return a typed error.
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