eebb5718a8
Per-attempt MCP subprocesses that enforce V1 contract invariants at
construction time. Worker LLM calls builder tools incrementally; the
MCP validates each call against the schema + cross-field invariants;
`{role}_finalize()` emits canonical Pydantic-validated JSON to stdout
for the worker controller to read (Phase 1c). Defense-in-depth: the
controller strict-parses whatever finalize emits.
Builders shipped:
- reviewer_builder: 9 tools. Auto-acks all CISummary gates as passed
at start; reviewer only calls record_gate to discuss specifics.
reviewer_override_gate requires ≥20-char justification. Approve
with any failed gate is refused with an actionable error pointing
at the override path. Request-changes requires ≥1 blocking issue.
Verdict-vs-blocking-issues invariant checked at finalize.
- implementer_builder: 7 tools. Outcome-specific finalize invariants:
resolved → ≥1 commit + ≥1 file; blocked → ≥1 blocker; noop → no
commits/files/blockers.
- estimator_builder: 4 tools. Lightweight; requires
recommended_tier + confidence + reasoning at finalize. Reasoning
capped at 2048 chars.
- conflict_resolver_builder: 8 tools. outcome='resolved' requires
new_head_sha + ≥1 commit + ≥1 file. resolution_strategy enum-checked.
- summarizer_builder: 3 tools. Summary 50-2000 chars (enforced at
MCP layer and Pydantic).
Shared infrastructure:
- _builder_base.py: BuilderState dataclass + invariant guard helpers
(require_started / require_not_finalized) + audit-record-with-summary
+ finalize_and_emit (validates against Pydantic model class,
emits canonical JSON to stdout, marks finalized).
41 builder tests in test_mcp_builders.py (happy paths + every
invariant + outcome-specific paths + audit summarization + JSON
round-trip through Pydantic strict-parse). Plus the existing 62
Phase-0 tests. 103 controller tests total. Full auto_agents suite
(2465 tests) still passes.