Repository navigation
fix(OMN-17427): enforce json_schema for local-coder code-edit turns - #3295
Conversation
|
| 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/cli/cli_local.py:236: HandlerLocalDashboardServe().handle(
src/omnimarket/nodes/node_delegate_skill_orchestrator/ports/port_local_delegation_dispatch.py:965: self._effect_handler = effect_handler or HandlerLlmDelegationCall()
src/omnimarket/nodes/node_delegate_skill_orchestrator/ports/port_local_delegation_dispatch.py:966: self._projection_handler = projection_handler or HandlerProjectionDelegation(
src/omnimarket/nodes/node_delegate_skill_orchestrator/ports/port_local_delegation_dispatch.py:3289: HandlerProjectionLlmCost().project(call_event, self._evidence_db)
src/omnimarket/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py:1370: loop = HandlerComplianceLoop()
src/omnimarket/nodes/node_delegation_orchestrator/handlers/handler_delegation_workflow.py:2265: HandlerEscalationDecision()
src/omnimarket/nodes/node_local_dashboard_serve_effect/handlers/handler_local_dashboard_serve.py:226: handler=HandlerProjectionRead(topic_map=topics, row_source=source),\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).
local-coder now declares supports_response_format_json_schema: true. This aligns with local-heavy-reasoning, which serves the same model. The code-edit turn protocol now closes each action over its own tool. Arguments come from ALLOWED_ARGUMENTS and REQUIRED_ARGUMENTS. This ensures replies accepted by the gate are parse_turn_reply valid. In the last 24 h, 304 local-rung attempts were refused no_schema. All refusals occurred on code-edit loop turns in the dev lane. A/B on 20 failing turn prompts: first-attempt accepted 12/20 -> 20/20.
6988fa0 to
397b422
Compare
✅ Hostile Reviewer — PASSEDBlocking findings (critical/error): 0 Gate semantics
Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524) |
|
Lab: host=h201 lane=deleg-quality-2-2a21 head=397b42253 rebase and retarget complete |
Summary
The worst answer-quality class in the last 24 h of lab delegation is code_generation turns from the delegated code-edit loop refused
no_schema_conforming_json: the model answers a prose line instead of the declared JSON object. This declaressupports_response_format_json_schema: trueon local-coder, so the code-edit response contract goes out as a provider-nativejson_schemaconstraint instead of prose only, and closes each action in that contract over its own tool's arguments so the gate and the loop's parser accept the same replies. On the same 20 failing turn prompts, first-attempt acceptance on local-coder went from 12/20 to 20/20.Ranking (lab dev lane, last 24 h)
Most terminal failures in document and review are timeouts, provider errors and runtime shutdowns, not answer quality. In code_generation the largest answer-quality class is DELIVERABLE_EXTRACTION: no_schema_conforming_json: 304 attempts across 170 events, every one on a code-edit loop turn; local-coder 234 of its 747 code-edit attempts, local-omnipc2-chat 48 of 485.
Cause
The response contract reaches local-coder only as prose inside a 20-30k token prompt, and the model drifts into narration instead of emitting schema-conforming JSON.
Change
A/B: same 20 prompts through onex delegate
All arms:
onex delegate --task-type code_generation --backend-id local-coder --response-contract <code-edit contract>over the same 20 failing code-edit turn prompts; pass = the first attempt accepted by the quality gate.--bus kafka --lane dev --locus deployed-lane)--bus inmemory --locus in-process)bifrost_delegation.yamlandRESPONSE_CONTRACTRESPONSE_CONTRACT, flag offThe in-process arms raise local-coder's max_grounded_input_tokens from 8000 to 60000 in both before and after, because the in-process path refuses these 20k-token prompts at the 8000 grounding budget and the dev lane does not; nothing else differs between before and after. The after arm cannot run on the dev lane until this deploys, because the deployed lane runs the released contract and a pin to local-heavy-reasoning for code_generation is refused by routing; the control arm shows the json_schema directive carries the gain.
Lab readback
Runtime-affecting (routing contract). Lab evidence above is from h201 against the .201 endpoint, after-arm run ids d7086335-43b2-4125-a15d-fa2ec38966a6, 0b47cc17-7670-43a6-8fcf-a6268354532f, ce33b7d1-7b19-46e9-9c75-c92296e6bbf0 (first three of twenty). After deploy, the readback is the same 20 prompts on the dev lane pinned to local-coder, expecting first-attempt acceptance near 20/20, and the no_schema_conforming_json count on local-coder in delegation_events falling.
Tests
Focused: test_handler_delegated_code_edit_orchestrator.py, test_declared_label_set_membership_omn18989.py, test_loop_ports.py, test_tool_use_rubric.py: 336 passed. Routing/config files (same-model spread, in-process spread, weighted spread, runtime dispatch port, wire completion fidelity, backend id model family, routing authority gate, bifrost renderer reducer seam): 75 passed. ruff check, ruff format --check and mypy --strict on turn_protocol.py clean; pre-commit passed.
Ticket: OMN-17427
Evidence-Source: OCC#12518
Evidence-Ticket: OMN-17427