Back to projects
Active Started Jan 2026

Build Loop

A checked build loop for multi-file changes: assess, plan, execute, review, iterate, learn. Plan-verify, native debug-loop, dependency cooldown, DOE tuning.

Claude Code Plugin Codex Adapter Python TypeScript SQLite MLX Rally Coordination DOE Optimization

Install

claude plugin marketplace add tyroneross/RossLabs-AI-Toolkit
claude plugin install build-loop@rosslabs-ai-toolkit

Or direct from the build-loop source repo alone (no companion plugins):

claude plugin marketplace add tyroneross/build-loop
claude plugin install build-loop@build-loop

The Problem

Multi-step builds drift. The model writes code, declares success, and leaves silent failures: placeholder data that looks real, test stubs that never ran, UI pages that do not render, scope creep past the original goal. You forget an edge case. The diff drifts from the plan. The implementer makes a quiet design call you never see.

What I Built

Build Loop turns significant code changes into a checked, repeatable workflow: assess, plan, execute, review, iterate, learn. The plan names design decisions up front. The implementer reports which decisions it made. A lint compares the claim to the diff. Cheap checks catch obvious mistakes before tests run. Every number on the page traces back to a real source. The build stops if what shipped does not match what was promised.

/build-loop:run is the single command for any coding task. The orchestrator classifies intent and routes to the right mode — build, fix, refactor, optimize, research, or test. You do not choose the mode.

Architecture

Build Loop is a Claude Code / Codex plugin, not a hosted service. Orchestration logic lives in markdown prompts (portable across hosts); the checks that gate every phase transition are Python, not model judgment; a small compiled TypeScript layer exposes the bundled debugger’s cross-session incident memory over MCP. Part of the verification-gated agent-work pattern (see /toolkit/patterns/verification-gated-agents): a deterministic plan-verify lint gates execution, and a fixed seven-step Review chain with a single exit point gates merge.

flowchart LR
  U["/build-loop:run &lt;task&gt;"] --> ORCH["Orchestrator<br/>Opus 4.8, Thinking tier"]
  ORCH --> A["1 Assess<br/>reads .build-loop/ + memory"]
  A --> P["2 Plan<br/>MECE chunks"]
  P -->|stakes-gated| PS["Fable 5<br/>Advisor dispatch ladder"]
  P -->|else| PI["inline Opus<br/>(labeled fallback)"]
  PS --> GV["plan_verify.py lint<br/>+ plan-critic (Fable)"]
  PI --> GV
  GV -->|fail| P
  GV -->|pass| E["3 Execute<br/>Sonnet implementers,<br/>parallel, MECE-owned"]
  E --> COMMIT["single-writer commit<br/>audit_before_commit.py"]
  COMMIT --> R["4 Review A-G<br/>Critic/Validate/Fact-Check: Fable<br/>Optimize/Simplify: Sonnet"]
  R -->|blocking fail, up to 5x| E
  R -->|independent-auditor verdict| REP["Report<br/>write_run_entry.py"]
  REP --> L["6 Learn (optional)<br/>Haiku pattern-detector<br/>+ Sonnet self-improve"]
  A -.reads.-> MEM[("build-loop-memory<br/>SQLite, +optional<br/>Postgres/pgvector")]
  REP -.writes decisions/lessons.-> MEM

Models — which, where, why:

StageModel / tierWhere it runsWhy there
Phase 2 Plan synthesis (stakes-gated)Claude Fable (Frontier tier) via the Advisor dispatch ladderadvisor agent, a peer host, or an already-Fable sessionA wrong plan costs more downstream than the extra tokens; fires only when synthesisDensity > 5, risk-surface change, or stakes ≥ medium — below that the orchestrator synthesizes inline on its own model and labels the fallback honestly
Verification verdictsClaude Fable (Frontier tier)plan-critic, scope-auditor, independent-auditor, fix-critique, fact-checker, security/overfitting/promotion reviewersAdversarial judgment gates Report — a code build cannot ship without a real independent-auditor verdict, so the check that decides that needs frontier-grade reasoning, not a fast pass
CoordinationClaude Opus (Thinking tier)build-orchestrator, assessment-orchestrator — phase flow, dispatch decisions, gate interpretation across all 5 phasesOwns the full picture across every phase; strong reasoning without paying frontier cost on every routine call
ExecutionClaude Sonnet (Code tier)implementer subagents (parallel, MECE file ownership), optimize-runner, ui-validator, design-contract-specialistWorkhorse — writes code fast under a plan it didn’t author; deliberately kept at Sonnet even for two high-frequency advisory critics (synthesis-critic, alignment-checker) as a cost tradeoff
Pattern checksClaude Haiku (Pattern tier)mock-scanner, recurring-pattern-detector, transcript-pattern-minerBounded, structured pattern-matching that doesn’t need a larger model to stay accurate
root-cause-investigatorInherits the caller’s modelPhase 5 Iterate, debug-loop root-cause passContext-driven — runs at whichever tier dispatched it, since deep investigation needs the caller’s existing context window, not a fixed tier
Local embeddings (default)MLX mxbai-embed-large-v1, 1024-dimembed_backend.py, in-process warm daemonApple Silicon local inference — ~10ms warm, ~2ms amortized per batch item; no network hop on every memory write or recall
Local embeddings (fallback)Ollama bge-m3, 1024-dimembed_backend.py, when MLX init failsSame dimension keeps vector-store columns compatible; falls through once per process and is not retried, to keep hook latency predictable
Hybrid recall rerank (optional)BAAI/bge-reranker-v2-m3 cross-encoder (sentence-transformers)recall.py --mode hybrid, over the top-50 RRF-fused candidatesSharpens a vector+sparse+graph RRF fusion before it reaches a judge; MPS on Apple Silicon, CPU fallback; the [retrieval] extra is optional — absent, the pipeline degrades silently to RRF-only ordering

Tools & infra — which, why:

  • Python (~210 gate/helper scripts, ~75k lines) — deterministic, exit-code-contract checks the orchestrator calls at every phase transition (plan_verify.py, audit_before_commit.py, write_run_entry.py, context_bootstrap.py, parallelism.py, self_mod_verify.py) — the things a prompt can’t be trusted to grade by eye.
  • TypeScript (~34 files, compiled via tsc) — MCP server exposing the bundled debugger’s cross-session incident memory as tools plus a CLI; published as @tyroneross/build-loop on GitHub Packages.
  • SQLite — default local store for episodic/semantic memory (indexes/semantic_facts.sqlite), written through memory_writer.py / write_decision, queried by lessons_index and semantic_index.
  • PostgreSQL + pgvector (optional) — dual-write extra (.[db], lazy psycopg import) for a shared Postgres-backed store; every sync script degrades to SQLite-only when psycopg or Postgres is absent, so it’s additive, not required.
  • tree-sitter + tree-sitter-typescript — static import-graph parsing for the architecture-scan skills (sourced from NavGator).
  • networkx — graph traversal for both the memory recall graph (recall_graph.py) and the import-graph architecture analysis.
  • Rally Point (agent-rally-point) — repo-local presence file and post()-mandated write channel for multi-session/multi-tool runs (two Claude sessions, Claude + Codex); lead leases stop two orchestrators claiming the same merge, and a solo run costs only a ~100-token status poll.
  • Ollama — local HTTP daemon (localhost:11434) serving the bge-m3 embedding fallback; MLX itself runs in-process with no daemon.
  • GitHub Packages (npm registry) — publish target for the compiled MCP package; the plugin itself distributes through the Claude Code / Codex marketplace mechanism, not an npm installer.

How it works

  1. A user runs /build-loop:run <anything, in plain language> — the single command. The orchestrator (Opus, Thinking tier) classifies intent and routes to build, fix, refactor, optimize, research, or test mode; the user never picks a mode.
  2. Phase 1 Assess: context_bootstrap.py reads repo state (project type, architecture, tools, prior runs) scoped to the current repo’s memory slug, recalling past lessons and decisions via a hybrid vector + sparse + graph search (RRF fusion, optional cross-encoder rerank) against SQLite (or Postgres+pgvector, if dual-write is configured). The orchestrator defines a goal and 3-5 pass/fail scoring criteria.
  3. Phase 2 Plan: the orchestrator breaks the goal into MECE (disjoint file-ownership) chunks. Plans crossing the stakes threshold dispatch synthesis to Claude Fable via the Advisor ladder; otherwise the orchestrator synthesizes inline on its own model and labels that fallback honestly.
  4. plan_verify.py runs a deterministic lint — delete-with-callers, numeric-drift, route-change-evidence, package-state, missing-evidence — and plan-critic (Fable) runs an adversarial soft critique. A plan naming an unverified reads-from dependency cannot proceed to Execute.
  5. Phase 3 Execute: parallelism.py --check-partition validates the MECE partition is disjoint, then the orchestrator fans out up to 4 Sonnet-tier implementer subagents in parallel (Mode A) or runs inline for cross-cutting work (Mode B). Implementers edit the working tree and return files_changed plus an envelope — they never commit.
  6. The orchestrator commits sequentially through a single-writer gate (audit_before_commit.py) — the fix for an earlier failure mode where two writers raced the same checkout’s HEAD/index and lost 3 of 4 commits.
  7. Phase 4 Review runs seven ordered sub-steps behind one exit point: Critic → Validate → Optimize (opt-in) → Fact-Check → Simplify → Auto-Resolve → Report. Critic, Validate, and Fact-Check run at Fable for adversarial judgment; Optimize and Simplify run at Sonnet.
  8. A code build cannot reach Report without a real independent-auditor verdict — write_run_entry.py --scope build blocks otherwise. UI-touching changes route through IBR’s headless visual scan when installed; symbol-only checks (nm, strings, “compiles cleanly”) are never accepted as UI verification.
  9. On a blocking Review failure, Phase 5 Iterate repairs and re-validates (up to 5x classic, 25x autonomous), auto-invoking a debug-loop root-cause pass on Review-B Validate failures and Iterate attempts 2 and 3.
  10. Report writes a runs[] entry to the repo-local .build-loop/state.json, and for anything durable, a decision/lesson/milestone entry to build-loop-memory/projects/<slug>/ — segmented so one repo’s history never bleeds into another’s recall.
  11. Phase 6 Learn always emits an outcome line; when it runs a full pass it scans recent runs for recurring patterns (Haiku recurring-pattern-detector) and auto-drafts experimental skills/agents with A/B tracking (Sonnet self-improvement-architect) — promotion to skills/active/ requires explicit opt-in plus 8 or more samples.
  12. Throughout, Rally Point coordination arms if more than one agent or session is active on the repo — presence writes, MECE write-handoff briefs, and lead leases so two orchestrators never claim the same merge.

Tech stack

Python (~210 gate/helper scripts, ~75k lines) implements the deterministic transition checks; the orchestration itself is markdown prompts, not code, so the same loop runs under Claude Code (slash commands, agents, hooks) or Codex (skills, AGENTS.md) without a rewrite. A compiled TypeScript layer (~34 files) exposes the bundled debugger’s incident memory as an MCP server, published to GitHub Packages. Memory defaults to SQLite (semantic_facts.sqlite) with an optional PostgreSQL + pgvector dual-write extra for a shared store; local embeddings run on MLX (mxbai-embed-large-v1, in-process) with an Ollama (bge-m3) fallback, and optional hybrid-recall reranking uses a BAAI cross-encoder via sentence-transformers on MPS. tree-sitter and networkx back the architecture-scan and memory-graph traversal. Rally Point (agent-rally-point) coordinates multi-session, multi-tool runs. Design of Experiments (DOE) tuning backs Optimize mode.

Native Debugging

Debug-loop, debugging-memory, and logging-tracer are built into the plugin as skills — root-cause investigation without a bundled MCP server. /build-loop:debug <symptom> runs causal-tree analysis, fix, verify, critique (up to 5 iterations). The orchestrator also auto-invokes the debug loop on Review-B Validate failures and Iterate attempts 2 and 3, so you usually do not call it manually. The standalone Coding Debugger plugin can be installed for extended cross-project incident memory; build-loop bridges to it when present and keeps going with local fallbacks when not.

Three Modes In One Plugin

  • Build — features, refactors, migrations, schema changes, and any multi-file work.
  • Optimize — measurable improvements using Design of Experiments instead of one-variable-at-a-time guessing. Test six variables at once and find out which one actually moved the number.
  • Research — repo-grounded analysis before deciding whether to change code.

Hard-Won Defaults

Each round of dispatch-pattern testing has surfaced a default now baked into the loop:

  • Plan verification before execution — the plan must name the goal, files, criteria, commands, and design decisions before build work starts. plan-verify runs a deterministic lint (delete-with-callers, numeric-drift, route-change-evidence, package-state, missing-evidence); plan-critic runs a soft critique.
  • Critic plus live validation for UI — passing tests do not mean the page renders. UI work needs a critic pass and browser or IBR-style evidence.
  • Explicit ownership for workers — parallel workers get bounded MECE file ownership; the orchestrator integrates the final diff.
  • Discoverability as a criterion — a shipped feature needs a path into the UI, not just a component on disk.
  • Paid API guardrails — cost-bearing APIs require rate limits, failure handling, and explicit validation before release.

Dependency Cooldown

Build-loop refuses to install third-party JS packages (or version bumps) until the resolved version has been published for at least 7 days. Mitigates smash-and-grab npm compromises — a malicious version published then yanked within hours never reaches your lifecycle scripts. Three layers: native config injection (npm min-release-age, pnpm minimumReleaseAge, yarn npmMinimalAgeGate), a PreToolUse backstop hook for ungated projects, and a constitution rule with an advisory commit-auditor flag on <7d-old deps in lockfile diffs. User-authored scopes are exempt via a configurable allowlist.

Multi-Session Coordination

When more than one coding agent works the same repo, build-loop coordinates through Agent Rally Point — repo-local presence, write-boundary checks, durable handoffs. Auto-invoked at three trigger points (Phase 1 Assess preamble, Phase 3 chunk-close, Phase 4 Review-A); solo runs incur only a ~100-token status poll, peer runs auto-bootstrap a coord file and write presence. Lead leases prevent two orchestrators from claiming the same merge.

Host-Neutral

Claude Code gets slash commands, agents, hooks, and plugin bridges. Codex gets skills, AGENTS.md, and explicit subagent prompts only when the user authorizes parallel delegation. Other coding tools can still follow the same phase structure through a plain AGENTS.md contract. The bridges matter: build-loop can consult API Registry before integration work, architecture mapping (NavGator) before risky edits, debugger memory before repeating an old failure, and visual validation (IBR) when UI behavior matters. When a bridge is missing, the loop keeps going with local fallback checks.

Deployment Policy

Build-loop uses a repo-local policy before running push/deploy commands. Default: preview and TestFlight flows auto-run; production deploys, releases, publishes, and protected-branch pushes require explicit confirmation. Repos can override each target with auto, confirm, or block.

Results

⚠️ no benchmark yet — no aggregate build success rate, time-to-ship, or defect-escape figures have been measured.

Individual thresholds have been tuned from dispatch-pattern testing and are in production use:

  • 5+ synthesis dimensions — plans crossing this threshold auto-route to the strong model in one pass; below it, the fast model lost cross-decision context in testing.
  • 7-day dependency cooldown — new or bumped third-party JS packages are blocked until the resolved version has been published for at least 7 days.
  • 5x / 25x iteration ceiling — Review failures get up to 5 repair-and-revalidate passes in classic mode, 25 in autonomous mode, before the run stops.
  • Low solo-run overhead — a solo run under Multi-Session Coordination adds only local coord/presence writes; peer runs add a coord file and presence writes. ⚠️ not separately benchmarked.

Lessons

  1. A single-writer git contract (implementers edit and return; only the orchestrator commits) was chosen over letting parallel implementers commit directly, after two writers racing one checkout’s HEAD/index lost 3 of 4 commits in earlier dispatch testing.
  2. Deterministic gates and LLM judges were kept as two separate mechanisms rather than folded into one, because grep-checkable rules (an unwritten read-path, a missing auditor verdict) catch what a model drifts past, while an adversarial judge catches what a fixed rule can’t express — neither alone covers both failure classes.
  3. Worktree isolation for any long-running, file-editing background writer (not only committing ones) was widened from advisory prose to an enforced lint after a commit-less headless subagent outlived its dispatch by roughly 8 hours and re-applied stale edits onto the live shared checkout after a branch switch — three files were contaminated before a late completion envelope caught it.