refactor: nuke gratuitous XML serialization + delete argument_parser

Argument parser:
- Delete ``strix/tools/argument_parser.py`` and its tests. The SDK
  validates and types tool arguments via Pydantic before they hit our
  wrappers, and the in-container tool server receives JSON-typed
  kwargs over the wire. The string-coercion belt-and-suspenders is no
  longer pulling its weight.

XML → JSON / typed structures:
- ``create_vulnerability_report``: ``cvss_breakdown`` is now a
  ``dict[str, str]`` of the 8 metrics; ``code_locations`` is a
  ``list[dict]``. No more XML parsing in the tool or the renderer.
- ``check_duplicate``: the dedup judge now emits a single JSON object
  instead of an ``<dedupe_result>`` block. Strict JSON parser handles
  optional code-fence wrappers.
- ``agent_finish``: completion report posted to the parent inbox is a
  JSON object (``kind``, ``from``, ``agent_id``, ``success``,
  ``summary``, ``findings``, ``recommendations``) rather than a
  hand-rolled ``<agent_completion_report>`` XML envelope.
- ``create_agent``: identity preamble + inherited-context markers are
  plain bracketed labels rather than ``<agent_delegation>`` /
  ``<inherited_context_from_parent>`` envelopes.
- ``inject_messages_filter``: peer messages get a
  ``[Message from agent <id> | type=... | priority=...]`` header line
  instead of an ``<inter_agent_message>`` envelope.
- Crash + system-warning messages: bracketed labels, no XML.
- System prompt: the inter-agent block now describes the new header
  format and drops the "never echo XML envelope" rule.
- ``strix/llm/utils.py``: deleted. ``clean_content`` collapsed into a
  one-line blank-line normalizer in the agent-message renderer (the
  XML envelope scrub had nothing left to scrub).

Tests updated to match the new shapes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
0xallam
2026-04-25 12:31:07 -07:00
parent 369fa56148
commit f08ad2a634
17 changed files with 219 additions and 667 deletions
+9 -7
View File
@@ -315,10 +315,10 @@ async def test_create_agent_spawns_and_registers_child() -> None:
assert bus.names[new_id] == "recon-bot"
assert new_id in bus.tasks
# Initial input shape: identity block + task message at the end.
# Initial input shape: identity preamble + task message at the end.
initial_input = runner_calls[0]["kwargs"]["input"]
assert any(
isinstance(item, dict) and "agent_delegation" in item.get("content", "")
isinstance(item, dict) and "You are agent recon-bot" in item.get("content", "")
for item in initial_input
)
assert initial_input[-1]["content"] == "enumerate hosts"
@@ -375,8 +375,8 @@ async def test_create_agent_inherits_parent_history() -> None:
initial_input = runner_calls[0]["input"]
contents = [item.get("content", "") for item in initial_input]
assert "<inherited_context_from_parent>" in contents
assert "</inherited_context_from_parent>" in contents
assert any("Inherited context from parent" in c for c in contents)
assert any("End of inherited context" in c for c in contents)
# Parent's exact items should be in between.
assert any(c == "scope: example.com" for c in contents)
@@ -427,9 +427,11 @@ async def test_agent_finish_posts_report_to_parent_inbox() -> None:
msg = parent_msgs[0]
assert msg["type"] == "completion"
assert msg["from"] == "child-A"
assert "found 3 issues" in msg["content"]
assert "<finding>xss in /search</finding>" in msg["content"]
assert "sanitize search input" in msg["content"]
payload = json.loads(msg["content"])
assert payload["kind"] == "agent_completion_report"
assert payload["summary"] == "found 3 issues"
assert "xss in /search" in payload["findings"]
assert "sanitize search input" in payload["recommendations"]
@pytest.mark.asyncio