Skip to content

feat(OMN-10794): wire HandlerComplianceLoop into HandlerDelegationWorkflow - #1560

Merged
jonahgabriel merged 2 commits into
mainfrom
jonah/omn-10794-compliance-loop-wiring
May 10, 2026
Merged

jonahgabriel merged 2 commits into
mainfrom
jonah/omn-10794-compliance-loop-wiring

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented May 10, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence-Source: OCC#907
Evidence-Ticket: OMN-10794

Summary

Wave 3 / Task 5 of the tokens-to-compliance epic. Wires the OMN-10792 HandlerComplianceLoop into the delegation orchestrator so that delegations opting in via output_schema_key get per-attempt schema validation, repair-prompt re-issue, and accumulated tokens_to_compliance / compliance_attempts on the terminal event.

Changes

ModelDelegationRequest (additive, optional)

  • output_schema_key: str | None — when set, activates the loop. Resolves to a schema in omnimarket's output schema registry.
  • compliance_budget: ModelBudgetLimits | None — token / cost / time ceilings the loop enforces between attempts.

HandlerDelegationWorkflow.handle_inference_response (split paths)

Two paths inside the same handler:

  1. Legacy (output_schema_key is None) — accept the response on the first attempt and forward to the quality gate. Behavior unchanged.
  2. Compliance loop (output_schema_key is set) — call HandlerComplianceLoop.evaluate(...):
    • compliant → forward to quality gate, accumulate tokens
    • budget ABORT → forward to quality gate (the failure surfaces in the terminal event)
    • non-compliant + budget CONTINUE → emit a fresh ModelInferenceIntent carrying the repair prompt and stay in ROUTED (self-loop), increment compliance_attempts for the next iteration

DelegationWorkflowState

New fields: compliance_attempts: int = 0, accumulated_tokens: int = 0. The orchestrator owns the loop counters; the loop handler is per-attempt-stateless.

FSM ROUTED → ROUTED self-loop

Added to _VALID_TRANSITIONS and contract.yaml transition table. Triggered by repair re-prompts from the loop.

Terminal event population

handle_gate_result now populates tokens_to_compliance and compliance_attempts on both ModelDelegationResult and the backwards-compatible ModelTaskDelegatedEvent. Defaults preserve legacy semantics: 1 attempt, total tokens of that single attempt.

Contract bump

node_delegation_orchestrator/contract.yaml → 0.3.0 (was 0.2.0 from OMN-10792). Updated description documents the new opt-in loop wiring; FSM section adds the self-loop transition.

Tests

  • 9 new unit tests in tests/unit/nodes/node_delegation_orchestrator/test_compliance_loop_wiring.py:
    • Legacy path unchanged (2 tests)
    • First-try compliance accepts immediately (1 test)
    • Repair-on-failure with self-loop (1 test)
    • Two-attempt success accumulates tokens (1 test)
    • Two-attempt terminal event carries running total (1 test)
    • Budget ABORT forwards to gate (1 test)
    • Budget ABORT terminal event carries actual attempts (1 test)
    • FSM self-loop is a legal transition (1 test)
  • All 32 existing orchestrator tests still pass.
  • mypy --strict clean.
  • pre-commit clean.

Why this is a runtime change (not pure-compute)

The wiring runs in the orchestrator's hot path. Downstream consumers (HandlerProjectionDelegation from OMN-10793, sqlite_adapter from OMN-10789) are already wired for tokens_to_compliance + compliance_attempts with safe defaults, so a rolling restart is the only deploy step. No schema migration, no data migration.

Files

  • src/omnibase_infra/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py
  • src/omnibase_infra/nodes/node_delegation_orchestrator/models/model_delegation_request.py
  • src/omnibase_infra/nodes/node_delegation_orchestrator/contract.yaml
  • tests/unit/nodes/node_delegation_orchestrator/test_compliance_loop_wiring.py
  • contracts/OMN-10794.yaml

Summary by CodeRabbit

  • New Features
    • Optional compliance-loop controls for delegation requests (activate schema validation and repair re-prompts), automated retries until acceptance or budget exhaustion, and terminal metrics for tokens-to-compliance and compliance attempts; legacy requests remain unchanged.
  • Documentation
    • Contract/interface docs updated to describe the compliance-loop behavior and version bump.
  • Tests
    • New unit and end-to-end tests validating legacy and compliance-loop flows, retries, budget aborts, and accumulated metrics.

Review Change Stack

…kflow

Wave 3 / Task 5 of the tokens-to-compliance epic.

Adds optional ``output_schema_key`` and ``compliance_budget`` fields to
ModelDelegationRequest. When set, HandlerDelegationWorkflow.handle_inference_response
invokes HandlerComplianceLoop per attempt:

* compliant or budget ABORT → record the attempt, transition ROUTED → INFERENCE_COMPLETED, forward to the quality gate (terminal event carries the running tokens_to_compliance + compliance_attempts)
* non-compliant + budget CONTINUE → emit a fresh ModelInferenceIntent carrying the repair prompt and stay in ROUTED (self-loop), incrementing compliance_attempts for the next iteration

DelegationWorkflowState gains ``compliance_attempts`` and ``accumulated_tokens``;
the FSM transition table allows ROUTED → ROUTED for the repair re-prompt path
(both in code _VALID_TRANSITIONS and in contract.yaml). Bumps node contract
version to 0.3.0 and updates the FSM transition documentation.

The compliance counters are populated onto the terminal ModelDelegationResult
and ModelTaskDelegatedEvent so the omnimarket projection (OMN-10793) and the
omniclaude sqlite_adapter (OMN-10789) can write them to delegation_events.

Backwards compatibility: legacy callers that omit ``output_schema_key`` get
the existing single-attempt path unchanged. Their terminal event carries
``compliance_attempts=1`` and ``tokens_to_compliance`` equal to that single
attempt's total_tokens — semantically equivalent to first-try success.

Tests: 9 new unit tests prove first-try compliance, repair-on-failure with
self-loop, two-attempt token accumulation, budget ABORT path, and FSM
self-loop legality. 32 existing orchestrator tests still pass. mypy strict
clean. pre-commit clean.

Evidence-Source: OCC#905
Evidence-Ticket: OMN-10794
@jonahgabriel
jonahgabriel enabled auto-merge (squash) May 10, 2026 10:24
@coderabbitai

coderabbitai Bot commented May 10, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8d4695c2-0981-4c66-beca-b43c556e9be9

📥 Commits

Reviewing files that changed from the base of the PR and between 0f51e0e and 9921c4b.

📒 Files selected for processing (2)
  • src/omnibase_infra/nodes/node_delegation_orchestrator/models/model_delegation_request.py
  • tests/integration/delegation/test_compliance_loop_wiring_integration.py

📝 Walkthrough

Walkthrough

This PR implements a compliance-loop feature for the HandlerDelegationWorkflow orchestrator, allowing schema validation and repair re-prompts during LLM inference. The request model gains optional output_schema_key and compliance_budget fields. The FSM permits ROUTED -> ROUTED self-loops for repair re-prompts. The workflow accumulates compliance attempt and token counters, forwarding them to terminal results. Legacy callers omitting output_schema_key follow a single-attempt path unchanged.

Changes

OMN-10794: Compliance-Loop Wiring

Layer / File(s) Summary
Request Model & Contract Definition
src/omnibase_infra/nodes/node_delegation_orchestrator/models/model_delegation_request.py, contracts/OMN-10794.yaml
ModelDelegationRequest adds optional output_schema_key and compliance_budget fields to enable compliance-loop behavior; OMN-10794.yaml defines the feature contract with FSM behavior, backwards-compatibility assertions, and verification checks.
FSM & Node Contract Updates
src/omnibase_infra/nodes/node_delegation_orchestrator/contract.yaml
Node and contract versions bumped to 3; contract description documents compliance-loop semantics; FSM transitions extended with ROUTED -> ROUTED self-loop trigger and refined ROUTED -> INFERENCE_COMPLETED transition.
Core Workflow Implementation
src/omnibase_infra/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py
Workflow state gains compliance_attempts and accumulated_tokens counters; FSM transition map permits self-loop; new helpers evaluate compliance responses and emit repair ModelInferenceIntents; handle_inference_response branches on output_schema_key presence to support legacy and loop paths; handle_gate_result derives and forwards compliance counters to terminal results.
Tests & Validation
tests/unit/nodes/node_delegation_orchestrator/test_compliance_loop_wiring.py, tests/integration/delegation/test_compliance_loop_wiring_integration.py
New unit and integration tests cover legacy single-attempt flow, first-try success, retry accumulation, budget-abort behavior, FSM self-loop allowance, and end-to-end wiring using omnimarket compute.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A loop to refine what models say,
Repair prompts dance the ROUTED way,
Tokens tally up and attempts climb,
Legacy callers finish in one time,
Tests hop through retries — all in rhyme.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: wiring HandlerComplianceLoop into HandlerDelegationWorkflow for OMN-10794, which is the core feature across all file modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-10794-compliance-loop-wiring

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/omnibase_infra/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py`:
- Around line 368-387: The handler currently asserts workflow.routing_decision
is not None which breaks cases where handle_invocation_command leaves a ROUTED
workflow without a routing_decision; remove that unconditional assert and
instead guard usage: only require routing_decision when you actually need it
(e.g., before calling codepaths that depend on it such as _evaluate_compliance
or any routing-specific logic), or update _evaluate_compliance to accept a None
routing_decision and handle it safely; ensure unexpected/replayed inference
responses for correlation IDs are ignored (return early) when routing_decision
is missing rather than crashing.

In
`@src/omnibase_infra/nodes/node_delegation_orchestrator/models/model_delegation_request.py`:
- Around line 73-89: Add a model-level validator on ModelDelegationRequest to
enforce the invariant between output_schema_key and compliance_budget: use
pydantic's `@root_validator` (or `@model_validator` for pydantic v2) to check that
if output_schema_key is not None then compliance_budget must also be not None
(and optionally reject compliance_budget being set while output_schema_key is
None), and raise a ValueError with a clear message when the invariant is
violated so invalid combinations are rejected at validation time rather than
causing a runtime assertion in the handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 304d5c4d-ed95-47ff-893f-e862786ed4ce

📥 Commits

Reviewing files that changed from the base of the PR and between 84e789c and 0f51e0e.

📒 Files selected for processing (5)
  • contracts/OMN-10794.yaml
  • src/omnibase_infra/nodes/node_delegation_orchestrator/contract.yaml
  • src/omnibase_infra/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py
  • src/omnibase_infra/nodes/node_delegation_orchestrator/models/model_delegation_request.py
  • tests/unit/nodes/node_delegation_orchestrator/test_compliance_loop_wiring.py

…p config

Two CodeRabbit findings + Integration Test Coverage gate:

1. ModelDelegationRequest: add @model_validator(mode='after') rejecting
   output_schema_key set without compliance_budget. The compliance loop's
   evaluator requires both — catching this at model construction prevents a
   downstream assertion crash in the workflow handler when the orchestrator
   first sees the inference response. (CodeRabbit #2)

2. tests/integration/delegation/test_compliance_loop_wiring_integration.py:
   exercise HandlerDelegationWorkflow's compliance-loop path against unmocked
   omnimarket schema-registry / schema-repair / budget-policy handlers and
   prove the cross-package contract holds end-to-end (3 tests). Closes the
   Integration Test Coverage gap.

Note: CodeRabbit finding #1 (don't require routing_decision for every ROUTED
workflow in handle_inference_response) is already addressed by the existing
'if workflow.routing_decision is None: return []' guard at line 389.

Evidence-Source: OCC#907
Evidence-Ticket: OMN-10794
@jonahgabriel
jonahgabriel merged commit d3876e6 into main May 10, 2026
64 of 65 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-10794-compliance-loop-wiring branch May 10, 2026 10:57
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