Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/omnimarket/configs/bifrost_delegation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ backends:
- code_generation
- refactoring
- documentation
# OMN-17427 -- LIVE-PROBED 2026-10-03 on the same endpoint
# local-heavy-reasoning reads (BIFROST_LOCAL_CODER_ENDPOINT_URL,
# Qwen3.8-27B). Without the directive the code-edit loop's turns were
# refused no_schema_conforming_json on 234 of 747 local-coder attempts
# in 24 h (prose or empty content instead of the JSON object); with the
# json_schema directive 20 of 20 replayed failing turns extracted.
# Re-probe after an endpoint redeploy.
supports_response_format_json_schema: true
# OMN-16442: the `local-reasoner` backend (model_name
# Qwen3.6-27B-MTP-IQ4_XS.gguf, endpoint_url_env
# BIFROST_LOCAL_REASONER_ENDPOINT_URL → .201:8001) was DELETED. OMN-16419
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* ``RESPONSE_CONTRACT`` is the JSON Schema every turn's ``onex delegate`` run
declares, so the delegation quality gate validates the reply's shape and
nothing else (OMN-15193: a declared contract is the gate's sole authority).
Each action is closed over its own tool's arguments, so a reply the gate
accepts is one ``parse_turn_reply`` accepts, and a backend that declares
structured output is constrained to it (OMN-17427).
* ``TOOL_SCHEMAS`` are the tools as a model is offered them (OpenAI function
form), including ``replace_in_files`` for bulk edits. The tool_use rubric
reads the same schemas to judge each call.
Expand Down Expand Up @@ -118,6 +121,62 @@
for tool in EnumCodeEditTool
)

_ARGUMENT_SCHEMAS: dict[str, dict[str, object]] = {
"path": {"type": "string"},
"offset": {"type": "integer", "minimum": 1},
"file_path": {"type": "string"},
"file_paths": {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"maxItems": MAX_BULK_FILES,
},
"glob": {"type": "string"},
"pattern": {"type": "string"},
"content": {"type": "string"},
"old_string": {"type": "string"},
"new_string": {"type": "string"},
"name": {"type": "string"},
"summary": {"type": "string"},
}


def _action_schema(
tool: EnumCodeEditTool,
*,
omit: tuple[str, ...] = (),
require: tuple[str, ...] = (),
) -> dict[str, object]:
required = ["tool", *REQUIRED_ARGUMENTS[tool], *require]
properties: dict[str, object] = {"tool": {"const": tool.value}}
for name in ALLOWED_ARGUMENTS[tool]:
if name in omit:
continue
schema = _ARGUMENT_SCHEMAS[name].copy()
if name in required and schema["type"] == "string" and name != "content":
schema["minLength"] = 1
properties[name] = schema
return {
"type": "object",
"required": required,
"properties": properties,
"additionalProperties": False,
}


_ACTION_SCHEMAS: tuple[dict[str, object], ...] = tuple(
schema
for tool in EnumCodeEditTool
for schema in (
(
_action_schema(tool, omit=("glob",), require=("file_paths",)),
_action_schema(tool, omit=("file_paths",), require=("glob",)),
)
if tool == EnumCodeEditTool.REPLACE_IN_FILES
else (_action_schema(tool),)
)
)

RESPONSE_CONTRACT: dict[str, object] = {
"type": "object",
"required": ["actions"],
Expand All @@ -127,30 +186,7 @@
"type": "array",
"minItems": 1,
"maxItems": MAX_ACTIONS_PER_TURN,
"items": {
"type": "object",
"required": ["tool"],
"properties": {
"tool": {"enum": [tool.value for tool in EnumCodeEditTool]},
"path": {"type": "string"},
"offset": {"type": "integer", "minimum": 1},
"file_path": {"type": "string"},
"file_paths": {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"maxItems": MAX_BULK_FILES,
},
"glob": {"type": "string"},
"pattern": {"type": "string"},
"content": {"type": "string"},
"old_string": {"type": "string"},
"new_string": {"type": "string"},
"name": {"type": "string"},
"summary": {"type": "string"},
},
"additionalProperties": False,
},
"items": {"anyOf": list(_ACTION_SCHEMAS)},
},
},
"additionalProperties": False,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from collections.abc import Sequence
from typing import Any, cast

import jsonschema
import pytest

from omnimarket.nodes.node_delegated_code_edit_orchestrator import (
Expand Down Expand Up @@ -711,8 +712,86 @@ def test_format_is_offered_as_a_tool() -> None:
names = [t["function"]["name"] for t in schemas]
assert "format" in names
contract = cast("dict[str, Any]", RESPONSE_CONTRACT)
tool_enum = contract["properties"]["actions"]["items"]["properties"]["tool"]["enum"]
assert "format" in tool_enum
tool_names = {
variant["properties"]["tool"]["const"]
for variant in contract["properties"]["actions"]["items"]["anyOf"]
}
assert "format" in tool_names


@pytest.mark.parametrize(
("reply", "expected"),
[
(
{
"note": "n",
"actions": [
{"tool": "view", "path": "a.py", "offset": 3},
{"tool": "grep", "pattern": "x", "path": "src"},
{"tool": "finish", "summary": "done"},
],
},
True,
),
(
{
"actions": [
{"tool": "grep", "pattern": "x", "name": "n", "summary": "s"}
]
},
False,
),
(
{
"actions": [
{
"tool": "edit",
"file_path": "a.py",
"old_string": "a",
"new_string": "b",
"summary": "s",
}
]
},
False,
),
(
{
"actions": [
{
"tool": "replace_in_files",
"old_string": "a",
"new_string": "b",
"glob": "src/*.py",
}
]
},
True,
),
(
{
"actions": [
{
"tool": "replace_in_files",
"old_string": "a",
"new_string": "b",
"glob": "src/*.py",
"file_paths": ["a.py"],
}
]
},
False,
),
({"actions": [{"tool": "view"}]}, False),
({"actions": [{"tool": "write", "file_path": "a.py", "content": ""}]}, True),
],
)
def test_response_contract_and_parser_agree(
reply: dict[str, object], expected: bool
) -> None:
validator = jsonschema.Draft202012Validator(RESPONSE_CONTRACT)
assert validator.is_valid(reply) is expected
assert (parse_turn_reply(json.dumps(reply))[1] == "") is expected


def _interrupted_ports() -> FakePorts:
Expand Down Expand Up @@ -1271,15 +1350,24 @@ def test_replace_in_files_schemas_declare_arrays_and_keep_the_turn_limit() -> No
assert function["parameters"]["required"] == ["old_string"]
actions = cast(dict[str, Any], RESPONSE_CONTRACT["properties"])["actions"]
assert actions["maxItems"] == 12
properties = actions["items"]["properties"]
assert "replace_in_files" in properties["tool"]["enum"]
assert properties["glob"] == {"type": "string"}
assert properties["file_paths"] == {
variants = [
variant
for variant in actions["items"]["anyOf"]
if variant["properties"]["tool"]["const"] == "replace_in_files"
]
assert len(variants) == 2
file_paths_variant, glob_variant = variants
assert file_paths_variant["required"] == ["tool", "old_string", "file_paths"]
assert file_paths_variant["properties"]["file_paths"] == {
"type": "array",
"items": {"type": "string"},
"minItems": 1,
"maxItems": MAX_BULK_FILES,
}
assert "glob" not in file_paths_variant["properties"]
assert glob_variant["required"] == ["tool", "old_string", "glob"]
assert glob_variant["properties"]["glob"] == {"type": "string", "minLength": 1}
assert "file_paths" not in glob_variant["properties"]


# -- OMN-20291: the replay's node failure classes ------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,30 @@ def test_the_lab_backend_declares_support_on_measured_evidence() -> None:
)


@pytest.mark.unit
def test_local_coder_declares_support_on_measured_evidence() -> None:
"""OMN-17427: In the last 24 h on the lab dev lane, 304 local-rung
code_generation attempts across 170 events were refused
DELIVERABLE_EXTRACTION: no_schema_conforming_json; local-coder 234 of its
747 code-edit attempts, local-omnipc2-chat 48 of 485.
Replayed on the .201 endpoint, the refused replies are one prose line
("Let me read the remaining sections ...") or empty content instead of
the JSON object.
Probed 2026-10-03 on that endpoint with response_format json_schema over
the code-edit contract: 20 of 20 replies extracted, 0 HTTP errors.
"""

from omnimarket.delegation.structured_output import (
load_backends_declaring_structured_output,
)

declaring = load_backends_declaring_structured_output()
assert "local-coder" in declaring, (
"the local-coder backend measured to support json_schema does not declare it, "
f"so the constraint is never sent; declaring={sorted(declaring)!r}"
)


@pytest.mark.unit
def test_the_capability_travels_onto_the_resolved_backend() -> None:
"""Consumer-first, and the reason the flag lives on the RESOLVED backend.
Expand Down
Loading