Repository navigation
fix(OMN-14513): reconcile node_projection_baselines to real producer schema - #1768
Conversation
…schema node_projection_baselines defined local models sharing almost no field names with the real producer contract (omnibase_infra's ModelBaselinesSnapshotEvent / ModelBaselinesComparisonRow / ModelBaselinesTrendRow / ModelBaselinesBreakdownRow): a required-no-default pattern_id the producer never sends, entirely fictional trend/breakdown concepts on the consumer side, and a snapshot write that bound columns (patterns_compared/patterns_recommended) that don't exist on baselines_snapshots. Live-checked on .201 stability-test before fixing: the projection_baselines consumer group had committed offset 2 with zero lag (both real events on the topic consumed) yet all four target tables held zero rows -- confirming failure mode #1 from the ticket (every real event silently crashed inside the runtime's catch-all dispatch boundary, never a partial degrade). Fix (both consumer paths declared in this node's contract, matching the OMN-14490/14506 precedent): - HandlerProjectionBaselines (the live-wired RuntimeLocal shim) and BaselinesProjectionRunner (the standalone Kafka->Postgres runner, still declared in docker-compose.projection.yml) both now validate the canonical omnibase_infra producer models directly instead of local slim copies, stripping transport-injected `_`-prefixed keys first. - New migration 0002 recreates baselines_comparisons/baselines_trend/ baselines_breakdown with the real producer row shapes (treatment_*/ control_*/roi_pct, cohort/session_count, pattern_id/pattern_label). All three tables held zero rows in every known environment, so there was no data to preserve across the shape change. - Wired the OMN-13548 DLQ path: BaselinesProjectionRunner declares poison_dlq_topics/publish_dlq (the base class's own POISON safety net routes an escaped ValidationError there); HandlerProjectionBaselines documents that a malformed payload propagates to the wiring layer's own dlq_topics route, matching the established RuntimeLocal-shim precedent. Two sibling nodes (node_projection_baselines_roi, node_projection_baselines_quality) imported this node's now-deleted fictional models. Gave each its own local, behavior-identical copy to avoid a compile break -- NOT a fix, tracked separately as OMN-14630 since their own aggregation semantics (token_delta, retry_delta, confidence tiers) have no producer analog and need their own redesign. Behavioral proof: tests/test_omn14513_baselines_seam.py drives the producer's real envelope through the real unwrap_envelope decode seam into BOTH consumer paths. Verified RED against the pre-fix models on this branch (pydantic ValidationError: comparisons.0.pattern_id Field required; runner silently degraded to a blank/'shadow'-keyed default row) and GREEN against the canonical ones. Closes OMN-14513
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Summary
OMN-14513:
node_projection_baselinesdefined local Pydantic models sharing almost no field names with the real producer contract (omnibase_infra.services.observability.baselines.models.model_baselines_snapshot_event.ModelBaselinesSnapshotEvent/ModelBaselinesComparisonRow/ModelBaselinesTrendRow/ModelBaselinesBreakdownRow) — a required-no-defaultpattern_idthe producer never sends, entirely fictionaltrend/breakdownhandling on the consumer side, and a snapshot write that bound columns (patterns_compared/patterns_recommended) that don't exist onbaselines_snapshots.Live-checked on .201 stability-test before fixing (per the ticket's DoD): the
projection_baselinesconsumer group had committed offset 2 with zero lag (both real events on the topic already consumed) yet all four target tables held zero rows — confirming failure mode #1 from the ticket description (every real event silently crashed inside the runtime's catch-all dispatch boundary; not a partial degrade).Fix (both consumer paths declared in this node's contract, matching the OMN-14490/OMN-14506 precedent)
HandlerProjectionBaselines(the live-wired RuntimeLocal handler shim — confirmed via__init__.py's entry point + the single live.201consumer group) andBaselinesProjectionRunner(the standalone Kafka→Postgres runner, still declared live indocker-compose.projection.yml) both now validate the canonicalomnibase_infraproducer models directly instead of local slim copies, stripping transport-injected_-prefixed keys first (_strip_transport_keys).0002_realign_child_tables_to_producer_schema.sqlrecreatesbaselines_comparisons/baselines_trend/baselines_breakdownwith the real producer row shapes (treatment_*/control_*/roi_pct,cohort/session_count,pattern_id/pattern_label). All three tables held zero rows in every known environment (verified live), so there was no data to preserve across the shape change.BaselinesProjectionRunnerdeclarespoison_dlq_topics/publish_dlq(the base class's own POISON safety net now routes an escapedValidationErrorthere);HandlerProjectionBaselinesdocuments that a malformed payload propagates to the wiring layer's owndlq_topicsroute, matching the establishedHandlerProjectionRegistrationprecedent.contract.yamlinput_model/event_modelnow point at the canonical producer model path;metadata.yamldeclares theomnibase-infradependency the node-metadata scope checker requires.Scope note: two sibling nodes patched to avoid a compile break, NOT fixed
node_projection_baselines_roiandnode_projection_baselines_qualityboth imported this node's now-deleted fictionalModelBaselinesComputedEvent. Gave each its own local, behavior-identical copy of the same fictional model so this PR doesn't silently regress them — this is explicitly a no-op preservation, not a fix (their own aggregation semantics liketoken_delta/retry_delta/confidence tiers have no producer analog and need their own redesign). Filed OMN-14630 to track that follow-up.Behavioral proof (non-vacuous)
tests/test_omn14513_baselines_seam.pydrives the producer's real envelope through the realunwrap_envelopedecode seam into BOTH consumer paths and asserts all 4 target tables receive real (non-default) A/B treatment/control data.git stashagainst the pre-fix handlers on this branch):pydantic.ValidationError: comparisons.0.pattern_id Field requiredon the handler path, and the runner path silently degrading to a blank/'shadow'-keyed default row (5 of 7 expected SQL statements, missing the comparison/trend inserts).treatment_sessions/control_sessions/roi_pct/cohort/pattern_idvalues landing in the in-memory DB / SQL binds.Seams
omnibase_infra.services.observability.baselines.models.model_baselines_snapshot_event.ModelBaselinesSnapshotEvent(UUIDsnapshot_id,datetimetimestamps,extra="forbid") — matched field-for-field against the producer.baselines_comparisons/baselines_trend/baselines_breakdowncolumns now mirrorModelBaselinesComparisonRow/ModelBaselinesTrendRow/ModelBaselinesBreakdownRowfield names exactly (see migration 0002 docstring for the full mapping rationale).event_bus.dlq_topics: [onex.dlq.omnimarket.projection-baselines-malformed.v1]added tocontract.yaml.Test plan
tests/test_omn14513_baselines_seam.py— new cross-boundary regression test (RED-vs-pre-fix verified, GREEN post-fix)tests/test_golden_chain_projection_baselines.py— rewritten against the real producer modeltests/test_projection_baselines_migration_omn11887.py— extended to cover migration 0002's column shapestests/test_projection_handlers.py—TestBaselinesHandlerrewritten to drive a real producer-shaped payloadtests/nodes/node_projection_baselines_{roi,quality}/+ their golden-chain tests — re-pointed imports, still green, unchanged behavioruv run ruff format --check/uv run ruff check/uv run mypy --strictclean on all touched nodespre-commit run --files <changed>clean (Contract-state-coverage gate, Projection-DLQ path gate, node metadata dependency scope, import-check all pass).201stability-test check performed before the fix (rpk consumer-group +psqlreadback) to pin the exact failure modeEvidence-Source: OCC#4216
Evidence-Ticket: OMN-14513
Evidence-Commit: a9883449338cda6dd0fdbc374ee8866a1fa1e9a6
Evidence-Head: f0b9661
Closes OMN-14513
Merge-sweep conflict repair evidence
Codex merge sweep merged current
origin/devinto this branch and resolved the ROI/quality sibling-node conflicts by keeping the newer OMN-14630 real-producer-schema implementation fromdev, while preserving this PR'snode_projection_baselinesseam repair. Repair commit:f0b9661891a061bb8af87f8db9bcd13d9e7c3c82.Local post-merge verification from the clean OMN-14513 worktree: