Repository navigation
feat(OMN-13645): flip context-ROI failed terminal live + project failed roi-runs - #1456
Conversation
…ed roi-runs node_context_roi_runner declared both terminals (context-roi-run-completed.v1 AND context-roi-run-failed.v1) but _emit_result only ever published to the completed topic, and node_projection_context_roi subscribed only to completed — so a fully-failed roi-run was never materialised into context_roi_scores and the N-arm experiment battery wedged with zero usable rows for failed runs. - runner: _emit_result routes a whole-run failure (failed_trials == total_trials, or zero cells) to the FAILED terminal; a run with at least one usable row stays on the COMPLETED terminal. Both carry the same ModelContextRoiRunResult. - projection: node_projection_context_roi subscribes to BOTH terminals so a failed run materialises rows (final_success=False / failure_stage) through the same terminal-agnostic projection path. Mirrors node_projection_delegation. Topics stay contract-sourced; no Plugin*, no new REST, event-bus is transport. Dev lane only. Deliverable 2 (feedback publisher to context-roi-runtime-row-scored.v1) is split out as a documented follow-up: the consumer needs a per-capsule ModelScoredRuntimeRow the arm-level ROI scores do not carry, and no materialised pack->capsule membership exists — blocked on a materialisation seam overlapping OMN-13647.
📝 WalkthroughWalkthroughContext-ROI run results now route to failed or completed terminal topics based on run outcome. The projection contract subscribes to both terminals, and the runner and projection tests cover failed-run materialization and terminal routing. ChangesContext-ROI terminal-topic flip
Sequence Diagram(s)sequenceDiagram
participant HandlerContextRoiRunner
participant event_bus
participant HandlerProjectionContextRoi
participant context_roi_scores
alt fully failed run
HandlerContextRoiRunner->>event_bus: publish context-roi-run-failed
else usable run
HandlerContextRoiRunner->>event_bus: publish context-roi-run-completed
end
event_bus->>HandlerProjectionContextRoi: deliver subscribed terminal event
HandlerProjectionContextRoi->>context_roi_scores: upsert rows by correlation_id
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
| 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_context_roi_runner/handlers/handler_context_roi_runner.py:285: result = HandlerContextPackBuilder().handle(request)\n\n\nHandler classes should be wired only in workflow_runner.py or adapter modules. Direct instantiation elsewhere bypasses the contract system.\n\n
Powered by node_pr_review_bot
✅ PR Review Bot — CLEANFindings: 0
Verdict semantics
Powered by node_pr_review_bot — Qwen3-Coder-30B reviewer + DeepSeek-R1 judge (OMN-7963) |
|
| Verdict | Meaning | Blocks merge? |
|---|---|---|
passed |
No critical/error findings | No |
blocked |
CRITICAL or ERROR findings found | Yes |
degraded |
All models unavailable (infra) | No (pilot) |
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)
OMN-13645 — Context-ROI terminal-topic flip: project failed roi-runs (un-wedge the experiment battery)
Track C, Deliverable 1. Deliverable 2 is split out as a documented, blocked follow-up (see below).
Problem
node_context_roi_runnerdeclared both terminals incontract.yamlpublish_topics—onex.evt.omnimarket.context-roi-run-completed.v1andonex.evt.omnimarket.context-roi-run-failed.v1— but_emit_result(handler line ~900) only ever published to the completed topic, so the failed terminal was declared-but-dead. Andnode_projection_context_roisubscribed only to the completed terminal. Net effect: a fully-failed roi-run was never materialised intocontext_roi_scores, and the N-arm experiment battery wedged with zero usable rows for failed runs — the never-implemented fix that closed the experiment epic while broken.Change (Deliverable 1)
handler_context_roi_runner.py_emit_result): route a whole-run failure (failed_trials == total_trials, or zero cells) to the FAILED terminal; a run with at least one usable row stays on the COMPLETED terminal. Both terminals carry the sameModelContextRoiRunResultpayload. This makes the declared-but-dead failed topic real (producer side).node_projection_context_roi/contract.yaml): subscribe to both terminals (consumer side). The projection handler is terminal-agnostic by construction — the failure outcome is already encoded on each row (final_success/failure_stage), so a failed run materialises rows withfinal_success=Falsethrough the exact sameproject()path. No fake per-topic branch. Mirrorsnode_projection_delegation, which already folds both the completed and failed delegation/generation terminals through oneoperation_matchhandler.Canonical compliance
CONTRACT + NODE + HANDLER only. Topics stay contract-sourced (no hardcoded literals). No
Plugin*, no new REST, event-bus is the transport. No hardcoded absolute paths; strongly-typed; no defensive defaults / silent fallbacks. Dev lane only — no prod/stability/judge touch.Deliverable 2 — feedback publisher: BLOCKED follow-up (honest diagnosis)
The brief also asked to build the missing publisher for
onex.evt.omnimarket.context-roi-runtime-row-scored.v1(consumed bynode_capsule_effectiveness_feedback_reducer). This cannot be built canonically today without fabricating data:ModelScoredRuntimeRowrequires per-capsule identity —factor: EnumContextFactor,content,source_artifact,source_commit,validity_scope(allmin_length>=1, used to derive thecapsule_hashkey).context_roi_scores/ModelAttemptReductionRow) are per-(task × arm × trial) aggregates over a context pack of multiple capsules. They carrycontext_factor_subset(a label likegolden_exemplar),context_pack_hash, outcome, androuting_source— but no single-capsule content/source provenance and no singleEnumContextFactor.context_pack_hash(the pack is built transiently bynode_context_pack_builder_compute;ModelContextPackArtifactcarriessource_artifact_hash/source_contract_hash, not thecapsule_storeidentity fields). The judge verdict (A2) is likewise not materialised onto the ROI rows.Producing a valid
ModelScoredRuntimeRowfrom arm-level ROI scores would require fabricating capsule provenance, which the doctrine forbids (no defensive/invented defaults). D2 is therefore blocked on a pack→capsule materialisation seam that overlaps the deferred OMN-13647 production context-pack enrichment workstream. Filed as a follow-up rather than shipping AI-slop.dod_evidence
DoD contract:
docs/work-tracking/contracts/OMN-13645.yaml.uv run pytest tests/test_golden_chain_projection_context_roi.py tests/nodes/node_context_roi_runner/test_handler_context_roi_runner.py -q→ 55 passed. Proves: a fully-failed run publishes on the failed terminal (and NOT completed); the projection materialises a failed run's rows (final_success=False,failure_stage=generation);handle()projects a failed-terminal envelope; the contract subscribes to both terminals.uv run pytest tests/ -q -m 'not kafka'(no-k) → 9821 passed, 48 skipped, 9 deselected.uv run mypy src/omnimarket/nodes/node_context_roi_runner/handlers/handler_context_roi_runner.py src/omnimarket/nodes/node_projection_context_roi/handlers/handler_projection_context_roi.py --strict→ Success: no issues found.uv run python -m omnimarket.nodes.node_runtime_sweep --import-check→ clean (334 entry points).ruff format+ruff check --fixclean;pre-commit runclean on all changed files.Deploy
No runtime deploy in this PR — handler-logic + contract-topic change. The serialized dev redeploy + live full-cycle proof (failed roi-run → projection row in
context_roi_scores) is run separately by the orchestrator (Redeploy #2). Devlocal/cheap_cloudtiers are currently backend-exhausted, so the wiring is proven offline (publish-routing + failed-terminal projection) independent of a fully-green generation.Evidence-Ticket: OMN-13645
Summary by CodeRabbit
New Features
Bug Fixes
Evidence-Source: OCC#3190