M3.5: multi-model (maker/checker) loops — roles, agent compiler, inter-stage/intra-run orchestration - #4
Open
dpickem wants to merge 7 commits into
Open
M3.5: multi-model (maker/checker) loops — roles, agent compiler, inter-stage/intra-run orchestration#4dpickem wants to merge 7 commits into
dpickem wants to merge 7 commits into
Conversation
added 5 commits
July 8, 2026 17:12
Introduce per-role maker/checker loops that run different models on different providers, plus the runtime plumbing to make them portable and safe. - Manifest: `roles` block (agent + vendor/model binding) and `execution` mode (inter-stage default / intra-run); `Role.outputs` so a read-only reviewer can write its own review notes without touching code or the maker's outputs. Skill is optional when roles are present. Validation covers role agent paths, role state outputs, and the intra-run cross-provider -> Cursor rule. - Agent definitions (`agents.py`): vendor-neutral markdown-with-frontmatter behavior specs (name/description/readonly/tools/verify + body). - Agent compiler (`agent_compiler.py`): compile a role def + model into `.codex/agents/*.toml`, `.claude/agents/*.md`, `.cursor/agents/*.yaml`. - Orchestrator (`orchestrator.py`): inter-stage (ordered adapter runs, handing output through the ledger) and intra-run (compiled sub-agents in one Cursor harness); roles preflight. - Worktree-local outputs + promotion (`outputs.py`): declared outputs are staged inside the worktree and promoted to the ledger by the control plane after the run. No adapter writes outside its worktree, so Codex/Claude drop `--add-dir` and Cursor keeps its sandbox — removing the coarse `--sandbox disabled` grant from the normal path. - Cursor writable-root parity (out-of-worktree targets still supported). - Example agent defs (`agents/implementer.md`, `agents/reviewer.md`) folding in Andrej Karpathy's LLM-coding principles. - Tests for manifest roles, agent parsing/compiling, and orchestration. - README + design-doc updates.
…ane wiring) Resolves findings 1-19 of the M3.5 review. - Shared preflight dispatch (deploy.resolve_preflight) used by run, apply, and deps check, so a roles loop is validated through the multi-model path everywhere (F1). --vendor override is propagated to inherited role vendors (F8), and preflight/execution share one normalized ExecutionPlan (F7). - Mode-correct preflight: intra-run checks the harness binary + compiles every role for it; inter-stage preflights each role's own adapter via its single-stage manifest (F2, F13). - Read-only reviewer enforced by the control plane: a checker that modifies any protected worktree file fails the run and is not promoted (F3). - Agent verify + tools now govern runs: verify compiles into the instructions and is verdict-parsed (PASS/FAIL); tools are classified and a read-only role may not hold a writing tool; unmappable tools fail preflight (F4). - Promotion is transactional and success-gated: outputs promote only when a stage/run fully succeeds, via temp-file + atomic replace, and symlink/ non-regular outputs are refused (lstat) (F5, F10). - Structured inter-stage handoff (status + promoted paths/digests + stdout); Git-diff code maker/checker explicitly deferred with L4 (F6). - Compiler tracks current runtime schemas: Cursor/Claude Markdown+frontmatter, Codex TOML developer_instructions + sandbox_mode; compiled name = role key (unique destinations) (F9, F16). - Role names validated to a safe vocabulary; stage-log paths asserted contained (F11). Role outputs participate in producer-collision/DAG validation (F15). - Aggregate runtime budget enforced across stages; deterministic aggregate status and preserved per-stage metrics (F12, F14). - CLI-level roles tests (run/apply/deps, reviewer mutation, failed promotion), fully typed test signatures + typed call records (F17, F18). Cursor docstring corrected (F19). README + design doc updated.
…nsistency) Resolves review-02 blocking findings 1-8 and significant findings 9-15. - Reviewer verdict now gates the pipeline: a read-only role with a verify rubric must emit exactly one explicit `Verdict: PASS|FAIL`; missing, conflicting, or FAIL fails the stage before promotion (B1). Applies to both inter-stage and intra-run (B3). - The pipeline stops on any non-success stage, including a failed/ rejecting reviewer, so later mutating roles never run (B2). - Intra-run enforces read-only support per harness (rejects a read-only role under a Claude harness) and validates harness/role model+provider compatibility, including cross-provider-needs-explicit-model (B3, B5). - Promotion is TOCTOU-safe and transaction-validated: sources open with O_NOFOLLOW + fstat, copy via a unique mkstemp temp + atomic replace, all bindings validated before any destination is replaced, and ledger containment re-asserted (B4). - One normalized ExecutionPlan.effective_outputs drives intra-run bindings, inter-stage provenance, dry-run, and run-record declared outputs; manifest effective_outputs excludes unowned top-level outputs (B6). - Structured handoff is persisted to (and reconstructed from) the ledger, and prior-stage stdout is fenced+labelled untrusted to resist prompt injection (B7, S14). Design/README M3.5 scope + budget reconciled (B7, B8). - Aggregate runtime budget measured from pipeline start incl. overhead (B8). - Durable typed StageRunResult persisted in the run record (S9); dry-run uses the plan (S10); execution-plan/handoff/stage models are Pydantic and new test signatures are fully typed (S11). - Role tools reframed as policy validation with READ/EXECUTE/WRITE classes: a read-only reviewer may spawn sub-reviewers and run tests; connectors are not auto-classified as writing; unknown tools fail (S12). - run_multi_model fails closed on planning problems (S13); cursor preflight docstring corrected (S15). - New regression tests: verdict FAIL/missing + pipeline stop, durable stages, explicit maker outputs + dry-run, intra-run harness/model gating, promotion symlink/prevalidate-all, fail-closed planning, handoff delimiter.
added 2 commits
July 9, 2026 15:01
Verified end-to-end against a live cursor-agent: a gpt-5.5-high main agent spawns the compiler-emitted `reviewer` sub-agent running on claude-opus-4-8-high (confirmed via the run's structured taskToolCall), satisfying the M3.5 cross-provider exit criterion. - Add opt-in live smoke test tests/test_cursor_live.py, skipped by default (LOOPCRAFT_LIVE_CURSOR=1) so the suite stays offline per CONTRIBUTING.md; it drives the real agent_compiler output through cursor-agent and asserts the cross-provider sub-agent spawn from stream-json. - Remove the "not demonstrated / schema-tested only" limitation from README and the design doc; note the plan/Max-Mode caveat for per-sub-agent model honoring. The Git-diff code maker/checker remains deferred to L4.
Document the remaining correctness and safety gaps after the Review 02 fixes so the next iteration has an explicit merge gate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
M3.5 makes a loop able to decompose into per-role agents on different
providers — e.g. a
gpt-5.5implementer and anopusreviewer — and adds theruntime plumbing to make that portable and safe. A role binds a vendor-neutral
agent definition (behavior) to an execution binding (vendor + model); the
agent definition is the single source of truth for behavior and the engine is a
swappable binding on top of it.
Two execution modes:
invocation and hands a structured artifact (status, promoted ledger output
paths + sha256 digests, stdout) to the next stage through the memory ledger.
native sub-agent format and one invocation spawns them as sub-agents.
Cross-provider intra-run is native only on Cursor.
A single normalized
ExecutionPlan(resolving the--vendoroverride, per-rolevendor/model, read-only policy, and output ownership) drives dry-run, preflight,
and execution so the paths cannot drift.
Cross-provider Cursor spawn — verified live
The exit criterion "a Cursor loop spawns a cross-provider sub-agent" is
demonstrated against a real
cursor-agent: agpt-5.5-highmain agent spawnedthe compiler-emitted
reviewersub-agent running onclaude-opus-4-8-high(confirmed via the run's structured
taskToolCall, which carriessubagentType.custom.name = reviewerandmodel = claude-opus-4-8-high). Theopt-in smoke test reproduces it and is skipped offline per
CONTRIBUTING.md:Caveat: per-sub-agent model selection is plan-dependent (Max Mode / usage-based);
legacy request-based plans without Max Mode may fall back to the parent model.
What's included
rolesblock (Role= agent + vendor/model + ownoutputs),executionmode, role-name vocabulary, role-output validation, and roleoutputs in fleet producer-collision/DAG analysis.
agents.py) and compiler (agent_compiler.py):compiles a role def + model into the runtimes' current native schemas —
.cursor/agents/*.mdand.claude/agents/*.md(Markdown + YAML frontmatter),.codex/agents/*.toml(developer_instructions+sandbox_mode); compiledname = role key (unique destinations);
verifycompiles into the instructions.orchestrator.py): normalized plan; inter-stage + intra-run;mode-correct preflight; reviewer verdict gating; read-only enforcement;
aggregate runtime budget; structured handoff persisted to the ledger.
outputs.py): outputs staged inthe worktree and promoted by the control plane (no out-of-worktree writes);
TOCTOU-safe (
O_NOFOLLOW+fstat, uniquemkstemp+ atomic replace,validate-all-before-replace).
run/apply/deps checkpreflight;--vendoroverride propagation;durable per-stage
StageRunResultrecords; corrected Cursor docstring.Enforced vs deferred (M3.5 scope)
Enforced: per-role vendor/model; output ownership consistent across
modes/dry-run/fleet; read-only reviewer (control-plane hash check inter-stage;
native
readonly/sandbox_modeintra-run; read-only role rejected under aClaude harness); a single explicit reviewer
Verdict: PASS/FAIL(missing/conflicting/FAIL fails and stops the pipeline); safe, success-gated
promotion; aggregate runtime budget from pipeline start; live Cursor
cross-provider sub-agent spawn (above). Role
toolsare policy-validated(READ/EXECUTE/WRITE), not yet mapped to runtime-native allowlists.
Deferred (documented, not dropped): a code maker/checker against a real Git
worktree/diff (with L4);
max_turns/max_tokensenforcement (needs adapterusage telemetry) and
max_consecutive_failures(scheduler/store boundary).Review history
Two review rounds are addressed in-branch, each with a report + response under
docs/review_notes/:0a75645): shared preflight; mode-correct preflight; read-onlyenforcement; verify/tools; success-gated + symlink-safe promotion; structured
handoff; normalized ownership plan;
--vendorpropagation; current runtimeschemas; role-name/stage-log containment; aggregate runtime budget; unique
compiled destinations; CLI-level tests; typed signatures.
c00ef10): verdict gating + pipeline stop; intra-run verdict +harness read-only/model-compat gating; promotion TOCTOU hardening;
plan-consistent
effective_outputs; ledger-persisted handoff + untrusted-stdoutfencing; durable typed stage records; dry-run uses the plan; Pydantic models;
role-tool policy validation; fail-closed direct execution.
92005e9): the cross-provider spawn demonstratedend-to-end + opt-in smoke test.
Test plan
make test— 410 passing, 1 skipped (the opt-in live test), fully offlinemake compile/make validate/make checkLOOPCRAFT_LIVE_CURSOR=1 uv run pytest tests/test_cursor_live.py -q