@robmclarty/volley 0.10.1 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":["git"],"sources":["../src/builder/context_check.ts","../src/builder/countdown.ts","../src/types.ts","../src/engine.ts","../src/workspace_tools.ts","../src/builder/tools.ts","../src/check/checkride.ts","../src/check/command.ts","../src/cost.ts","../src/prewarm.ts","../src/containment.ts","../src/trust.ts","../src/workspace.ts","../src/worktree.ts","../src/builder.ts","../src/changes.ts","../src/critic/prompt.ts","../src/critic/run.ts","../src/render/format.ts","../src/iteration.ts","../src/summary.ts","../src/phases.ts","../src/acp_progress.ts","../src/acp_tools.ts","../src/check/detect.ts","../src/config.ts","../src/loop_state.ts","../src/flow.ts","../src/orchestrator.ts","../src/render/renderer.ts","../src/acp.ts","../src/exit_codes.ts","../src/matrix.ts","../src/preflight.ts","../src/cli.ts"],"sourcesContent":["/**\n * Best-effort local-context guard. A too-small context window\n * silently truncates the tool schemas volley sends — the #1 reported local\n * tool-calling failure (Ollama's 4k default). We warn at builder start *where\n * the value is detectable* and never block or fail on it: detection is a\n * courtesy, the setup requirement is the user's (README `## Local builder`).\n *\n * On the ai_sdk transport this probe reads the server-side `num_ctx` (a\n * Modelfile or server default). Under fascicle's native transport (the\n * deferred future bridge) `num_ctx`/`keep_alive` become per-call\n * `provider_options.ollama` options set at request time, so the value would be\n * volley's to pass rather than a server default to probe — the warning stays\n * useful either way.\n */\nimport type { BuilderProvider } from '../types.js';\n\n/** Below this, tool schemas start getting truncated for volley's tool set. */\nexport const MIN_RECOMMENDED_NUM_CTX = 16384;\n\n/** Probe timeout — a local `/api/show` answers in single-digit ms when up; a\n * hung server must not stall builder start. */\nconst PROBE_TIMEOUT_MS = 2000;\n\n/** The warning when a detected context window is too small, or null when the\n * window is adequate or unknown (`num_ctx === null` = not detectable). Pure so\n * the threshold decision is unit-testable without a server. */\nexport function context_warning(model: string, num_ctx: number | null): string | null {\n if (num_ctx === null || num_ctx >= MIN_RECOMMENDED_NUM_CTX) return null;\n return (\n `local builder model '${model}' is configured with num_ctx ${String(num_ctx)}, below the ` +\n `~${String(MIN_RECOMMENDED_NUM_CTX)} volley recommends: a small context window silently ` +\n 'truncates the tool schemas (the #1 local tool-calling failure). Raise it (e.g. a Modelfile ' +\n '`PARAMETER num_ctx 16384`) or expect the model to ignore its tools.'\n );\n}\n\n/** Pull `num_ctx` out of Ollama's newline-delimited `parameters` blob\n * (e.g. `\"num_ctx 4096\\nstop \\\"<|im_end|>\\\"\"`). Null when\n * the parameter is absent or unparseable — which is the common case for a\n * server relying on its own default, and precisely the \"not detectable\" edge. */\nexport function parse_num_ctx(parameters: string | null): number | null {\n if (parameters === null) return null;\n const match = /^\\s*num_ctx\\s+(\\d+)\\s*$/m.exec(parameters);\n if (match === null) return null;\n const value = Number(match[1]);\n return Number.isFinite(value) ? value : null;\n}\n\n/** Best-effort probe of an Ollama server for a model's configured `num_ctx`\n * via `/api/show` (`base_url` is the server root). Returns null on any\n * failure (server down, non-OK, field absent, parse/JSON error) — the\n * warning never gates the builder. */\nexport async function probe_ollama_num_ctx(\n base_url: string,\n model: string,\n abort?: AbortSignal,\n): Promise<number | null> {\n const signals = [AbortSignal.timeout(PROBE_TIMEOUT_MS)];\n if (abort !== undefined) signals.push(abort);\n try {\n const res = await fetch(`${base_url.replace(/\\/$/, '')}/api/show`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ model }),\n signal: AbortSignal.any(signals),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as { parameters?: unknown };\n return parse_num_ctx(typeof body.parameters === 'string' ? body.parameters : null);\n } catch {\n return null;\n }\n}\n\n/** Emit a small-context warning via `warn` when an Ollama builder model's\n * `num_ctx` is detectably below the recommended floor. Ollama-only — LM Studio\n * exposes no reliable pre-flight context field, so it is documented, not\n * probed. Never throws (setup friction is data, not an error). */\nexport async function warn_small_local_context(\n provider: BuilderProvider,\n model: string,\n base_url: string,\n warn: (message: string) => void,\n abort?: AbortSignal,\n): Promise<void> {\n if (provider !== 'ollama') return;\n const warning = context_warning(model, await probe_ollama_num_ctx(base_url, model, abort));\n if (warning !== null) warn(warning);\n}\n","/**\n * The tool-loop builder's step countdown. A model that explores first can\n * spend its whole budget before it verifies: in volley-41806476 the builder's\n * 50th step was a `bash` call fascicle refused, and the half-fixed tree went to\n * the check and critic. So for the last few steps of a session, each turn's\n * request ends with a note of how many are left and what to do with them.\n *\n * The note goes in through fascicle's `prepare_step`, which reshapes only what\n * one turn sends, so the transcript stays as the model wrote it, and the note\n * sits after everything a local runtime has cached, so its cached prefix holds.\n */\nimport type { PrepareStepHook } from 'fascicle';\n\n/** How many of a session's last steps carry the countdown: five, or a tenth\n * of a long budget, but never more than half of it, so a short session still\n * starts without one. */\nexport function countdown_window(max_steps: number): number {\n return Math.min(Math.max(5, Math.ceil(max_steps / 10)), Math.floor(max_steps / 2));\n}\n\n/** The note for a turn with `steps_left` steps left, this one included.\n * `check` names how to run the check. On the last step fascicle runs only a\n * call that ends the session, which for the builder is `finish`. */\nexport function countdown_note(steps_left: number, check: string): string {\n if (steps_left <= 1) {\n return (\n '[volley] This is the last step of this session, and only finish runs on it. ' +\n \"Call finish now, with a summary that says what's done and what isn't verified.\"\n );\n }\n return (\n `[volley] ${String(steps_left)} steps left in this session, this one included, ` +\n 'and on the last one only finish runs. ' +\n `If you haven't run ${check} since your last edit, run it now, ` +\n 'then fix what it reports or call finish.'\n );\n}\n\n/** The `prepare_step` hook that adds the countdown to a session of\n * `max_steps` steps. */\nexport function step_countdown(max_steps: number, check: string): PrepareStepHook {\n const window = countdown_window(max_steps);\n return ({ step_index, messages }) => {\n const steps_left = max_steps - step_index;\n if (steps_left > window) return undefined;\n return {\n messages: [...messages, { role: 'user', content: countdown_note(steps_left, check) }],\n };\n };\n}\n","/**\n * Shared value and type contracts for volley.\n *\n * Type aliases are PascalCase; value-level identifiers are snake_case.\n * Fascicle's usage/cost types are used verbatim so summaries carry the\n * substrate's shapes, not a re-derivation.\n */\nimport type { FinishReason, Throughput, UsageTotals } from 'fascicle';\n\nexport type Verdict = 'approved' | 'changes_requested';\n\nexport type CriticPreset = 'reviewer' | 'optimizer' | 'researcher';\n\n/** Transport for the critic role. The critic is read-only + schema-constrained,\n * so it has always been able to run on a local model. `openrouter` reaches a\n * hosted model over one API key and takes the local critic's tools and\n * degradation ladder. */\nexport type CriticProvider = 'claude_cli' | 'ollama' | 'lmstudio' | 'openrouter';\n\n/** Transport for the builder role. `claude_cli` is a full agentic Claude Code\n * session; every other provider runs the builder as a volley-driven tool loop\n * (write/exec tools supplied by the harness), whether its model is local\n * (`ollama`, `lmstudio`) or hosted (`openrouter`). */\nexport type BuilderProvider = 'claude_cli' | 'ollama' | 'lmstudio' | 'openrouter';\n\nexport type BuilderPermissionMode = 'acceptEdits' | 'bypassPermissions';\n\n/** `auto`, `none`, or any shell command (the `string & {}` keeps the literal\n * hints in editor completions without collapsing the union). */\nexport type CheckMode = 'auto' | 'none' | (string & {});\n\nexport type CheckRunnerKind = 'checkride' | 'command' | 'none';\n\nexport type CostSource = 'provider_reported' | 'engine_derived' | 'unknown';\n\n/** Fascicle's `provider_error.cause_kind` discriminant — why a provider call\n * died. Recorded alongside a critic retry so a degraded run says\n * *what* failed, not just that it retried. */\nexport type CauseKind = 'provider_5xx' | 'network' | 'unknown';\n\n/** Why a local critic's verdict came from the tool-less fallback:\n * `stream_error`, the tool-bearing call kept dying on the provider's stream\n * after the bounded retry; `step_exhaustion`, it spent its step budget (or\n * stopped on a tool call) without producing a verdict. */\nexport type DegradeCause = 'stream_error' | 'step_exhaustion';\n\nexport type RunStatus =\n | 'running'\n | 'success'\n | 'budget_exhausted'\n | 'cost_cap_reached'\n /** The builder edited the gate that judges it, under `--fail-on-gate-edit`:\n * the run halts on the spot rather than iterating, because a check the builder\n * can rewrite is not evidence the work is done. */\n | 'gate_edit_blocked'\n /** A critique's other outcome: the critic requested changes, or the check\n * failed, on the one change it reviewed. A run never ends this way. */\n | 'rejected'\n | 'interrupted'\n | 'error';\n\n/** What a run does: the builder/critic loop (`run`), or one check and one\n * critique of a change already made, with no builder at all (`critique`). */\nexport type RunMode = 'run' | 'critique';\n\n/** User-facing configuration, before resolution (config file / flags). */\nexport type VolleyConfig = {\n prompt: string;\n workspace: string;\n criteria: string;\n check?: CheckMode;\n builder_model?: string;\n builder_provider?: BuilderProvider;\n builder_url?: string;\n builder_max_steps?: number;\n builder_max_tool_calls?: number;\n builder_max_output_tokens?: number;\n allow_unsandboxed_builder?: boolean;\n critic_model?: string;\n critic_provider?: CriticProvider;\n critic_url?: string;\n builder_permission_mode?: BuilderPermissionMode;\n critic?: CriticPreset | (string & {});\n max_iterations?: number;\n max_cost_usd?: number | null;\n git_checkpoints?: boolean;\n worktree?: boolean;\n discard_worktree?: boolean;\n gate_paths?: string[];\n fail_on_gate_edit?: boolean;\n sandbox_image?: string;\n state_dir?: string;\n verbose?: boolean;\n quiet?: boolean;\n json?: boolean;\n show_thinking?: boolean;\n dry_run?: boolean;\n};\n\n/** Fully resolved run configuration; the run's `config.json` mirrors this. */\nexport type ResolvedConfig = {\n version: 2;\n run_id: string;\n started_at: string;\n /** A run, or a critique (`volley critique`). A critique's builder fields\n * hold the defaults, untouched by flags and the environment, since no\n * builder is ever constructed, and its loop settings are one round with\n * nothing isolated or committed. */\n mode: RunMode;\n /** The task. A critique needs none, since a critic judges against the\n * criteria alone, so it's empty unless one was given to record. */\n prompt: string;\n criteria: string;\n check: CheckMode;\n check_resolved: CheckRunnerKind;\n builder_model: string;\n builder_provider: BuilderProvider;\n /** The builder seat's own model server base URL (`--builder-url`), as given.\n * It is normalized, and crossed to the host LLM endpoint when contained, only\n * where it is used, because the crossing depends on where the run executes.\n * Null falls back to the provider's env var (`VOLLEY_OLLAMA_URL` /\n * `VOLLEY_LMSTUDIO_URL` / `VOLLEY_OPENROUTER_URL`), then its default, never to\n * the critic's URL. Only a provider volley reaches at a base URL (ollama,\n * lmstudio, openrouter) takes one. */\n builder_url: string | null;\n builder_max_steps: number;\n /** How many tool calls a tool-loop builder may make in one turn, reads\n * aside (`read_file`, `search_files`, `list_files` are `read_only` and\n * don't count); fascicle runs a turn's calls in order up to the first one\n * past the cap, drops the rest, and tells the model which it dropped. 1 by\n * default, since some model and runtime pairs return parallel calls badly;\n * raise it for a pair that handles them. Ignored by the `claude_cli`\n * builder. */\n builder_max_tool_calls: number;\n /** The most output tokens a tool-loop builder may generate in one turn,\n * reasoning included, or null to leave each turn to the provider's own\n * limit. 16384 by default on a local builder (ollama, lmstudio), null on\n * openrouter. A turn cut off at it before it made a tool call costs that\n * one step, not the session: fascicle feeds back that it hit the limit and\n * the loop goes on. Ignored by the `claude_cli` builder. */\n builder_max_output_tokens: number | null;\n /** Operator opt-out permitting a non-`claude_cli` builder to run without a\n * sandbox — it gets a real host bash. Refused by default. */\n allow_unsandboxed_builder: boolean;\n critic_model: string;\n critic_provider: CriticProvider;\n /** The critic seat's own model server base URL (`--critic-url`), as given;\n * resolved like `builder_url`, and null never falls back to the builder's. */\n critic_url: string | null;\n builder_permission_mode: BuilderPermissionMode;\n critic_preset: CriticPreset | 'custom';\n critic_prompt_path: string | null;\n max_iterations: number;\n max_cost_usd: number | null;\n git_checkpoints: boolean;\n /** Isolate the builder run's effects in a per-run git worktree: the\n * builder/critic file tools' containment root moves to the worktree, while\n * the run's state stays where `state_dir` puts it (the control plane). Off by\n * default; requires the workspace to be a git repository. */\n worktree: boolean;\n /** Throw a `--worktree` run's effects away at teardown even when it converged:\n * the run branch is force-deleted rather than kept, because only the\n * verdicts are wanted. This is what `volley matrix` sweeps with — one config,\n * many builder×critic seats, no per-seat commits or branches left anywhere.\n * Refused without `--worktree`; `--git` still wins, so a `--worktree --git`\n * run integrates exactly as it always has. */\n discard_worktree: boolean;\n /** Glob patterns naming the *gate*: the tests, fixtures, and check\n * configuration that decide whether the builder's work passes. An edit to one\n * is reported to the critic and recorded in the summary — and refused outright\n * under `fail_on_gate_edit`. Defaults to `DEFAULT_GATE_PATTERNS`; a config's\n * own list replaces it, because what counts as the gate is the task's call\n * (a test-writing task edits tests by design). */\n gate_paths: string[];\n /** Halt the run when the builder edits a `gate_paths` match, instead of\n * reporting it and continuing. Off by default: a gate edit is legitimate often\n * enough that refusing it by default would break honest tasks, and the mark on\n * the summary already makes it impossible to miss. */\n fail_on_gate_edit: boolean;\n /** Container image the local-builder Docker sandbox runs. Defaults to\n * volley's own `Dockerfile`-built image; `--sandbox-image <tag>` /\n * `VOLLEY_SANDBOX_IMAGE` override it. Meaningful only for a local builder —\n * the `claude_cli` path never uses Docker. */\n sandbox_image: string;\n /** The root that holds each run's state at `<state_dir>/<run_id>/`, as an\n * absolute path: `--state-dir`, else the default root,\n * `$XDG_STATE_HOME/volley` or `~/.local/state/volley`. `resolve_config`\n * always sets one. Null is the layout older runs used, `<workspace>/.volley/`,\n * rotated aside by the next fresh run: a run an older volley started\n * resumes in it, and a hand-built config can still ask for it. */\n state_dir: string | null;\n workspace: string;\n verbose: boolean;\n quiet: boolean;\n json: boolean;\n show_thinking: boolean;\n};\n\n/** One failing check slot's raw artifact, for the critic prompt. */\nexport type CheckArtifact = {\n slot: string;\n path: string | null;\n content: string;\n truncated: boolean;\n};\n\nexport type CheckResult = {\n ran: boolean;\n runner: CheckRunnerKind;\n ok: boolean;\n exit_code: number | null;\n duration_ms: number;\n failing_slots: string[];\n detail: CheckArtifact[];\n /** Raw checkride summary JSON (when the runner is checkride). */\n summary?: unknown;\n /** checkride's capped excerpt of the failing slots (`.check/digest.md`),\n * when the check failed and checkride wrote one. */\n digest?: string;\n /** Captured combined output (when the runner is a shell command). */\n log?: string;\n};\n\n/** How one path changed between the run's baseline and the builder's output.\n * `renamed` covers git's rename/copy detection (the destination path is the one\n * recorded); `unknown` is any status git reports that none of these name. */\nexport type ChangeStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'unknown';\n\n/** One path the builder changed, and whether that path is part of the *gate* —\n * the tests, fixtures, and check configuration that decide whether the work\n * passes. A gate edit is not misconduct by itself (some tasks are *about* the\n * tests); it is the fact that makes a green check prove less. */\nexport type ChangedFile = {\n path: string;\n status: ChangeStatus;\n gate: boolean;\n};\n\n/** What the builder changed since the run's baseline, as the harness sees it\n * (`src/changes.ts`). Null in `LoopState` when the build root is not a git\n * repository — change detection is evidence, never a precondition. */\nexport type ChangeSet = {\n /** The commit the changes are measured against — the build root's HEAD before\n * the first iteration. Null in a repository with no commits yet, where only\n * untracked files can be reported. */\n baseline: string | null;\n /** The changed paths, sorted, capped at the collection limit. */\n files: ChangedFile[];\n /** Every gate-matching path — computed over the *full* list before the cap,\n * so truncation can never hide a gate edit. */\n gate_edits: string[];\n /** How many paths changed in total, before the cap. */\n total: number;\n truncated: boolean;\n};\n\n/** Per-phase record for iteration summaries. */\nexport type PhaseRecord = {\n provider: string;\n model: string;\n session_id: string | null;\n /** Wall-clock of the phase's model work, the same measure for every provider\n * so an all-local run and an all-Claude run compare directly. The builder's is\n * fascicle's `GenerateResult.timing`: the whole call, every turn and the tools\n * between them. The critic's spans its whole degradation ladder, failed\n * attempts included, since no one result's timing covers the attempts before\n * it. Neither counts the Ollama prewarm. */\n duration_ms: number;\n usage: UsageTotals;\n cost_usd: number | null;\n cost_source: CostSource;\n /** How the phase's generate call ended. For a local builder,\n * `'max_steps'` is a budget cutoff surfaced as a warning, not an error. */\n finish_reason: FinishReason;\n /** Tool calls fascicle executed in this phase, and how many were recovered\n * from assistant text rather than returned structurally — the raw\n * counts behind the salvage-rate health metric. */\n tool_calls: number;\n salvaged_tool_calls: number;\n /** Turns the provider cut off at the output cap before they made a tool\n * call (`--builder-max-output-tokens`), each of which cost a step and went\n * on. Set on a builder record when any was; absent otherwise. Additive. */\n truncated_turns?: number;\n /** Provider-error retries that preceded this phase's successful call\n * — the local-critic degradation ladder's first rung: a stochastic\n * Ollama stream death is retried once before falling back. Set on the critic\n * record (0 when the first call succeeded); absent on the builder, which is\n * not retried this build. Additive — old summary consumers ignore it. */\n retries?: number;\n /** The `cause_kind` of the retried provider error, recorded with `retries`.\n * Absent when no retry happened. */\n retry_cause_kind?: CauseKind;\n /** This local-critic verdict was rendered by the tool-less fallback rung:\n * the tool-bearing critique kept dying on the provider's stream\n * even after the bounded retry, or ran out of steps before its verdict, so the\n * critic judged with no read access — grounded only by the criteria, the raw\n * check artifacts, and a workspace file inventory. Set (true) on a degraded\n * critic record; absent on a full critique and on the builder. Additive, and a\n * degraded verdict is *always* marked so it never passes silently as a full\n * one. */\n critic_degraded?: boolean;\n /** Why the verdict degraded, set with `critic_degraded`. Additive. */\n degrade_cause?: DegradeCause;\n /** Output tokens per second over the model's own turns (tool execution and\n * retry backoff excluded), from fascicle's per-step timing. `basis` is\n * `decode` when every turn streamed, `blended` when any round trip counted\n * prefill and network too — always the case for `claude_cli`, whose rate\n * fascicle derives from the CLI's reported API time. Absent when no turn\n * carried timing. Additive.\n *\n * On Ollama, `decode` holds only while a turn's first chunk arrives as its\n * first token is generated. Ollama sends a tool call whole, so a turn whose\n * only output is a tool call dispatches nothing until generation ends, and\n * its tokens are divided by the last few milliseconds: a non-thinking seat's\n * rate reads far too high until robmclarty/fascicle#12 times those turns\n * another way. A thinking seat needs ai-sdk-ollama 4.3.0 or later, which\n * streams the reasoning even though volley never sets `think`. */\n throughput?: Throughput;\n};\n\nexport type HaltReason = 'cost_cap' | 'gate_edit' | null;\n\n/** Carry-state threaded through the fascicle loop. */\nexport type LoopState = {\n iteration: number;\n iteration_started_at: string;\n feedback: string | null;\n verdict: Verdict | null;\n unmet_criteria: string[];\n check: CheckResult | null;\n /** What the builder changed this iteration, measured against the run's\n * baseline (`src/changes.ts`). Null when the build root is not a git\n * repository, and before the first `build` step of a run. */\n changes: ChangeSet | null;\n builder: PhaseRecord | null;\n critic: PhaseRecord | null;\n total_usage: UsageTotals;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n check_duration_ms: number;\n /** How many of the run's builder sessions ended on the step limit\n * (`max_steps`) rather than calling finish. */\n builder_max_steps_hits: number;\n iteration_cost_usd: number;\n halt: HaltReason;\n cost_warned: boolean;\n};\n\nexport type RunInput = {\n resume_from: LoopState | null;\n};\n\n/** Projection of final loop state; the run's `summary.json` mirrors this. */\nexport type RunResult = {\n run_id: string;\n status: RunStatus;\n started_at: string;\n completed_at: string | null;\n iterations_completed: number;\n total_usage: UsageTotals;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n check_duration_ms: number;\n /** How many of the run's builder sessions hit the step limit before they\n * called finish: work handed to the check and critic unverified. The\n * warning a run prints for each goes to stderr, which `--json` silences, so\n * a harness reads it here. Always 0 for a `claude_cli` builder, which has\n * no step limit, and for a critique. */\n builder_max_steps_hits: number;\n final_verdict: Verdict | null;\n /** The run branch teardown left behind because this run's work was never\n * integrated: under `--worktree` without `--git` a converged run has no\n * other copy of its effects, so teardown commits them onto `volley/<run id>`\n * and keeps the branch instead of force-deleting it. Null whenever nothing\n * survived — every non-worktree run, every integrated run, every discarded\n * one. `--json` consumers read it here; the run's `summary.json` mirrors it. */\n salvaged_branch: string | null;\n /** A run, or a critique, which runs no builder. */\n mode: RunMode;\n /** Where this run keeps its config, summary, trajectory, feedback, verdict,\n * and iterations: `<state_dir>/<run_id>/` under a state root, else the\n * workspace's `.volley/`. Inside the sandbox container it is the container's\n * path, which a harness maps back to the directory it mounted. */\n run_state_dir: string;\n};\n\nexport type VolleyPhase = 'builder' | 'critic' | 'check';\n\n/** Recoverable domain failures surface as `kind`-tagged Error values (the\n * same discrimination style as fascicle's error taxonomy) so the top-level\n * handler maps them to exit codes without string matching or instanceof. */\nexport type ConfigError = Error & { kind: 'config_error' };\n\nexport type CheckError = Error & { kind: 'check_error' };\n\nexport type PhaseError = Error & {\n kind: 'phase_error';\n phase: VolleyPhase;\n iteration: number;\n cause: unknown;\n};\n\nexport function config_error(message: string): ConfigError {\n return Object.assign(new Error(message), { kind: 'config_error' as const });\n}\n\nexport function check_error(message: string): CheckError {\n return Object.assign(new Error(message), { kind: 'check_error' as const });\n}\n\n/** Wraps a provider/schema failure with the phase and iteration it hit. */\nexport function phase_error(\n phase: VolleyPhase,\n iteration: number,\n cause: unknown,\n): PhaseError {\n const detail = cause instanceof Error ? cause.message : String(cause);\n return Object.assign(\n new Error(`${phase} failed on iteration ${iteration}: ${detail}`),\n { kind: 'phase_error' as const, phase, iteration, cause },\n );\n}\n\nexport function error_kind(err: unknown): string | null {\n if (typeof err === 'object' && err !== null && 'kind' in err) {\n const kind = (err as { kind: unknown }).kind;\n return typeof kind === 'string' ? kind : null;\n }\n return null;\n}\n","/**\n * The ONLY module that calls fascicle's `create_engine`. Every\n * other module receives an `Engine`-shaped value, which keeps the engine\n * mockable in tests and confines provider knowledge to one seam.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { create_engine } from 'fascicle';\nimport type { Engine, ProviderConfigMap, PricingTable } from 'fascicle';\nimport { config_error } from './types.js';\nimport type { BuilderProvider, CriticProvider } from './types.js';\n\nexport type { Engine } from 'fascicle';\n\n/** LM Studio's OpenAI-compatible server and Ollama's server-root defaults.\n * The Ollama URL is the server root, NOT `…/api`: `ai-sdk-ollama` appends\n * `/api/...` itself, so a base URL ending in `/api` requests `/api/api/chat`\n * and 404s. */\nexport const DEFAULT_OLLAMA_URL = 'http://localhost:11434';\nexport const DEFAULT_LMSTUDIO_URL = 'http://localhost:1234/v1';\n/** OpenRouter's API root, the one fascicle's openrouter adapter defaults to. */\nexport const DEFAULT_OPENROUTER_URL = 'https://openrouter.ai/api/v1';\n\n/** The variable an `openrouter` seat's API key is read from. */\nconst OPENROUTER_KEY_VAR = 'OPENROUTER_API_KEY';\n\n/** The variable a `claude_cli` seat's API key is read from, which the Claude\n * CLI also reads on its own. */\nconst ANTHROPIC_KEY_VAR = 'ANTHROPIC_API_KEY';\n\n/** Every variable a seat reads a credential from. Every process volley starts\n * runs without them (the check, the builder's commands, and volley's own git\n * and checkride calls, which run hooks and filters the builder can write), so\n * nothing the builder writes can read the keys its seats spend. */\nexport const SEAT_CREDENTIAL_VARS: ReadonlyArray<string> = [OPENROUTER_KEY_VAR, ANTHROPIC_KEY_VAR];\n\n/** The environment every process volley starts runs with: `env`, `PATH`\n * included, less every variable a seat reads a credential from. */\nexport function command_env(env: Readonly<Record<string, string | undefined>>): Record<string, string> {\n const stripped: ReadonlySet<string> = new Set(SEAT_CREDENTIAL_VARS);\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => entry[1] !== undefined && !stripped.has(entry[0]),\n ),\n );\n}\n\n/** Loopback authorities the container→host crossing rewrites. A base URL\n * pointing at one of these is local to wherever volley runs; contained, that is\n * *inside* the sandbox container, where the host LLM daemon is unreachable\n * except across the boundary at `VOLLEY_MODEL_HOST`. `URL.hostname` keeps an\n * IPv6 literal's brackets, so the IPv6 loopback is spelled `[::1]`. */\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]', '0.0.0.0']);\n\n/** Cross a loopback base URL to the host LLM endpoint. When volley\n * runs inside its sandbox container the local model daemon is on the *host*, so\n * the example's `docker run` injects `VOLLEY_MODEL_HOST=host.docker.internal`\n * (the host-gateway allowlist target; see `sandbox_invocation` in\n * `src/sandbox.ts`). This normalizer *consumes that override* and swaps a\n * loopback host for the gateway, so an unchanged `http://localhost:11434` still\n * reaches the host from in-container. A non-loopback URL (a real remote daemon)\n * is left untouched, and an unset `VOLLEY_MODEL_HOST` (the host / unsandboxed\n * path) is a no-op — so the default and all-Claude paths are unaffected. */\nexport function cross_to_host_gateway(\n base_url: string,\n env: Record<string, string | undefined>,\n): string {\n const host = env['VOLLEY_MODEL_HOST'];\n if (host === undefined || host === '') return base_url;\n let parsed: URL;\n try {\n parsed = new URL(base_url);\n } catch {\n return base_url;\n }\n if (!LOOPBACK_HOSTS.has(parsed.hostname.toLowerCase())) return base_url;\n parsed.hostname = host;\n // `URL` re-serializes `http://host:port` with a trailing `/`; drop it so the\n // Ollama server-root shape (no path) is preserved, while a real path (LM\n // Studio's `/v1`) is left intact.\n return parsed.toString().replace(/\\/$/, '');\n}\n\n/** The providers a seat reaches at a base URL volley configures. `claude_cli`\n * picks its own endpoint, so it never appears here. */\ntype UrlProvider = 'ollama' | 'lmstudio' | 'openrouter';\n\n/** Where a URL-taking provider's base URL comes from when a seat names none of\n * its own: the provider's env var, then its default. `normalize` canonicalizes\n * a URL from any source, so two spellings of one server compare equal. */\ntype SeatUrlSource = {\n env: string;\n default_url: string;\n normalize: (url: string) => string;\n};\n\nfunction strip_trailing_slashes(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n\nconst SEAT_URL_SOURCES: Readonly<Record<UrlProvider, SeatUrlSource>> = {\n // A trailing `/api` (the pre-v0.3.1 documented default, and a natural mistake\n // since Ollama's REST paths all start with it) is stripped rather than left\n // to 404 every request.\n ollama: {\n env: 'VOLLEY_OLLAMA_URL',\n default_url: DEFAULT_OLLAMA_URL,\n normalize: (url) => strip_trailing_slashes(url).replace(/\\/api$/, ''),\n },\n // LM Studio's base URL keeps its `/v1`: the OpenAI-compatible client appends\n // `/chat/completions` to it.\n lmstudio: {\n env: 'VOLLEY_LMSTUDIO_URL',\n default_url: DEFAULT_LMSTUDIO_URL,\n normalize: strip_trailing_slashes,\n },\n // OpenRouter's base URL keeps its `/api/v1` the same way, so a seat URL can\n // name a proxy or another OpenAI-compatible gateway.\n openrouter: {\n env: 'VOLLEY_OPENROUTER_URL',\n default_url: DEFAULT_OPENROUTER_URL,\n normalize: strip_trailing_slashes,\n },\n};\n\n/** The providers that take a seat URL (`--builder-url` / `--critic-url`), and\n * so get their endpoint probed by `--dry-run`. */\nexport const SEAT_URL_PROVIDERS = Object.keys(SEAT_URL_SOURCES) as ReadonlyArray<UrlProvider>;\n\n/** Whether a seat on `provider` reaches its model at a base URL volley\n * configures, and so takes a URL of its own. */\nexport function takes_seat_url(\n provider: BuilderProvider | CriticProvider | undefined,\n): provider is UrlProvider {\n return (SEAT_URL_PROVIDERS as ReadonlyArray<string | undefined>).includes(provider);\n}\n\n/** An absent, empty, or all-whitespace value counts as unset. */\nfunction present(value: string | null | undefined): string | null {\n const trimmed = value?.trim() ?? '';\n return trimmed === '' ? null : trimmed;\n}\n\n/** The base URL a seat's model calls go to: the seat's own URL, else the\n * provider's env var (`VOLLEY_OLLAMA_URL` / `VOLLEY_LMSTUDIO_URL` /\n * `VOLLEY_OPENROUTER_URL`), else its default. A seat never falls back to the\n * other seat's URL. The result is normalized, then a loopback authority is\n * crossed to the host LLM endpoint when volley runs contained. Both seats can\n * be loopback URLs on different ports, and each crosses on its own port. */\nexport function seat_base_url(\n provider: UrlProvider,\n seat_url: string | null,\n env: Record<string, string | undefined>,\n): string {\n const source = SEAT_URL_SOURCES[provider];\n const raw = present(seat_url) ?? present(env[source.env]) ?? source.default_url;\n return cross_to_host_gateway(source.normalize(raw), env);\n}\n\n/** The API key an `openrouter` seat sends, from `OPENROUTER_API_KEY`. An unset\n * or blank key is a config error naming the variable, which `resolve_config`\n * raises before any work, because fascicle's own \"requires a non-empty\n * api_key\" doesn't say where the key comes from. */\nexport function openrouter_api_key(env: Record<string, string | undefined>): string {\n const key = present(env[OPENROUTER_KEY_VAR]);\n if (key === null) {\n throw config_error(\n `${OPENROUTER_KEY_VAR} is not set: an openrouter seat sends it as its API key`,\n );\n }\n return key;\n}\n\nfunction load_pricing_overrides(path: string): PricingTable {\n if (!existsSync(path)) {\n throw config_error(`VOLLEY_PRICING_PATH not found: ${path}`);\n }\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as PricingTable;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw config_error(`VOLLEY_PRICING_PATH is not valid JSON: ${detail}`);\n }\n}\n\nexport type EngineOptions = {\n /** The Claude session's working directory. A run passes its build root, which\n * is the worktree under `--worktree`, so the builder writes where the check\n * and the critic look. */\n workspace: string;\n /** When the builder runs on a URL-taking provider, that provider is\n * configured alongside claude_cli so one engine drives both roles. */\n builder_provider?: BuilderProvider;\n /** The builder seat's own base URL (`--builder-url`); null or absent falls\n * back to the provider's env var, then its default. */\n builder_url?: string | null;\n /** When the critic runs on a URL-taking provider, that provider is\n * configured alongside claude_cli so one engine drives both roles. */\n critic_provider?: CriticProvider;\n /** The critic seat's own base URL (`--critic-url`), resolved the same way. */\n critic_url?: string | null;\n env?: Record<string, string | undefined>;\n};\n\n/** A seat's provider entry, with the base URL resolved for that seat. The ai-sdk\n * peer (`ai-sdk-ollama` / `@ai-sdk/openai-compatible`) is loaded lazily by\n * fascicle only when the provider actually runs. The entry is complete, because\n * `Engine.with_providers` replaces a provider's whole entry: whatever this\n * returns is all a seat's derived engine knows about the provider, so an\n * `openrouter` entry carries its key and its transport along with its URL.\n *\n * `openrouter` runs on fascicle's native transport, its OpenAI-compatible core,\n * so no ai-sdk peer gets installed for it, and its `X-Title` attributes the\n * traffic to volley.\n *\n * For the local providers, native transport is the deferred future bridge, not\n * adopted here: they stay on the ai_sdk transport, which fascicle 0.14.0 already\n * selects by default (`transport?: 'ai_sdk' | 'native'` defaults to `'ai_sdk'`),\n * so no field is needed today. Flipping later is a one-line change — add\n * `transport: 'native'` to the ollama/lmstudio entry returned below, which both\n * seats' engines then share. No URL re-pointing is required: `seat_base_url`\n * already yields the daemon-root URL the native `/api/chat` transport wants\n * (its adapter appends `/api/chat` itself), which is exactly what the v0.3.1\n * base-URL fix produces.\n * Kept as a proven-once-then-reverted option so the transport stays a clean\n * second variable in the model-vs-transport comparison. Flipping it today would\n * also lose the reasoning: fascicle's native Ollama adapter drops\n * `message.thinking`, with `think` unset or true (robmclarty/fascicle#12), so a\n * thinking seat's reasoning would vanish from the terminal and the trajectory.\n *\n * Every provider's base URL crosses a loopback authority to `VOLLEY_MODEL_HOST`\n * when volley runs contained, so an in-container model client reaches the\n * host LLM endpoint at `host.docker.internal`; on the host / unsandboxed path the\n * override is unset and this is a no-op. */\nfunction seat_provider_config(\n provider: UrlProvider,\n seat_url: string | null,\n env: Record<string, string | undefined>,\n): ProviderConfigMap {\n const base_url = seat_base_url(provider, seat_url, env);\n switch (provider) {\n case 'ollama':\n return { ollama: { base_url } };\n case 'lmstudio':\n return { lmstudio: { base_url } };\n case 'openrouter':\n return {\n openrouter: {\n api_key: openrouter_api_key(env),\n base_url,\n transport: 'native',\n x_title: 'volley',\n },\n };\n }\n}\n\n/** Per-run engine. `claude_cli` is always configured with `options.workspace`\n * (the run's build root) as its session cwd; any URL-taking provider selected\n * by the builder or critic role is wired in alongside it, at that seat's URL,\n * so one engine drives both roles. An engine holds one URL per provider, so on\n * a provider both seats share it carries the builder's; `create_seat_engines`\n * gives the critic its own engine when its URL differs. Binary, auth mode,\n * fallback provider URLs, and pricing come from the environment. */\nexport function create_volley_engine(options: EngineOptions): Engine {\n const env = options.env ?? process.env;\n\n const auth_mode = env['VOLLEY_AUTH_MODE'] ?? 'auto';\n if (auth_mode !== 'auto' && auth_mode !== 'oauth' && auth_mode !== 'api_key') {\n throw config_error(\n `VOLLEY_AUTH_MODE must be auto, oauth, or api_key; got: ${auth_mode}`,\n );\n }\n\n const binary = env['VOLLEY_CLAUDE_BIN'];\n const pricing_path = env['VOLLEY_PRICING_PATH'];\n\n const providers: ProviderConfigMap = {\n claude_cli: {\n default_cwd: options.workspace,\n setting_sources: ['project', 'local'],\n auth_mode,\n ...(binary !== undefined && binary.length > 0 ? { binary } : {}),\n ...(auth_mode === 'api_key' && env[ANTHROPIC_KEY_VAR] !== undefined\n ? { api_key: env[ANTHROPIC_KEY_VAR] }\n : {}),\n },\n };\n // A run may select a URL-taking provider for the builder, the critic, or both\n // (even two different ones). The critic's goes in first, so a critic-only\n // engine (the dry-run canary's) gets the critic's URL, and on a provider both\n // seats share, the builder's URL wins.\n if (takes_seat_url(options.critic_provider)) {\n Object.assign(\n providers,\n seat_provider_config(options.critic_provider, options.critic_url ?? null, env),\n );\n }\n if (takes_seat_url(options.builder_provider)) {\n Object.assign(\n providers,\n seat_provider_config(options.builder_provider, options.builder_url ?? null, env),\n );\n }\n\n return create_engine({\n providers,\n ...(pricing_path !== undefined && pricing_path.length > 0\n ? { pricing: load_pricing_overrides(pricing_path) }\n : {}),\n });\n}\n\n/** The engine each seat's model calls go through. */\nexport type SeatEngines = { builder: Engine; critic: Engine };\n\n/** One engine per seat, shared unless it can't be. fascicle fixes one base URL\n * per provider when it builds an engine, so two seats on the same provider at\n * different URLs need two engines: the critic's is derived from the builder's\n * with `with_providers`, which keeps claude_cli, auth, and pricing and\n * overrides only the shared provider's entry. Every other pairing, including a\n * run that sets no seat URL at all, gets the one engine a run has always had. */\nexport async function create_seat_engines(options: EngineOptions): Promise<SeatEngines> {\n const env = options.env ?? process.env;\n const builder = create_volley_engine(options);\n const provider = options.critic_provider;\n if (\n provider !== options.builder_provider ||\n !takes_seat_url(provider) ||\n seat_base_url(provider, options.builder_url ?? null, env) ===\n seat_base_url(provider, options.critic_url ?? null, env)\n ) {\n return { builder, critic: builder };\n }\n try {\n const critic = builder.with_providers(\n seat_provider_config(provider, options.critic_url ?? null, env),\n );\n return { builder, critic };\n } catch (err) {\n // Nothing has run on the builder's engine yet; release it, not leak it.\n await builder.dispose();\n throw err;\n }\n}\n\n/** Dispose each distinct seat engine once. Both disposals start together, so\n * one that fails doesn't keep the other from running. */\nexport async function dispose_seat_engines(engines: SeatEngines): Promise<void> {\n const distinct =\n engines.critic === engines.builder ? [engines.builder] : [engines.builder, engines.critic];\n await Promise.all(distinct.map((engine) => engine.dispose()));\n}\n","/**\n * Shared workspace tools: `contain()` path confinement plus the read-only\n * tool set (`read_file`, `search_files`, `list_files`).\n *\n * The claude_cli builder/critic get file access from the CLI's own built-in\n * tools. API-style providers (ollama, lmstudio, …) have no built-ins, so\n * volley supplies its own. The critic uses the read-only set as-is via\n * `src/critic/tools.ts`; the builder set in\n * `src/builder/tools.ts` reuses `contain()` and the read tools and adds its\n * write/exec surface. Every path is resolved and confined to the\n * workspace root.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { z } from 'zod';\nimport type { Tool } from 'fascicle';\n\nexport const READ_FILE_MAX_BYTES = 200_000;\nexport const SEARCH_MAX_MATCHES = 200;\nconst LIST_MAX_ENTRIES = 2000;\n\n/** Directories never worth handing a seat; they bury signal and blow the\n * traversal budget. The acp seats' `list_files` and `search` skip the same\n * names (`./acp_tools.ts`), so a seat sees one tree under acp and on the CLI. */\nexport const IGNORED_DIRS: ReadonlySet<string> = new Set([\n 'node_modules',\n '.git',\n '.volley',\n '.check',\n 'dist',\n '.cache',\n]);\n\n/** Which tool set a seat holds, so its prompt names the tools it has: volley's\n * own (`'volley'`), or fascicle's workspace tools under `volley acp`\n * (`'acp'`). */\nexport type ToolSet = 'volley' | 'acp';\n\n/** Resolve `rel` inside `workspace`, rejecting absolute paths and any `..`\n * escape. Returns the absolute path; throws on containment violation. The\n * `workspace` root passed here is the build root, which is the per-run git\n * worktree under `--worktree` (`build_root`), not necessarily the\n * workspace the run was started on. */\nexport function contain(workspace: string, rel: string): string {\n const root = resolve(workspace);\n const candidate = isAbsolute(rel) ? resolve(rel) : resolve(root, rel);\n const within = candidate === root || candidate.startsWith(`${root}${sep}`);\n if (!within) {\n throw new Error(`path escapes the workspace: ${rel}`);\n }\n return candidate;\n}\n\ntype WalkEntry = { rel: string; abs: string };\n\nfunction walk(root: string, start: string, limit: number): WalkEntry[] {\n const out: WalkEntry[] = [];\n const stack = [start];\n while (stack.length > 0 && out.length < limit) {\n const dir = stack.pop() as string;\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n continue;\n }\n for (const name of entries) {\n const abs = join(dir, name);\n let is_dir: boolean;\n try {\n is_dir = statSync(abs).isDirectory();\n } catch {\n continue;\n }\n if (is_dir) {\n if (!IGNORED_DIRS.has(name)) stack.push(abs);\n continue;\n }\n out.push({ rel: relative(root, abs), abs });\n if (out.length >= limit) break;\n }\n }\n return out;\n}\n\n/** The files a read tool's optional `path` covers: the whole tree, the tree\n * under a directory, or the one file it names. A path that doesn't exist\n * throws, so the seat reads why rather than an empty result that looks like\n * \"nothing matched\". */\nfunction scoped_files(workspace: string, path: string | undefined, limit: number): WalkEntry[] {\n const root = resolve(workspace);\n if (path === undefined) return walk(root, root, limit);\n const start = contain(workspace, path);\n let is_dir: boolean;\n try {\n is_dir = statSync(start).isDirectory();\n } catch (err) {\n throw new Error(`no such file or directory: ${path}`, { cause: err });\n }\n return is_dir ? walk(root, start, limit) : [{ rel: relative(root, start), abs: start }];\n}\n\nfunction build_regex(pattern: string, flags: string): RegExp {\n try {\n return new RegExp(pattern, flags);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`invalid regular expression: ${detail}`);\n }\n}\n\nconst read_file_input = z.object({\n path: z.string().describe('Workspace-relative path to the file to read.'),\n});\n\nconst search_files_input = z.object({\n pattern: z.string().describe('JavaScript regular expression to match against each line.'),\n path: z\n .string()\n .optional()\n .describe('Optional workspace-relative directory or file to limit the search to.'),\n ignore_case: z.boolean().optional().describe('Case-insensitive match. Default false.'),\n});\n\nconst list_files_input = z.object({\n path: z\n .string()\n .optional()\n .describe('Optional workspace-relative directory or file. Default: the workspace root.'),\n contains: z\n .string()\n .optional()\n .describe('Optional substring filter applied to each relative path.'),\n});\n\n// Each is `read_only`, so a builder's per-turn call cap doesn't count it: a\n// read changes nothing a later call in the turn could depend on.\n//\n// Each tool is typed as fascicle's `Tool` (input `unknown`) and re-parses the\n// model's raw arguments with its own schema. fascicle's `Tool` is invariant\n// on the input type, so typed-per-tool values will not widen into `Tool[]`;\n// parsing inside `execute` keeps the wiring cast-free and validates arguments\n// at the boundary. The declared `input_schema` still drives the JSON schema\n// the model sees.\nexport function read_only_tools(workspace: string): Tool[] {\n const read_file: Tool = {\n name: 'read_file',\n read_only: true,\n description:\n 'Read a UTF-8 text file from the workspace. Returns the file content ' +\n `(truncated at ${String(READ_FILE_MAX_BYTES)} bytes).`,\n input_schema: read_file_input,\n execute: (raw) => {\n const input = read_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const content = readFileSync(abs, 'utf8');\n return content.length > READ_FILE_MAX_BYTES\n ? `${content.slice(0, READ_FILE_MAX_BYTES)}\\n… [truncated at ${String(READ_FILE_MAX_BYTES)} bytes]`\n : content;\n },\n };\n\n const search_files: Tool = {\n name: 'search_files',\n read_only: true,\n description:\n 'Search workspace files for lines matching a regular expression. Returns ' +\n `up to ${String(SEARCH_MAX_MATCHES)} \"relative/path:line: text\" hits.`,\n input_schema: search_files_input,\n execute: (raw) => {\n const input = search_files_input.parse(raw);\n const regex = build_regex(input.pattern, input.ignore_case === true ? 'i' : '');\n const files = scoped_files(workspace, input.path, LIST_MAX_ENTRIES);\n const hits: string[] = [];\n for (const file of files) {\n if (hits.length >= SEARCH_MAX_MATCHES) break;\n let content: string;\n try {\n content = readFileSync(file.abs, 'utf8');\n } catch {\n continue;\n }\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i += 1) {\n if (hits.length >= SEARCH_MAX_MATCHES) break;\n const line = lines[i] as string;\n if (regex.test(line)) hits.push(`${file.rel}:${String(i + 1)}: ${line.trim()}`);\n }\n }\n if (hits.length === 0) return 'no matches';\n const capped =\n hits.length >= SEARCH_MAX_MATCHES ? `\\n… [capped at ${String(SEARCH_MAX_MATCHES)} matches]` : '';\n return `${hits.join('\\n')}${capped}`;\n },\n };\n\n const list_files: Tool = {\n name: 'list_files',\n read_only: true,\n description:\n 'List files under a workspace directory (recursively; skips node_modules, ' +\n '.git, and other build/output directories).',\n input_schema: list_files_input,\n execute: (raw) => {\n const input = list_files_input.parse(raw);\n let files = scoped_files(workspace, input.path, LIST_MAX_ENTRIES).map((f) => f.rel);\n if (input.contains !== undefined) {\n const needle = input.contains;\n files = files.filter((f) => f.includes(needle));\n }\n if (files.length === 0) return 'no files';\n const capped =\n files.length >= LIST_MAX_ENTRIES ? `\\n… [capped at ${String(LIST_MAX_ENTRIES)} entries]` : '';\n return `${files.join('\\n')}${capped}`;\n },\n };\n\n return [read_file, search_files, list_files];\n}\n\n/** A `paths + sizes` listing of the workspace tree, no file contents — the\n * grounding a tool-less critic gets when its provider's tool parser died and the\n * degradation ladder traded read access for survival. Reuses the same\n * `walk` + `IGNORED_DIRS` traversal as the read tools, so the inventory matches\n * what a working `list_files` would have surfaced; caps at `limit` entries. */\nexport function workspace_inventory(root: string, limit: number = LIST_MAX_ENTRIES): string {\n const base = resolve(root);\n const files = walk(base, base, limit);\n if (files.length === 0) return 'no files';\n const lines = files.map((file) => {\n let size: number;\n try {\n size = statSync(file.abs).size;\n } catch {\n size = 0;\n }\n return `${file.rel} (${String(size)} bytes)`;\n });\n const capped =\n files.length >= limit ? `\\n… [capped at ${String(limit)} entries]` : '';\n return `${lines.join('\\n')}${capped}`;\n}\n","/**\n * Builder tool set for local (non-CLI) builders.\n *\n * A local model brings no built-in tools, so volley supplies the whole\n * agentic surface: the shared read-only trio (reused from\n * `src/workspace_tools.ts`) plus `write_file`, `edit_file`, `bash`,\n * `fetch`, and the terminal `finish`. File paths are confined to the\n * workspace via `contain()`.\n *\n * Error semantics: a wrong-but-recoverable input — `edit_file`\n * matching 0 or N places, a `bash` command exiting non-zero or timing out, a\n * `fetch` that is SSRF-blocked or fails — is *returned* as a tool result the\n * model reads and acts on. Tools throw only on a genuine harness fault\n * (containment violation, unreadable input, over-cap write).\n *\n * `fetch` is a native readability pipeline (`linkedom` + `@mozilla/\n * readability` + `turndown`) with SSRF protection at the undici connector, not\n * as a pre-flight URL check: a validating DNS `lookup` rejects hostnames that\n * resolve to a non-unicast address before the TCP connect, and the resolved\n * socket's peer address is re-checked after connect — which also catches\n * literal-IP URLs (Node skips `lookup` for those) and every redirect hop\n * (each re-dispatches through the same guarded connector). The byte cap is\n * enforced while reading the HTTP stream, so raw HTML is never returned and a\n * huge page cannot OOM the tool.\n *\n * Egress is defended in two independent layers: this tool's SSRF\n * deny-list (above) and the sandbox's container network posture (`--network none`\n * by default, or a host-collapsed allowlist bridge — see `SandboxNetwork` in\n * `src/sandbox.ts`). Under whole-process containment the whole volley\n * process — `fetch` included — runs inside the container, so both layers apply to\n * `fetch`'s egress: `--network none` leaves it no route and it returns a \"could\n * not fetch\" error result, and the loop continues.\n */\nimport { spawnSync } from 'node:child_process';\nimport { lookup as dns_lookup } from 'node:dns';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { LookupFunction } from 'node:net';\nimport { dirname } from 'node:path';\nimport { Readability } from '@mozilla/readability';\nimport ipaddr from 'ipaddr.js';\nimport { parseHTML } from 'linkedom';\nimport TurndownService from 'turndown';\nimport { Agent, buildConnector, interceptors, request } from 'undici';\nimport { z } from 'zod';\nimport type { Tool, ToolExecContext } from 'fascicle';\nimport { command_env } from '../engine.js';\nimport { contain, read_only_tools } from '../workspace_tools.js';\n\nexport const WRITE_FILE_MAX_BYTES = 1_000_000;\n\n// Sized to fit a workspace `pnpm check`: volley's own checkride timeout is\n// 600s, so a shorter budget would kill the builder's self-verify\n// mid-run. Overridable per call site via `BuilderToolOptions` (tests use a\n// short value so the timeout path is exercised without a 10-minute wait).\nexport const BASH_TIMEOUT_MS = 600_000;\n\n// Model-facing cap on each of stdout/stderr; oversize output is truncated\n// with a marker. Not a memory guard — `BASH_CAPTURE_MAX_BYTES`\n// below bounds what `spawnSync` buffers before we ever truncate.\nconst BASH_MAX_OUTPUT_BYTES = 100_000;\n\n// OOM backstop on `spawnSync`'s captured output, well above the display cap:\n// a command that floods gigabytes is bounded here, then truncated to the\n// display cap for the model.\nconst BASH_CAPTURE_MAX_BYTES = 10_000_000;\n\n// Hard cap on bytes read from the HTTP stream before conversion: a page\n// larger than this is truncated at the socket, so raw HTML never reaches the\n// model and a huge page cannot OOM the tool.\nconst FETCH_MAX_BYTES = 200_000;\n\n// Default page-size for the model-facing markdown slice; `start_index`\n// paginates through the rest (MCP fetch-server contract).\nconst FETCH_MAX_CHARS = 5000;\n\n// How many redirect hops to follow. Each hop re-dispatches through the same\n// SSRF-guarded connector, so a redirect into a private range is still refused.\nconst FETCH_MAX_REDIRECTS = 5;\n\n// Per-request timeout (headers and body idle), in ms.\nconst FETCH_TIMEOUT_MS = 30_000;\n\n// Below this, readability's extraction is treated as a miss (empty article /\n// JS-rendered SPA) and we fall back to converting the whole document body.\nconst FETCH_MIN_EXTRACT_CHARS = 200;\n\nconst FETCH_USER_AGENT = 'volley-local-builder';\n\n/** The raw outcome of running one bash command, before the model-facing\n * truncation + timeout marker the `bash` tool applies. `status` is the exit code\n * (null when the process was killed by a signal — e.g. the timeout SIGKILL);\n * `timed_out` marks the timeout path. */\nexport type BashOutcome = {\n status: number | null;\n stdout: string;\n stderr: string;\n timed_out: boolean;\n};\n\n/** How the `bash` tool runs a command: the local `host_bash_executor`\n * (`spawnSync`) — which under whole-process containment runs *inside*\n * volley's own hardened container, no `docker exec` hop. The executor runs one\n * command to completion and returns its raw outcome; the `bash` tool owns the\n * truncation + timeout marker. Kept as an injectable seam so tests can supply a\n * fake and a future shape could re-point it (the `docker exec` executor was\n * retired). */\nexport type BashExecutor = (\n command: string,\n options: { timeout_ms: number; max_capture_bytes: number },\n) => BashOutcome;\n\nexport type BuilderToolOptions = {\n /** Override `BASH_TIMEOUT_MS` (ms). */\n bash_timeout_ms?: number;\n /** Override `BASH_MAX_OUTPUT_BYTES` (bytes, per stream). */\n bash_max_output_bytes?: number;\n /**\n * Where `bash` runs a command. Defaults to `host_bash_executor` — the local\n * `spawnSync`, which under containment runs inside volley's own container against the\n * bind-mounted worktree. Injectable so tests can supply a fake (the\n * `docker exec` executor was retired).\n */\n bash_executor?: BashExecutor;\n /** Override `FETCH_MAX_BYTES` (bytes read from the HTTP stream before the cap). */\n fetch_max_bytes?: number;\n /**\n * Test seam: override the connection-time SSRF classifier. Production leaves\n * this unset and uses `is_forbidden_address`, which rejects every non-unicast\n * (private / loopback / link-local / CGNAT / …) address. Tests set it to reach\n * a loopback fixture server while still exercising the real rejection path.\n */\n fetch_is_address_forbidden?: (address: string) => boolean;\n /**\n * Test seam: override the DNS resolver the SSRF connector validates through.\n * Defaults to `node:dns` `lookup`. Lets a test point a hostname at a private\n * address to exercise the redirect-into-private-range rejection.\n */\n fetch_lookup?: LookupFunction;\n};\n\nconst write_file_input = z.object({\n path: z.string().describe('Workspace-relative path to write. Parent directories are created.'),\n content: z.string().describe('Full UTF-8 content of the file. Overwrites any existing content.'),\n});\n\nconst edit_file_input = z.object({\n path: z.string().describe('Workspace-relative path of the file to edit.'),\n old_str: z\n .string()\n .min(1)\n .describe('Exact text to replace. Must occur exactly once in the file.'),\n new_str: z.string().describe('Replacement text.'),\n});\n\nconst bash_input = z.object({\n command: z.string().describe('Shell command to run in the workspace directory.'),\n});\n\nconst finish_input = z.object({\n summary: z.string().describe('Short summary of what was accomplished.'),\n});\n\nconst fetch_input = z.object({\n url: z.string().describe('Absolute http(s) URL to fetch.'),\n max_chars: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`Maximum characters of extracted markdown to return (default ${String(FETCH_MAX_CHARS)}).`),\n start_index: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe('Character offset into the extracted markdown to start from, for paging a long page. Default 0.'),\n});\n\nfunction count_occurrences(haystack: string, needle: string): number {\n return haystack.split(needle).length - 1;\n}\n\n/** Truncate `text` to at most `max` bytes, appending a marker when clipped.\n * Byte-based to honor the byte cap; a split multibyte char at the boundary\n * renders as the replacement char, which is acceptable for tool output. */\nfunction truncate_bytes(text: string, max: number): string {\n if (Buffer.byteLength(text, 'utf8') <= max) return text;\n const clipped = Buffer.from(text, 'utf8').subarray(0, max).toString('utf8');\n return `${clipped}\\n… [truncated at ${String(max)} bytes]`;\n}\n\n/**\n * Non-unicast → forbidden. Rejects loopback, private, link-local,\n * unspecified, broadcast, multicast, CGNAT, and the IPv6 equivalents; an\n * IPv4-mapped IPv6 address is folded to its v4 form first so `::ffff:127.0.0.1`\n * is caught as loopback (and `::ffff:<public>` is still allowed). An\n * unparseable address fails closed.\n */\nexport function is_forbidden_address(address: string): boolean {\n let parsed;\n try {\n parsed = ipaddr.parse(address);\n } catch {\n return true;\n }\n const canonical =\n 'isIPv4MappedAddress' in parsed && parsed.isIPv4MappedAddress() ? parsed.toIPv4Address() : parsed;\n return canonical.range() !== 'unicast';\n}\n\n// Default DNS resolver the SSRF connector validates through; the `fetch_lookup`\n// option swaps it in tests.\nconst default_resolver: LookupFunction = (hostname, options, callback) => {\n dns_lookup(hostname, options, callback);\n};\n\n// A `lookup` that resolves normally, then rejects the connection if any\n// resolved address is forbidden — closing the DNS-rebinding / redirect-hop gap\n// a pre-flight URL check leaves open. Runs before the TCP connect, so a\n// hostname pointing at a private range never opens a socket.\nfunction guarded_lookup(is_forbidden: (address: string) => boolean, resolve: LookupFunction): LookupFunction {\n return (hostname, options, callback) => {\n resolve(hostname, options, (err, address, family) => {\n if (err !== null) {\n callback(err, '', 0);\n return;\n }\n const resolved = Array.isArray(address) ? address.map((entry) => entry.address) : [address];\n const blocked = resolved.find((entry) => is_forbidden(entry));\n if (blocked !== undefined) {\n callback(ssrf_error(blocked, hostname), '', 0);\n return;\n }\n callback(null, address, family);\n });\n };\n}\n\nfunction ssrf_error(address: string, hostname: string): NodeJS.ErrnoException {\n const err: NodeJS.ErrnoException = new Error(\n `blocked non-unicast address ${address} for host \"${hostname}\"`,\n );\n err.code = 'ERR_SSRF_BLOCKED';\n return err;\n}\n\n// An undici Agent whose connector validates SSRF at two points: the `lookup`\n// above (hostnames, before connect) and the peer address of the established\n// socket (which also catches literal-IP URLs — Node skips `lookup` for those —\n// and every redirect hop, since each re-dispatches through this connector).\nfunction create_ssrf_agent(is_forbidden: (address: string) => boolean, resolve: LookupFunction): Agent {\n const base = buildConnector({ lookup: guarded_lookup(is_forbidden, resolve), timeout: FETCH_TIMEOUT_MS });\n const connector: typeof base = (options, callback) => {\n base(options, (err, socket) => {\n if (err !== null) {\n callback(err, null);\n return;\n }\n if (socket === null) {\n callback(new Error('connection produced no socket'), null);\n return;\n }\n const remote = socket.remoteAddress;\n if (remote !== undefined && is_forbidden(remote)) {\n socket.destroy();\n callback(ssrf_error(remote, options.hostname), null);\n return;\n }\n callback(null, socket);\n });\n };\n return new Agent({ connect: connector, headersTimeout: FETCH_TIMEOUT_MS, bodyTimeout: FETCH_TIMEOUT_MS });\n}\n\n// Read the response body, stopping at `max_bytes` so raw HTML never fully\n// buffers. Breaking the `for await` destroys the stream, ending the\n// download.\nasync function read_body_capped(body: AsyncIterable<Buffer>, max_bytes: number): Promise<Buffer> {\n const chunks: Buffer[] = [];\n let total = 0;\n for await (const chunk of body) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n const remaining = max_bytes - total;\n if (buf.length >= remaining) {\n chunks.push(buf.subarray(0, remaining));\n break;\n }\n chunks.push(buf);\n total += buf.length;\n }\n return Buffer.concat(chunks);\n}\n\nfunction header_value(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value[0] ?? '';\n return value ?? '';\n}\n\nfunction content_kind(content_type: string, body: string): 'html' | 'text' | 'binary' {\n const ct = content_type.toLowerCase();\n if (ct.includes('html') || ct.includes('xml')) return 'html';\n if (\n ct.startsWith('text/') ||\n ct.includes('json') ||\n ct.includes('javascript') ||\n ct.includes('csv')\n ) {\n return 'text';\n }\n if (ct === '') return body.trimStart().startsWith('<') ? 'html' : 'text';\n return 'binary';\n}\n\n// Extract the main content as markdown: readability over a linkedom DOM, then\n// turndown. Falls back to converting the whole document when readability finds\n// little (empty article / JS-rendered SPA). Never returns raw HTML.\nfunction extract_markdown(html: string): string {\n const turndown = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' });\n turndown.remove(['script', 'style', 'noscript']);\n let body_markdown = '';\n let title = '';\n try {\n const { document } = parseHTML(html);\n const article = new Readability(document).parse();\n if (article !== null) {\n title = (article.title ?? '').trim();\n if (article.content) {\n body_markdown = turndown.turndown(article.content).trim();\n }\n }\n } catch {\n body_markdown = '';\n }\n if (body_markdown.length < FETCH_MIN_EXTRACT_CHARS) {\n let fallback = '';\n try {\n fallback = turndown.turndown(html).trim();\n } catch {\n fallback = '';\n }\n if (fallback.length > body_markdown.length) body_markdown = fallback;\n }\n const prefix = title.length > 0 && !body_markdown.startsWith(`# ${title}`) ? `# ${title}\\n\\n` : '';\n return `${prefix}${body_markdown}`.trim();\n}\n\n// MCP fetch-server pagination: return the `max_chars` slice at `start_index`,\n// and when more remains, a self-describing trailer naming the next start_index.\nfunction paginate(full: string, max_chars: number, start_index: number): string {\n if (start_index >= full.length) {\n return `(no more content: start_index ${String(start_index)} is at or past the end of the ${String(full.length)}-character document)`;\n }\n const slice = full.slice(start_index, start_index + max_chars);\n const next = start_index + slice.length;\n if (next >= full.length) return slice;\n const remaining = full.length - next;\n return `${slice}\\n\\n<truncated: ${String(remaining)} more characters. Call fetch again with start_index=${String(next)} to continue.>`;\n}\n\n// Flatten an error (and its `cause` chain) into a single line for the model.\nfunction error_detail(err: unknown): string {\n const parts: string[] = [];\n const seen = new Set<unknown>();\n let current: unknown = err;\n while (current !== undefined && current !== null && !seen.has(current)) {\n seen.add(current);\n if (current instanceof Error) {\n const code = (current as NodeJS.ErrnoException).code;\n parts.push(code !== undefined ? `${current.message} [${code}]` : current.message);\n current = (current as { cause?: unknown }).cause;\n } else {\n // Thrown values are Errors in practice; a non-Error is defensive only, so\n // keep a string as-is and never risk an \"[object Object]\" stringification.\n parts.push(typeof current === 'string' ? current : `non-error value (${typeof current})`);\n break;\n }\n }\n return parts.length > 0 ? parts.join(' <- ') : 'unknown error';\n}\n\ntype FetchConfig = {\n is_forbidden: (address: string) => boolean;\n resolve: LookupFunction;\n max_bytes: number;\n};\n\nasync function run_fetch(raw: unknown, ctx: ToolExecContext, config: FetchConfig): Promise<string> {\n const input = fetch_input.parse(raw);\n const max_chars = input.max_chars ?? FETCH_MAX_CHARS;\n const start_index = input.start_index ?? 0;\n\n let target: URL;\n try {\n target = new URL(input.url);\n } catch {\n return `error: not a valid absolute URL: ${input.url}`;\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') {\n return `error: unsupported URL scheme \"${target.protocol}\" — only http and https are fetched`;\n }\n\n const agent = create_ssrf_agent(config.is_forbidden, config.resolve);\n const dispatcher = agent.compose(interceptors.redirect({ maxRedirections: FETCH_MAX_REDIRECTS }));\n try {\n const res = await request(target.href, {\n dispatcher,\n signal: ctx.abort,\n headersTimeout: FETCH_TIMEOUT_MS,\n bodyTimeout: FETCH_TIMEOUT_MS,\n headers: {\n 'user-agent': FETCH_USER_AGENT,\n accept: 'text/html,application/xhtml+xml,text/plain;q=0.9,*/*;q=0.8',\n // No compression: keep the pipeline simple and the byte cap honest.\n 'accept-encoding': 'identity',\n },\n });\n if (res.statusCode >= 400) {\n await res.body.dump();\n return `error: HTTP ${String(res.statusCode)} fetching ${target.href}`;\n }\n const bytes = await read_body_capped(res.body, config.max_bytes);\n const content_type = header_value(res.headers['content-type']);\n const text = bytes.toString('utf8');\n if (text.trim().length === 0) {\n return `error: empty response body from ${target.href}`;\n }\n const kind = content_kind(content_type, text);\n if (kind === 'binary') {\n return `error: cannot extract non-text content (content-type: ${content_type}) from ${target.href}`;\n }\n const markdown = kind === 'html' ? extract_markdown(text) : text.trim();\n if (markdown.length === 0) {\n return `error: no readable content extracted from ${target.href}`;\n }\n return paginate(markdown, max_chars, start_index);\n } catch (err) {\n return `error: could not fetch ${target.href}: ${error_detail(err)}`;\n } finally {\n await agent.close().catch(() => undefined);\n }\n}\n\n/**\n * The `bash` executor: run the command via `spawnSync` with a shell, bounded by\n * the timeout (SIGKILL on expiry) and the OOM capture cap. Under whole-process\n * containment this runs *inside* volley's hardened container against the\n * bind-mounted worktree — the container is the isolation boundary, no\n * `docker exec` hop — and it is likewise the executor on the\n * `--allow-unsandboxed-builder` host escape hatch. A command runs with\n * volley's environment less the seats' keys, so nothing the builder runs can\n * read the key its seat spends. `status` is null when a signal (the timeout\n * SIGKILL) killed the process.\n */\nfunction host_bash_executor(cwd: string): BashExecutor {\n return (command, options) => {\n const result = spawnSync(command, {\n shell: true,\n cwd,\n env: command_env(process.env),\n encoding: 'utf8',\n timeout: options.timeout_ms,\n killSignal: 'SIGKILL',\n maxBuffer: options.max_capture_bytes,\n });\n return {\n status: result.status,\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n timed_out: (result.error as NodeJS.ErrnoException | undefined)?.code === 'ETIMEDOUT',\n };\n };\n}\n\n// Same wiring convention as the shared read tools: each tool is typed as\n// fascicle's `Tool` (input `unknown`) and re-parses the model's raw\n// arguments with its own schema inside `execute`.\nexport function builder_tools(workspace: string, options: BuilderToolOptions = {}): Tool[] {\n const bash_timeout_ms = options.bash_timeout_ms ?? BASH_TIMEOUT_MS;\n const bash_max_output_bytes = options.bash_max_output_bytes ?? BASH_MAX_OUTPUT_BYTES;\n const bash_executor = options.bash_executor ?? host_bash_executor(workspace);\n\n const write_file: Tool = {\n name: 'write_file',\n description:\n 'Write a UTF-8 text file in the workspace, creating parent directories ' +\n 'and overwriting any existing content. Rejects content over ' +\n `${String(WRITE_FILE_MAX_BYTES)} bytes.`,\n input_schema: write_file_input,\n execute: (raw) => {\n const input = write_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const bytes = Buffer.byteLength(input.content, 'utf8');\n if (bytes > WRITE_FILE_MAX_BYTES) {\n throw new Error(\n `content is ${String(bytes)} bytes, over the ${String(WRITE_FILE_MAX_BYTES)}-byte write cap`,\n );\n }\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, input.content, 'utf8');\n return `wrote ${String(bytes)} bytes to ${input.path}`;\n },\n };\n\n const edit_file: Tool = {\n name: 'edit_file',\n description:\n 'Replace one exact occurrence of old_str with new_str in a workspace ' +\n 'file. old_str must match the file content exactly once — on 0 or ' +\n 'multiple matches nothing is changed and an error is returned; read ' +\n 'the file and retry with a longer, unique old_str.',\n input_schema: edit_file_input,\n execute: (raw) => {\n const input = edit_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const content = readFileSync(abs, 'utf8');\n const matches = count_occurrences(content, input.old_str);\n if (matches === 0) {\n return (\n `error: old_str not found in ${input.path} (0 matches). ` +\n 'No change made. Read the file and retry with an exact excerpt of its current content.'\n );\n }\n if (matches > 1) {\n return (\n `error: old_str matches ${String(matches)} times in ${input.path}. ` +\n 'No change made. Include more surrounding context to make old_str unique.'\n );\n }\n writeFileSync(abs, content.replace(input.old_str, input.new_str), 'utf8');\n return `edit applied to ${input.path}`;\n },\n };\n\n const bash: Tool = {\n name: 'bash',\n description:\n 'Run a shell command in the workspace and return its exit code, stdout, ' +\n 'and stderr. Each call is independent — no shell state (working ' +\n 'directory, environment, variables) carries over between commands. A ' +\n 'non-zero exit is a normal result, not an error: read it and adjust. ' +\n `Each stream is truncated past ${String(bash_max_output_bytes)} bytes, ` +\n `and the command is killed if it runs longer than ${String(bash_timeout_ms)}ms.`,\n input_schema: bash_input,\n // Stateless per command (the executor is injectable without touching\n // this contract — under containment it is the local `spawnSync` running in-container),\n // and never throws on the command's own failure — a non-zero exit or a\n // timeout is *returned* as `{ exit_code, stdout, stderr }` for the model to\n // read. The executor buffers up to `BASH_CAPTURE_MAX_BYTES` (OOM guard)\n // before we truncate to the model-facing cap.\n execute: (raw) => {\n const input = bash_input.parse(raw);\n const outcome = bash_executor(input.command, {\n timeout_ms: bash_timeout_ms,\n max_capture_bytes: BASH_CAPTURE_MAX_BYTES,\n });\n let stderr = truncate_bytes(outcome.stderr, bash_max_output_bytes);\n if (outcome.timed_out) {\n const note = `[command timed out after ${String(bash_timeout_ms)}ms and was killed]`;\n stderr = stderr.length > 0 ? `${stderr}\\n${note}` : note;\n }\n // `status` is the numeric exit code, or null when the process was killed\n // by a signal (e.g. the timeout SIGKILL).\n return {\n exit_code: outcome.status,\n stdout: truncate_bytes(outcome.stdout, bash_max_output_bytes),\n stderr,\n };\n },\n };\n\n const fetch: Tool = {\n name: 'fetch',\n description:\n 'Fetch an http(s) URL and return its main content converted to Markdown. ' +\n `Returns at most max_chars characters (default ${String(FETCH_MAX_CHARS)}); ` +\n 'when the page is longer, a trailer names the start_index to pass to read ' +\n 'the next slice. Private, loopback, and link-local addresses are refused. ' +\n 'A blocked, non-HTML, or failed request returns an error string you can read and act on.',\n input_schema: fetch_input,\n // Native readability pipeline with connection-time SSRF protection; a\n // blocked / non-HTML / HTTP error is returned as a tool result, not\n // thrown. The classifier and resolver are overridable for tests only.\n execute: (raw, ctx) =>\n run_fetch(raw, ctx, {\n is_forbidden: options.fetch_is_address_forbidden ?? is_forbidden_address,\n resolve: options.fetch_lookup ?? default_resolver,\n max_bytes: options.fetch_max_bytes ?? FETCH_MAX_BYTES,\n }),\n };\n\n return [...read_only_tools(workspace), write_file, edit_file, bash, fetch, finish_tool()];\n}\n\n/** The terminal `finish` tool, on its own for a builder set that brings its\n * own file and command tools (`../acp_tools.ts`). */\nexport function finish_tool(): Tool {\n return {\n name: 'finish',\n description:\n 'Declare the task complete. Calling this tool ends your turn — do not ' +\n 'call it until the work is done and verified.',\n input_schema: finish_input,\n // A successful `finish` ends the loop deterministically. The summary\n // is recorded in the trajectory like any tool call and otherwise ignored\n // — the workspace, not the self-report, is truth.\n ends_turn: true,\n execute: (raw) => {\n const input = finish_input.parse(raw);\n return `finished: ${input.summary}`;\n },\n };\n}\n","/**\n * checkride runner: spawn `pnpm exec checkride --json --digest`, gate on the\n * `.check/summary.json` contract (`schema_version: 1`), and collect raw\n * failing-slot artifacts for the critic — the critic reads what the tool\n * actually said, not a normalized digest. The digest checkride writes on a red\n * run is kept beside them for the next builder, which needs a short list of\n * what to fix more than the whole of every slot's output.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { isAbsolute, join, relative, sep } from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport { aborted_error } from 'fascicle';\nimport { command_env } from '../engine.js';\nimport { check_error } from '../types.js';\nimport type { CheckArtifact, CheckResult } from '../types.js';\n\nexport const CHECK_ARTIFACT_MAX_CHARS = 8000;\n\nconst CHECKRIDE_SCHEMA_VERSION = 1;\n\nexport type CheckrideSummaryCheck = {\n name: string;\n adapter: string | null;\n ok: boolean;\n skipped?: boolean;\n exit_code: number | null;\n duration_ms: number;\n output_file: string | null;\n};\n\nexport type CheckrideSummary = {\n schema_version: number;\n ok: boolean;\n total_duration_ms: number;\n checks: CheckrideSummaryCheck[];\n};\n\nexport type SpawnCaptureResult = {\n exit_code: number | null;\n stdout: string;\n stderr: string;\n};\n\n/** How long a check's output may stay open after its shell exits, while\n * something that escaped its process group still holds it, before the reads\n * stop so the check can finish. */\nconst OUTPUT_GRACE_MS = 2000;\n\n/** Kill a check's whole process group with SIGKILL. A test runner's workers,\n * and anything the check started in the background, sit in the shell's group,\n * so killing the shell alone would leave them running. Windows has no process\n * groups to signal, so there only the shell goes. */\nfunction kill_group(proc: ChildProcess): void {\n if (proc.pid === undefined) return;\n try {\n if (process.platform === 'win32') proc.kill('SIGKILL');\n else process.kill(-proc.pid, 'SIGKILL');\n } catch {\n // The group is gone: every process in it has exited.\n }\n}\n\n/** What a check runs with beside its command. */\nexport type CheckSpawnOptions = {\n abort?: AbortSignal;\n /** The whole environment the check runs with, in place of volley's own;\n * nothing is merged in, so it carries the `PATH` the check needs. Absent,\n * the check gets volley's less the seats' keys. */\n env?: Readonly<Record<string, string>>;\n};\n\n/** Run a check to its end in a process group of its own, capturing its\n * output. The abort kills the whole group and rejects with `aborted_error`,\n * and the shell's exit kills whatever it left behind, so a stopped run leaves\n * no test workers or servers running. */\nexport function spawn_capture(\n cmd: string,\n args: string[],\n options: CheckSpawnOptions & { cwd: string },\n): Promise<SpawnCaptureResult> {\n const { abort } = options;\n if (abort?.aborted === true) return Promise.reject(new aborted_error('check aborted'));\n return new Promise((resolve_promise, reject) => {\n const proc = spawn(cmd, args, {\n cwd: options.cwd,\n env: options.env ?? command_env(process.env),\n detached: process.platform !== 'win32',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stdout = '';\n let stderr = '';\n let grace: NodeJS.Timeout | undefined;\n const on_abort = (): void => {\n kill_group(proc);\n reject(new aborted_error('check aborted'));\n };\n const finish = (): void => {\n clearTimeout(grace);\n abort?.removeEventListener('abort', on_abort);\n };\n proc.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n proc.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n proc.on('error', (err) => {\n finish();\n reject(check_error(`check command failed to start: ${err.message}`));\n });\n proc.on('exit', () => {\n kill_group(proc);\n grace = setTimeout(() => {\n proc.stdout.destroy();\n proc.stderr.destroy();\n }, OUTPUT_GRACE_MS);\n });\n proc.on('close', (code) => {\n finish();\n resolve_promise({ exit_code: code, stdout, stderr });\n });\n abort?.addEventListener('abort', on_abort, { once: true });\n });\n}\n\nexport type ParsedSummary = {\n summary: CheckrideSummary;\n warning: string | null;\n};\n\n/** Best-effort parse of the summary contract. `pnpm exec` talks over the\n * command's stdout (pnpm 11's dep-verify prints an \"Already up to date\"\n * install line ahead of the JSON), so the object is extracted between the\n * first `{` and the last `}` rather than parsed from byte 0. An unexpected\n * schema_version warns and still parses; no JSON object at all is a harness\n * error (exit 4). */\nexport function parse_checkride_summary(stdout: string): ParsedSummary {\n const start = stdout.indexOf('{');\n const end = stdout.lastIndexOf('}');\n let raw: unknown;\n try {\n if (start === -1 || end < start) throw new Error('no JSON object in stdout');\n raw = JSON.parse(stdout.slice(start, end + 1));\n } catch {\n throw check_error('checkride --json produced unparseable stdout');\n }\n if (typeof raw !== 'object' || raw === null || !Array.isArray((raw as CheckrideSummary).checks)) {\n throw check_error('checkride summary missing checks array');\n }\n const summary = raw as CheckrideSummary;\n const warning =\n summary.schema_version === CHECKRIDE_SCHEMA_VERSION\n ? null\n : `checkride summary schema_version ${String(summary.schema_version)} != ${String(CHECKRIDE_SCHEMA_VERSION)}; parsing best-effort`;\n return { summary, warning };\n}\n\n/** Parse the summary from stdout, falling back to the on-disk contract:\n * `.check/summary.json` is what checkride documents; stdout is its mirror and\n * wrappers may talk over it beyond what the tolerant slice can recover. */\nexport function parse_summary_with_fallback(stdout: string, workspace: string): ParsedSummary {\n try {\n return parse_checkride_summary(stdout);\n } catch (err) {\n const file = join(workspace, '.check', 'summary.json');\n if (!existsSync(file)) throw err;\n return parse_checkride_summary(readFileSync(file, 'utf8'));\n }\n}\n\nexport function failing_checks(summary: CheckrideSummary): CheckrideSummaryCheck[] {\n return summary.checks.filter((c) => !c.ok && c.skipped !== true);\n}\n\n/** Whether `path` sits under `dir`. */\nfunction within(dir: string, path: string): boolean {\n const from_dir = relative(dir, path);\n return from_dir !== '..' && !from_dir.startsWith(`..${sep}`) && !isAbsolute(from_dir);\n}\n\n/** Per failing slot: the raw artifact (`<output_file>` when present, else\n * `<slot>.stdout.txt`) in `check_dir`, a workspace's `.check/` or an archived\n * iteration's copy of it, truncated with a pointer to the file. The names come\n * from a summary the builder could have written, so a path that leaves\n * `check_dir` has no artifact, rather than putting a file from elsewhere in\n * front of a model. */\nexport function read_failing_artifacts(\n check_dir: string,\n failing: CheckrideSummaryCheck[],\n): CheckArtifact[] {\n return failing.map((check) => {\n const file = check.output_file ?? `${check.name}.stdout.txt`;\n const path = join(check_dir, file);\n if (!within(check_dir, path) || !existsSync(path) || !statSync(path).isFile()) {\n return { slot: check.name, path: null, content: '(no artifact found)', truncated: false };\n }\n const raw = readFileSync(path, 'utf8');\n const truncated = raw.length > CHECK_ARTIFACT_MAX_CHARS;\n return {\n slot: check.name,\n path,\n content: truncated ? raw.slice(0, CHECK_ARTIFACT_MAX_CHARS) : raw,\n truncated,\n };\n });\n}\n\n/** checkride's digest of a red run (`.check/digest.md`, written under\n * `--digest` and removed on a green one), or undefined when there is none. It\n * is capped by checkride itself, at 8 kB. */\nfunction read_digest(workspace: string): string | undefined {\n const path = join(workspace, '.check', 'digest.md');\n return existsSync(path) ? readFileSync(path, 'utf8') : undefined;\n}\n\nexport type CheckrideOpts = CheckSpawnOptions & {\n workspace: string;\n};\n\nexport async function run_checkride(opts: CheckrideOpts): Promise<CheckResult> {\n const { workspace, ...spawn_options } = opts;\n const proc = await spawn_capture('pnpm', ['exec', 'checkride', '--json', '--digest'], {\n ...spawn_options,\n cwd: workspace,\n });\n // checkride exit 2 is a harness/usage error — an operator problem, not\n // something to iterate on.\n if (proc.exit_code === 2) {\n throw check_error(`checkride harness error: ${proc.stderr.trim()}`);\n }\n const { summary } = parse_summary_with_fallback(proc.stdout, opts.workspace);\n const failing = failing_checks(summary);\n // Only a red run writes a digest; on a green one checkride removes any\n // stale one, and volley doesn't look.\n const digest = summary.ok ? undefined : read_digest(opts.workspace);\n return {\n ran: true,\n runner: 'checkride',\n ok: summary.ok,\n exit_code: proc.exit_code,\n duration_ms: summary.total_duration_ms,\n failing_slots: failing.map((c) => c.name),\n detail: read_failing_artifacts(join(opts.workspace, '.check'), failing),\n summary,\n ...(digest !== undefined ? { digest } : {}),\n };\n}\n","/**\n * Generic command runner: `sh -c <command>`, combined\n * output captured, exit-0 semantics. Command-not-found is an operator error\n * (exit 4), not an iterable failure.\n */\nimport { check_error } from '../types.js';\nimport type { CheckResult, CheckRunnerKind } from '../types.js';\nimport { spawn_capture } from './checkride.js';\nimport type { CheckSpawnOptions } from './checkride.js';\n\nexport type CommandCheckOpts = CheckSpawnOptions & {\n command: string;\n workspace: string;\n};\n\nexport async function run_command_check(opts: CommandCheckOpts): Promise<CheckResult> {\n const { command, workspace, ...spawn_options } = opts;\n const started = Date.now();\n const proc = await spawn_capture('sh', ['-c', command], { ...spawn_options, cwd: workspace });\n // sh reports 127 for command-not-found and 126 for not-executable.\n if (proc.exit_code === 127 || proc.exit_code === 126) {\n throw check_error(\n `check command failed to start (exit ${String(proc.exit_code)}): ${command}`,\n );\n }\n const log = `${proc.stdout}${proc.stderr}`;\n return {\n ran: true,\n runner: 'command',\n ok: proc.exit_code === 0,\n exit_code: proc.exit_code,\n duration_ms: Date.now() - started,\n failing_slots: [],\n detail: [],\n log,\n };\n}\n\nexport function skipped_check(reason: 'none' | 'cost_cap'): CheckResult {\n return {\n ran: false,\n runner: 'none',\n // With no check configured the loop is critic-gated only, so the gate is\n // open (`ok: true`). A cost-cap skip must not look like a passing gate.\n ok: reason === 'none',\n exit_code: null,\n duration_ms: 0,\n failing_slots: [],\n detail: [],\n };\n}\n\n/** What a rejected check says in place of its output. */\nexport const CHECK_REJECTED = 'the check was rejected when it asked to run, so it never ran';\n\n/** A check the user rejected when it asked to run: recorded as a failed\n * check, with the refusal as its output, so a round can't converge on work\n * nothing checked, and the critic hears why there's no result. */\nexport function rejected_check(runner: CheckRunnerKind): CheckResult {\n return {\n ran: true,\n runner,\n ok: false,\n exit_code: null,\n duration_ms: 0,\n failing_slots: [],\n detail: [],\n log: CHECK_REJECTED,\n };\n}\n","/**\n * Cost and usage accumulation. All pricing knowledge lives in\n * fascicle; volley only folds `GenerateResult.usage` / `.cost` into loop\n * state and enforces the cap predicate in the guard.\n */\nimport { claude_cli_reported, throughput } from 'fascicle';\nimport type { GenerateResult, UsageTotals } from 'fascicle';\nimport type {\n CostSource,\n LoopState,\n PhaseRecord,\n ResolvedConfig,\n} from './types.js';\n\nexport const EMPTY_USAGE: UsageTotals = { input_tokens: 0, output_tokens: 0 };\n\nexport function add_usage(a: UsageTotals, b: UsageTotals): UsageTotals {\n const sum: UsageTotals = {\n input_tokens: a.input_tokens + b.input_tokens,\n output_tokens: a.output_tokens + b.output_tokens,\n };\n const optional = ['cached_input_tokens', 'cache_write_tokens', 'reasoning_tokens'] as const;\n for (const key of optional) {\n const total = (a[key] ?? 0) + (b[key] ?? 0);\n if (a[key] !== undefined || b[key] !== undefined) sum[key] = total;\n }\n return sum;\n}\n\n/** The providers whose calls carry the charge they report, which fascicle\n * records as the call's cost in place of a pricing table's estimate: the\n * Claude CLI's own total, and OpenRouter's per-response charge. */\nconst REPORTING_PROVIDERS: ReadonlySet<string> = new Set(['claude_cli', 'openrouter']);\n\nexport function cost_source_of(result: GenerateResult<unknown>): CostSource {\n if (result.cost === undefined) return 'unknown';\n return REPORTING_PROVIDERS.has(result.model_resolved.provider)\n ? 'provider_reported'\n : 'engine_derived';\n}\n\n/** One phase's record from its generate result. The duration is fascicle's\n * call-level wall clock (`GenerateResult.timing`: every turn and the tools\n * between them) unless the caller measured a wider span, as the critic does for\n * its whole degradation ladder. */\nexport function phase_record(\n result: GenerateResult<unknown>,\n model: string,\n duration_ms: number = result.timing?.duration_ms ?? 0,\n): PhaseRecord {\n const rate = throughput(result);\n const truncated = result.steps.filter((step) => step.truncated === true).length;\n return {\n provider: result.model_resolved.provider,\n model,\n session_id: claude_cli_reported(result)?.session_id ?? null,\n duration_ms,\n usage: result.usage,\n cost_usd: result.cost?.total_usd ?? null,\n cost_source: cost_source_of(result),\n finish_reason: result.finish_reason,\n tool_calls: result.tool_calls.length,\n salvaged_tool_calls: result.tool_calls.filter((call) => call.salvaged === true).length,\n ...(truncated > 0 ? { truncated_turns: truncated } : {}),\n ...(rate !== undefined ? { throughput: rate } : {}),\n };\n}\n\n/** Fold one phase's result into the loop state. Unknown cost records `null`\n * for the phase and warns once per run — a run never fails over pricing. */\nexport function accumulate(\n state: LoopState,\n role: 'builder' | 'critic',\n result: GenerateResult<unknown>,\n model: string,\n duration_ms?: number,\n): LoopState {\n const record = phase_record(result, model, duration_ms);\n const cost = record.cost_usd ?? 0;\n return {\n ...state,\n [role]: record,\n total_usage: add_usage(state.total_usage, result.usage),\n total_cost_usd: state.total_cost_usd + cost,\n iteration_cost_usd: state.iteration_cost_usd + cost,\n builder_cost_usd: state.builder_cost_usd + (role === 'builder' ? cost : 0),\n critic_cost_usd: state.critic_cost_usd + (role === 'critic' ? cost : 0),\n cost_warned: state.cost_warned || record.cost_usd === null,\n };\n}\n\nexport function cost_cap_hit(config: ResolvedConfig, state: LoopState): boolean {\n return config.max_cost_usd !== null && state.total_cost_usd >= config.max_cost_usd;\n}\n","/**\n * Best-effort Ollama model pre-load. A cold multi-GB model can spend minutes\n * in load + first prompt eval — longer than the provider path's in-request\n * header timeout — so the first real `generate` dies with an opaque\n * `stream interrupted: fetch failed`. Ollama's documented load call (a\n * `/api/generate` POST with a model and no prompt) returns as soon as the\n * model is resident, so absorbing the load here keeps the real call's\n * time-to-first-byte inside its budget.\n *\n * Best-effort like the context probe: any failure (server down, unknown\n * model, timeout) is swallowed — the real generate call surfaces the error\n * with retry and reporting behind it. Ollama-only; LM Studio has no\n * equivalent load-without-generating endpoint.\n */\n\n/** Generous ceiling on the load itself: a disk-cold 30B-class model takes\n * tens of seconds to minutes. Past this, give up and let the real call try. */\nconst PREWARM_TIMEOUT_MS = 300_000;\n\n/** Load `model` into the Ollama server's memory (`base_url` is the server\n * root). Resolves when the model is resident, on any failure, or at the\n * timeout — never throws, never gates the phase. An already-resident model\n * returns immediately, so warming the same model for both roles is free.\n *\n * Load-bearing only on the ai_sdk transport: the cold-load death this\n * absorbs is the ai-sdk/undici in-request header timeout, not an Ollama\n * limit. On fascicle's native transport — the deferred future bridge, see\n * `seat_provider_config` in engine.ts — the per-turn call is a bare\n * `fetch(..., { signal })` with no default body timeout, so a cold model can\n * take as long as it needs and this pre-warm's necessity drops away (keep it\n * regardless: a resident model makes it a no-op). Native would also move the\n * `num_ctx`/`keep_alive` levers to per-call `provider_options.ollama`, rather\n * than the server-side Modelfile defaults volley probes today. */\nexport async function prewarm_ollama_model(\n base_url: string,\n model: string,\n abort?: AbortSignal,\n): Promise<void> {\n const signals = [AbortSignal.timeout(PREWARM_TIMEOUT_MS)];\n if (abort !== undefined) signals.push(abort);\n try {\n await fetch(`${base_url.replace(/\\/$/, '')}/api/generate`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ model }),\n signal: AbortSignal.any(signals),\n });\n } catch {\n // Best-effort: the real generate call owns error surfacing.\n }\n}\n","/**\n * Whether volley is running inside its sandbox container. A leaf, so the\n * config resolution, the preflight, and the run-config signing can all ask\n * without importing one another.\n */\n\n/** volley *detects* it is running inside its sandbox container rather than\n * starting the container itself. The signal is the `VOLLEY_CONTAINED=1` marker\n * volley's own image bakes in (`Dockerfile` `ENV`), so a `docker run <hardened\n * flags> <image> volley run …` is recognized as contained out of the box. Kept\n * env-only — no ambient `/.dockerenv` probe — so the safety gate is deterministic\n * and testable, and so a CI job that itself runs in an unrelated container does\n * not silently satisfy the gate; a hand-rolled sandbox must set the marker (or\n * the operator uses `--allow-unsandboxed-builder`). */\nexport function detect_containment(env: Readonly<Record<string, string | undefined>>): boolean {\n const value = env['VOLLEY_CONTAINED'];\n return value === '1' || value === 'true';\n}\n","/**\n * Which run configs a host-side resume may trust. A resume runs what a run's\n * `config.json` says: its check, a shell command, and its seats, permission\n * mode and prompt included. Inside the sandbox the builder runs arbitrary\n * commands with write access to its own run's state, so a contained run's\n * config is the builder's to rewrite, and resuming it on the host would run\n * whatever the builder left there.\n *\n * So volley on the host signs each config it writes, an HMAC under a key of\n * this machine's that never enters the container, and a host-side resume\n * trusts only a config whose signature holds. Inside the sandbox nothing is\n * signed, since the key isn't there and one made there would be in the\n * builder's reach, so a contained run's config never carries a signature the\n * host accepts, and the builder can't forge one without the key.\n */\nimport { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { detect_containment } from './containment.js';\n\ntype Env = Readonly<Record<string, string | undefined>>;\n\n/** Prefixed to what is signed, so a signature over a run config can't pass for\n * one over anything else under the same key. */\nconst DOMAIN = 'volley run config v1\\n';\n\n/** Where this machine's key lives: `$XDG_CONFIG_HOME/volley/run-key`, else\n * `~/.config/volley/run-key`, outside every state root, so a container a run\n * root is mounted into still can't read it. A relative `XDG_CONFIG_HOME` is\n * ignored, as the XDG spec says. */\nexport function trust_key_path(env: Env, home: string = homedir()): string {\n const xdg = env['XDG_CONFIG_HOME'];\n const base = xdg !== undefined && isAbsolute(xdg) ? xdg : join(home, '.config');\n return join(base, 'volley', 'run-key');\n}\n\nfunction error_code(err: unknown): unknown {\n return (err as { code?: unknown }).code;\n}\n\n/** The key as stored, or null when there is none or it isn't one. */\nfunction read_key(path: string): Buffer | null {\n try {\n const hex = readFileSync(path, 'utf8').trim();\n return /^[0-9a-f]{64}$/.test(hex) ? Buffer.from(hex, 'hex') : null;\n } catch {\n return null;\n }\n}\n\n/** The key, created on first use: 32 random bytes in a file only its user can\n * read, in a directory only its user can enter. Two runs that start together\n * race to create it; the loser reads the winner's. */\nfunction machine_key(env: Env): Buffer | null {\n const path = trust_key_path(env);\n const existing = read_key(path);\n if (existing !== null) return existing;\n try {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n writeFileSync(path, `${randomBytes(32).toString('hex')}\\n`, { flag: 'wx', mode: 0o600 });\n } catch (err) {\n if (error_code(err) !== 'EEXIST') return null;\n }\n return read_key(path);\n}\n\nfunction hmac(key: Buffer, config_text: string): string {\n return createHmac('sha256', key).update(DOMAIN).update(config_text).digest('hex');\n}\n\n/** This machine's signature over a run's `config.json` text, or null where\n * there's none to give: inside the sandbox, or when the key can't be read or\n * created. */\nexport function sign_config(config_text: string, env: Env = process.env): string | null {\n if (detect_containment(env)) return null;\n const key = machine_key(env);\n return key === null ? null : hmac(key, config_text);\n}\n\n/** Does `signature` hold for `config_text` under this machine's key? Never\n * creates the key: with none there's nothing it could hold under. */\nexport function config_signed(\n config_text: string,\n signature: string | null,\n env: Env = process.env,\n): boolean {\n if (signature === null) return false;\n const key = read_key(trust_key_path(env));\n if (key === null) return false;\n const expected = Buffer.from(hmac(key, config_text), 'hex');\n const given = Buffer.from(signature.trim(), 'hex');\n return given.length === expected.length && timingSafeEqual(given, expected);\n}\n","/**\n * Workspace lifecycle: run-state initialization, stale-run\n * backup rotation, path helpers, and optional git checkpoints.\n */\nimport { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { sign_config } from './trust.js';\nimport { check_error, config_error } from './types.js';\nimport type { ResolvedConfig } from './types.js';\n\n/** A run id names the run's `volley/<run id>` branch and its state directory,\n * so it is held to what both take without quoting: letters, digits, `-`, and\n * `_`, starting with a letter or digit, so it never reads as an option and\n * never climbs out of the directory it names. */\nexport const RUN_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;\n\n/** The root each run's state sits under when `--state-dir` names none:\n * `$XDG_STATE_HOME/volley`, else `<home>/.local/state/volley`. A relative\n * `XDG_STATE_HOME` is ignored, as the XDG spec says. `home` is the host's by\n * default; the sandbox passes its container's to spell the same root inside. */\nexport function default_state_root(\n env: Readonly<Record<string, string | undefined>>,\n home: string = homedir(),\n): string {\n const xdg = env['XDG_STATE_HOME'];\n const base = xdg !== undefined && isAbsolute(xdg) ? xdg : join(home, '.local', 'state');\n return join(base, 'volley');\n}\n\n/** What locates a run's state, as a structural subset of `ResolvedConfig` so a\n * resume can find a run before it has a whole config. */\nexport type StateLocation = Pick<ResolvedConfig, 'workspace' | 'state_dir' | 'run_id'>;\n\n/** Where a run keeps its config, summary, trajectory, feedback, verdict, and\n * iterations: `<state_dir>/<run_id>/` under its state root, or, in the layout\n * older runs used (`state_dir` null), `<workspace>/.volley/`. */\nexport function run_state_dir(run: StateLocation): string {\n return run.state_dir === null ? join(run.workspace, '.volley') : join(run.state_dir, run.run_id);\n}\n\nexport function state_path(run: StateLocation, ...parts: string[]): string {\n return join(run_state_dir(run), ...parts);\n}\n\nexport function iteration_dir(run: StateLocation, iteration: number): string {\n return state_path(run, 'iterations', String(iteration).padStart(3, '0'));\n}\n\n/** A state root that sits inside `root` (the build root), as the path from\n * there in git's `/`-separated vocabulary, or null when it sits outside. A\n * root inside the tree would otherwise pass for the builder's work: listed in\n * the changes the critic reads, and committed by every `--git` checkpoint.\n * The legacy `.volley/` (`state_dir` null) is excluded by name already. */\nexport function state_root_within(root: string, state_dir: string | null): string | null {\n if (state_dir === null) return null;\n const path = relative(resolve(root), resolve(state_dir));\n if (path === '' || path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path)) return null;\n return path.split(sep).join('/');\n}\n\n/** Filesystem-safe timestamp for `.bak.<stamp>` rotation names. Shared by the\n * run-state rotation here and the worktree rotation so both preserve\n * prior state under the same never-destroy naming. */\nexport function backup_stamp(date: Date = new Date()): string {\n return date.toISOString().replace(/[:.]/g, '-');\n}\n\n/** Fresh-run initialization: rotate a stale state directory aside (a prior\n * `.volley/` becomes `.volley.bak.<stamp>`), then create the directory tree.\n * Under a state root each run has a directory of its own, so only a reused\n * `--run-id` ever finds one to rotate. An empty one is used as it is: that is\n * what a contained run is handed when its run directory is the mount, which\n * can't be renamed. Resume runs skip rotation (`preserve: true`). */\nexport function initialize_run_state(\n run: StateLocation,\n options: { preserve?: boolean } = {},\n): void {\n const dir = run_state_dir(run);\n if (existsSync(dir) && options.preserve !== true && readdirSync(dir).length > 0) {\n renameSync(dir, `${dir}.bak.${backup_stamp()}`);\n }\n if (run.state_dir !== null && !existsSync(run.state_dir)) {\n // Trajectories hold prompts and tool output, so a root volley creates is\n // its user's alone, as the XDG spec asks of a state directory.\n mkdirSync(run.state_dir, { recursive: true, mode: 0o700 });\n }\n mkdirSync(join(dir, 'iterations'), { recursive: true });\n}\n\n/** Beside a run's `config.json`: this machine's signature over it\n * (`./trust.ts`), which a host-side resume checks before it trusts the\n * config. */\nexport const CONFIG_SIGNATURE = 'config.sig';\n\n/** Record the run's config, signed when volley runs on the host. Returns\n * whether it was signed: inside the sandbox it never is, and on the host only\n * when the machine's key can't be read or created. A signature a reused run\n * directory held from before is removed rather than left to vouch for this\n * config. */\nexport function write_resolved_config(\n config: ResolvedConfig,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): boolean {\n const record = {\n version: config.version,\n run_id: config.run_id,\n started_at: config.started_at,\n mode: config.mode,\n prompt: config.prompt,\n criteria: config.criteria,\n check: config.check,\n check_resolved: config.check_resolved,\n builder_model: config.builder_model,\n builder_provider: config.builder_provider,\n builder_url: config.builder_url,\n builder_max_steps: config.builder_max_steps,\n builder_max_tool_calls: config.builder_max_tool_calls,\n builder_max_output_tokens: config.builder_max_output_tokens,\n critic_model: config.critic_model,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n builder_permission_mode: config.builder_permission_mode,\n critic_preset: config.critic_preset,\n critic_prompt_path: config.critic_prompt_path,\n max_iterations: config.max_iterations,\n max_cost_usd: config.max_cost_usd,\n git_checkpoints: config.git_checkpoints,\n worktree: config.worktree,\n discard_worktree: config.discard_worktree,\n gate_paths: config.gate_paths,\n fail_on_gate_edit: config.fail_on_gate_edit,\n sandbox_image: config.sandbox_image,\n state_dir: config.state_dir,\n workspace: config.workspace,\n };\n const text = `${JSON.stringify(record, null, 2)}\\n`;\n writeFileSync(state_path(config, 'config.json'), text);\n const signature = sign_config(text, env);\n if (signature === null) {\n rmSync(state_path(config, CONFIG_SIGNATURE), { force: true });\n return false;\n }\n writeFileSync(state_path(config, CONFIG_SIGNATURE), `${signature}\\n`);\n return true;\n}\n\n/** The identity volley's own commits fall back to. git won't commit without a\n * name and an email, and the sandbox image carries no git config, so inside\n * it a checkpoint or a worktree's salvage commit failed outright; a machine\n * never set up for git can be the same. `.invalid` is reserved, so the email\n * can't reach anyone. */\nconst FALLBACK_IDENTITY: ReadonlyArray<readonly [string, string]> = [\n ['user.name', 'volley'],\n ['user.email', 'volley@volley.invalid'],\n];\n\n/** The `-c` flags that give a commit in `cwd` the fallback identity for each\n * part git has no value for. One the repo or the user configured wins, and so\n * does a `GIT_AUTHOR_*` or `GIT_COMMITTER_*` variable, which git ranks above\n * any config. Put them ahead of the subcommand. */\nexport function commit_identity(cwd: string): string[] {\n return FALLBACK_IDENTITY.flatMap(([key, value]) => {\n const set = spawnSync('git', ['config', '--get', key], {\n cwd,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n return set.status === 0 && set.stdout.trim() !== '' ? [] : ['-c', `${key}=${value}`];\n });\n}\n\n/**\n * `--git`: commit everything under `root` after a phase (`git -C <root>`, run\n * here via the spawn `cwd`). `root` is the build root (`build_root`): the\n * workspace on the default path, or the per-run worktree under `--worktree`, so\n * checkpoints land on the worktree branch rather than the workspace's.\n * A checkpoint with nothing to commit is fine; a missing git binary or repo is\n * not. `excluded_dir` (from `state_root_within`) keeps a state root inside the\n * tree out of the commit; `:/` keeps the rest of the staging repo-wide, as a\n * bare `git add -A` is, and `literal` reads the path as written, wildcards and\n * all.\n */\nexport function git_checkpoint(root: string, message: string, excluded_dir: string | null = null): void {\n if (!existsSync(join(root, '.git'))) {\n // `.git` is a directory in the workspace and a file in a linked worktree;\n // existsSync accepts both.\n throw config_error(`git checkpoints require a git repository: ${root}`);\n }\n const pathspec = excluded_dir === null ? [] : ['--', ':/', `:(exclude,literal)${excluded_dir}`];\n const add = spawnSync('git', ['add', '-A', ...pathspec], { cwd: root, env: command_env(process.env) });\n if (add.error !== undefined || add.status !== 0) {\n throw check_error(`git add failed: ${add.stderr?.toString() ?? String(add.error)}`);\n }\n const commit = spawnSync('git', [...commit_identity(root), 'commit', '-m', message, '--no-verify'], {\n cwd: root,\n env: command_env(process.env),\n });\n // Exit 1 with \"nothing to commit\" is a no-op iteration, not a failure. So is\n // \"nothing added to commit\", which git says instead when the only untracked\n // files left are the state root `excluded_dir` kept out.\n if (commit.error !== undefined) {\n throw check_error(`git commit failed to start: ${String(commit.error)}`);\n }\n const out = `${commit.stdout?.toString() ?? ''}${commit.stderr?.toString() ?? ''}`;\n if (commit.status !== 0 && !/nothing (?:added )?to commit/.test(out)) {\n throw check_error(`git commit failed: ${out.trim()}`);\n }\n}\n\n/**\n * Integration — bring a successful `--worktree --git` run's effects onto the\n * workspace branch. The per-phase checkpoints on `branch` are the raw\n * audit/replay trail; here they collapse into a single squash commit\n * (`git merge --squash` then `commit`) on the workspace's current branch. The\n * shared object store makes this a local, fetch-free merge, and — because the\n * workspace branch never moved during the run (checkpoints went to the phase\n * branch) — it is conflict-free by construction. A run whose phase branch has no\n * new commits integrates to a no-op. Only successful runs integrate; an\n * abandoned run's branch is discarded wholesale by the teardown trio instead.\n */\nexport function integrate_worktree(workspace: string, branch: string, message: string): void {\n if (!existsSync(join(workspace, '.git'))) {\n throw config_error(`--worktree integration requires a git repository: ${workspace}`);\n }\n const squash = spawnSync('git', ['merge', '--squash', branch], {\n cwd: workspace,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (squash.error !== undefined) {\n throw check_error(`git merge --squash failed to start: ${String(squash.error)}`);\n }\n if (squash.status !== 0) {\n throw check_error(\n `git merge --squash ${branch} failed: ${(squash.stderr || squash.stdout).trim()}`,\n );\n }\n const commit = spawnSync('git', [...commit_identity(workspace), 'commit', '-m', message, '--no-verify'], {\n cwd: workspace,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (commit.error !== undefined) {\n throw check_error(`git commit failed to start: ${String(commit.error)}`);\n }\n // An empty phase branch stages nothing; \"nothing to commit\" is a no-op.\n const out = `${commit.stdout ?? ''}${commit.stderr ?? ''}`;\n if (commit.status !== 0 && !out.includes('nothing to commit')) {\n throw check_error(`git commit failed: ${out.trim()}`);\n }\n}\n","/**\n * Git-worktree orchestration: isolate a builder run's\n * *effects* on a per-run branch checked out into a sibling worktree, then tear\n * the whole thing down when the run ends. The worktree lifecycle wraps the\n * fascicle loop — it is not itself a loop — so these are straight-line git\n * subprocess calls and the flow's no-loops rule is unaffected.\n *\n * Teardown is not one behaviour but three, decided by `worktree_fate` and\n * predicted out loud by `report_worktree_fate` before any model spend: a\n * converged `--worktree --git` run *integrates* (the orchestrator squash-merges,\n * then the branch is discarded), a `--discard-worktree` run *discards*, and a\n * plain `--worktree` run *salvages* — its work was never integrated and lives\n * nowhere else, so teardown commits it onto the run branch and keeps the branch\n * instead of force-deleting the build. Everything that did not converge still\n * discards wholesale.\n */\nimport { existsSync, renameSync, rmSync, symlinkSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { check_error, config_error } from './types.js';\nimport { backup_stamp, commit_identity } from './workspace.js';\n\n/** A live worktree: the checked-out path and the branch it holds. */\nexport type WorktreeHandle = {\n path: string;\n branch: string;\n};\n\n/** The sibling directory a run's worktree is checked out into — one per\n * workspace, alongside it so it never nests inside the repo's own tree. */\nexport function worktree_path(workspace: string): string {\n return `${resolve(workspace)}.worktree`;\n}\n\n/** The per-run branch name (one named branch per phase). Derived from the\n * run id so it is stable across a resume. */\nexport function worktree_branch(run_id: string): string {\n return `volley/${run_id}`;\n}\n\n/**\n * The directory the builder's *effects* land in: the run's worktree\n * when `--worktree` is on, else the workspace itself. This is the containment\n * root the builder/critic file tools resolve through `contain()` and the\n * `bash` tool's cwd — re-pointing it moves writes into the worktree without\n * disturbing the workspace. The check, the change report, and the checkpoints\n * follow it there; the run's state stays wherever `state_dir` puts it.\n */\nexport function build_root(workspace: string, worktree: boolean): string {\n return worktree ? worktree_path(workspace) : workspace;\n}\n\n/** What becomes of a *successful* `--worktree` run's effects. Any other\n * outcome — cost cap, budget, interrupt, error — always discards: an abandoned\n * phase's branch is thrown away wholesale, as it always has been. */\nexport type WorktreeFate = 'none' | 'integrate' | 'salvage' | 'discard';\n\n/** The config fields the fate turns on, as a structural subset of\n * `ResolvedConfig` so the decision is testable without a whole config. */\nexport type WorktreeFateConfig = {\n worktree: boolean;\n git_checkpoints: boolean;\n discard_worktree: boolean;\n};\n\n/**\n * Which of the three outcomes a converged run gets:\n *\n * - `integrate` — `--worktree --git`: the phase branch's checkpoints squash-merge\n * onto the workspace branch (`integrate_worktree`), then teardown discards it.\n * - `discard` — `--discard-worktree`: the effects go away with the branch. What\n * `volley matrix` sweeps with: isolate the effects, keep only verdicts.\n * - `salvage` — `--worktree` alone: nothing integrates, and the worktree holds the\n * run's only copy of its work, so teardown commits that onto the run branch and\n * keeps it rather than force-deleting a green run's build.\n *\n * `--git` wins over `--discard-worktree`, so the documented `--worktree --git`\n * integrate path is untouched by asking for a throw-away run.\n */\nexport function worktree_fate(config: WorktreeFateConfig): WorktreeFate {\n if (!config.worktree) return 'none';\n if (config.git_checkpoints) return 'integrate';\n if (config.discard_worktree) return 'discard';\n return 'salvage';\n}\n\n/** The run branch as a *prediction* can name it: `--dry-run` resolves its own\n * run id, which is not the id the real run will get, so the notice names the\n * pattern and the post-run report names the branch. */\nconst RUN_BRANCH_PATTERN = 'volley/<run id>';\n\nexport type WorktreeNotice = { level: 'info' | 'warn'; message: string };\n\n/**\n * What this run will do with its effects, in one line, said before any model\n * spend — the same predict-at-dry-run/warn-at-run-start shape as the local-critic\n * seat canary and the `num_ctx` guard. `salvage` is a warning, not an\n * info line: `--worktree` without `--git` integrates nothing, and it is the one\n * fate an operator is likely to have configured by accident.\n */\nexport function worktree_notice(config: WorktreeFateConfig): WorktreeNotice | null {\n const fate = worktree_fate(config);\n if (fate === 'none') return null;\n if (fate === 'integrate') {\n return {\n level: 'info',\n message:\n 'worktree: --worktree --git — a successful run squash-merges its run branch onto the ' +\n 'workspace branch at teardown; any other outcome is discarded.',\n };\n }\n if (fate === 'discard') {\n return {\n level: 'info',\n message:\n 'worktree: --discard-worktree — the run builds in an isolated worktree whose effects are ' +\n 'thrown away at teardown, converged or not. Verdicts only; no branch is kept.',\n };\n }\n return {\n level: 'warn',\n message:\n 'worktree: --worktree without --git — a successful run will NOT be integrated into the ' +\n 'workspace branch, and the builder writes only inside the sibling worktree, so your working ' +\n `tree stays as it is. The run's work is committed onto its own branch (${RUN_BRANCH_PATTERN}) ` +\n 'at teardown and left there for `git switch` / `git cherry-pick`. Add --git to squash-merge ' +\n 'it onto the workspace branch instead, or --discard-worktree to throw it away deliberately.',\n };\n}\n\n/** The renderer channels a notice writes through — structurally satisfied by\n * `Renderer`, so this module stays independent of the render layer. */\nexport type NoticeSink = {\n info: (message: string) => void;\n warn: (message: string) => void;\n};\n\n/** Emit the run's worktree fate on the channel its severity deserves (nothing at\n * all when `--worktree` is off). Called from the `--dry-run` preflight and again\n * at run start, so the outcome is predicted whether or not the operator dry-ran. */\nexport function report_worktree_fate(config: WorktreeFateConfig, sink: NoticeSink): void {\n const notice = worktree_notice(config);\n if (notice === null) return;\n if (notice.level === 'warn') {\n sink.warn(notice.message);\n return;\n }\n sink.info(notice.message);\n}\n\ntype GitResult = { status: number; stdout: string; stderr: string };\n\n/** Run git in `cwd`. A missing git binary is a precondition failure (like the\n * missing-repo guard); a non-zero exit is left to the caller to interpret. */\nfunction git(cwd: string, args: string[]): GitResult {\n const result = spawnSync('git', args, { cwd, env: command_env(process.env), encoding: 'utf8' });\n if (result.error !== undefined) {\n throw config_error(`git is required for --worktree but could not run: ${String(result.error)}`);\n }\n return { status: result.status ?? -1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };\n}\n\n/** Run git and throw on a non-zero exit, surfacing git's own diagnostics. */\nfunction git_ok(cwd: string, args: string[]): GitResult {\n const result = git(cwd, args);\n if (result.status !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim();\n throw check_error(`git ${args.join(' ')} failed: ${detail}`);\n }\n return result;\n}\n\n/** Best-effort git for teardown: swallows both spawn and exit failures so the\n * idempotent trio never throws out of a run's `finally`. Still reports what it\n * can — a spawn failure reads as a non-zero exit with no output — so the salvage\n * path can interrogate the repo without reintroducing a throw. */\nfunction git_quiet(cwd: string, args: string[]): GitResult {\n try {\n const result = spawnSync('git', args, { cwd, env: command_env(process.env), encoding: 'utf8' });\n return { status: result.status ?? -1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };\n } catch {\n // Teardown is cleanup; never mask the run's real outcome.\n return { status: -1, stdout: '', stderr: '' };\n }\n}\n\nfunction branch_exists(repo: string, branch: string): boolean {\n return git(repo, ['show-ref', '--verify', '--quiet', `refs/heads/${branch}`]).status === 0;\n}\n\n/**\n * Check `branch` out into a fresh worktree at `worktree_path(workspace)`.\n *\n * Rotate-on-conflict: a leftover worktree directory or branch from a\n * crashed run is renamed aside under a `.bak.<stamp>` name — never destroyed —\n * before the fresh one is created, mirroring `.volley.bak.<stamp>`.\n */\nexport function create_worktree(options: {\n workspace: string;\n branch: string;\n base?: string;\n log?: (message: string) => void;\n}): WorktreeHandle {\n const repo = resolve(options.workspace);\n if (!existsSync(join(repo, '.git'))) {\n throw config_error(`--worktree requires the workspace to be a git repository: ${repo}`);\n }\n const path = worktree_path(repo);\n const base = options.base ?? 'HEAD';\n const log = options.log ?? (() => {});\n\n // Preserve a leftover directory (possibly dirty), then drop its now-dangling\n // registration so `worktree add` sees a clean slate.\n if (existsSync(path)) {\n const backup = `${path}.bak.${backup_stamp()}`;\n renameSync(path, backup);\n git(repo, ['worktree', 'prune']);\n log(`worktree: rotated existing ${path} aside to ${backup}`);\n }\n // Preserve a leftover branch's commits rather than clobbering with `-B`.\n if (branch_exists(repo, options.branch)) {\n const backup_branch = `${options.branch}.bak.${backup_stamp()}`;\n git_ok(repo, ['branch', '-m', options.branch, backup_branch]);\n log(`worktree: rotated existing branch ${options.branch} aside to ${backup_branch}`);\n }\n\n git_ok(repo, ['worktree', 'add', '-b', options.branch, path, base]);\n\n // The toolchain rides along: `node_modules` is untracked, so a fresh\n // checkout has none — link the workspace's install in so the deterministic\n // check (which runs at the build root) and the builder's `bash` can\n // run the project toolchain without a per-run re-install.\n const modules = join(repo, 'node_modules');\n if (existsSync(modules) && !existsSync(join(path, 'node_modules'))) {\n symlinkSync(modules, join(path, 'node_modules'), 'dir');\n log(`worktree: linked node_modules from ${repo}`);\n }\n\n return { path, branch: options.branch };\n}\n\n/** What a teardown left behind. Both fields are null on the discarding path —\n * branch and checkout are gone, which is the point. */\nexport type TeardownOutcome = {\n /** The run branch teardown kept, holding work that was never integrated, for a\n * `git switch` / `git cherry-pick`. Null when the branch was deleted (nothing\n * was salvaged, or the run committed nothing worth keeping). */\n salvaged_branch: string | null;\n /** The checkout teardown refused to delete because its work could not be\n * committed (a stale index lock, a broken repo): the files are\n * still on disk, and the next run rotates them aside rather than destroying\n * them. Null whenever the checkout was removed. */\n kept_path: string | null;\n};\n\n/**\n * Tear the worktree down with the idempotent trio: remove the worktree,\n * delete its branch, prune the registration. Each step tolerates the target\n * already being gone, so a second teardown — or teardown of a worktree that\n * was never created — is a safe no-op.\n *\n * `salvage` flips the trio from *discard* to *keep* for the one case that has no\n * other copy of its work: a converged run whose effects were never integrated\n * (`--worktree` without `--git` — there are no checkpoint commits and no squash\n * merge, so `branch -D` plus a `--force` removal would eat the build). Teardown\n * then commits the checkout's state onto the run branch, skips the `branch -D`,\n * and removes only the checkout. Failed and integrated runs keep discarding:\n * nothing is left to save.\n */\nexport function teardown_worktree(options: {\n workspace: string;\n branch: string;\n salvage?: boolean;\n}): TeardownOutcome {\n const repo = resolve(options.workspace);\n const path = worktree_path(repo);\n const outcome: TeardownOutcome =\n options.salvage === true\n ? salvage_worktree(repo, path, options.branch)\n : { salvaged_branch: null, kept_path: null };\n // Salvage that could not commit: the work exists only in this directory, so\n // leave the whole worktree standing rather than removing what holds it.\n if (outcome.kept_path !== null) return outcome;\n\n git_quiet(repo, ['worktree', 'remove', '--force', path]);\n if (outcome.salvaged_branch === null) {\n git_quiet(repo, ['branch', '-D', options.branch]);\n }\n git_quiet(repo, ['worktree', 'prune']);\n // If git left the directory behind (already detached from the repo), clear it.\n if (existsSync(path)) {\n try {\n rmSync(path, { recursive: true, force: true });\n } catch {\n // Best effort; a lingering directory does not fail the run.\n }\n }\n return outcome;\n}\n\n/**\n * Commit whatever the run left in the worktree onto the run's own branch, so an\n * unintegrated success survives its teardown. Reports the branch when it ends up\n * carrying commits the workspace branch does not — a run that changed nothing\n * leaves no branch behind — or the checkout path when the commit did not land,\n * which is teardown's signal to keep its hands off the directory.\n */\nfunction salvage_worktree(repo: string, path: string, branch: string): TeardownOutcome {\n if (existsSync(path)) {\n git_quiet(path, ['add', '-A']);\n git_quiet(path, [\n ...commit_identity(path),\n 'commit',\n '-m',\n `volley: salvage unintegrated worktree (${branch})`,\n '--no-verify',\n ]);\n if (worktree_dirty(path)) return { salvaged_branch: null, kept_path: path };\n }\n return { salvaged_branch: branch_ahead(repo, branch) ? branch : null, kept_path: null };\n}\n\n/** Uncommitted or untracked changes still in the checkout — i.e. the salvage\n * commit did not land. A git call that fails outright reads as clean: teardown's\n * existing guards already cope with a checkout git cannot speak for. */\nfunction worktree_dirty(path: string): boolean {\n const status = git_quiet(path, ['status', '--porcelain']);\n return status.status === 0 && status.stdout.trim().length > 0;\n}\n\n/** Does `branch` carry commits the workspace's HEAD does not? The run branch is\n * cut from HEAD, so this asks \"did the run commit anything?\" — and answers false\n * for a branch that does not exist, which keeps teardown idempotent. */\nfunction branch_ahead(repo: string, branch: string): boolean {\n const ahead = git_quiet(repo, ['rev-list', '--count', `HEAD..${branch}`]);\n return ahead.status === 0 && Number(ahead.stdout.trim()) > 0;\n}\n\nexport type WorktreeOptions<T> = {\n enabled: boolean;\n workspace: string;\n branch: string;\n log?: (message: string) => void;\n /** Consulted with the body's value on a clean exit: `true` means this run's\n * work was never integrated, so teardown must salvage it onto the run branch\n * instead of discarding it. Never consulted when the body throws — a\n * failed run's branch is thrown away wholesale. */\n salvage?: (value: T) => boolean;\n};\n\n/** The body's value plus what teardown left behind. */\nexport type WorktreeOutcome<T> = TeardownOutcome & { value: T };\n\n/**\n * Run `body` with the run's worktree lifecycle around it: when enabled, create\n * the worktree first and guarantee teardown on every exit path; when disabled,\n * this is a transparent pass-through so the default path is byte-for-byte\n * unchanged.\n *\n * The discarding teardown stays in the `finally` — it is what a throw, an abort,\n * or a non-salvaging exit gets. A *salvaging* teardown has to run inside the\n * `try` instead, because its outcome (the surviving branch) is part of this\n * call's return value; `discard_on_exit` hands the responsibility over so the\n * two never both fire and `branch -D` the branch salvage just kept.\n */\nexport async function with_worktree<T>(\n options: WorktreeOptions<T>,\n body: () => Promise<T>,\n): Promise<WorktreeOutcome<T>> {\n if (!options.enabled) {\n return { value: await body(), salvaged_branch: null, kept_path: null };\n }\n create_worktree({\n workspace: options.workspace,\n branch: options.branch,\n ...(options.log !== undefined ? { log: options.log } : {}),\n });\n let discard_on_exit = true;\n try {\n const value = await body();\n if (options.salvage?.(value) !== true) {\n return { value, salvaged_branch: null, kept_path: null };\n }\n discard_on_exit = false;\n return {\n value,\n ...teardown_worktree({\n workspace: options.workspace,\n branch: options.branch,\n salvage: true,\n }),\n };\n } finally {\n if (discard_on_exit) {\n teardown_worktree({ workspace: options.workspace, branch: options.branch });\n }\n }\n}\n","/**\n * Builder invocation: one call to the builder leaf per iteration is one\n * complete agentic session in the workspace — Claude Code under `claude_cli`,\n * or a model driving volley's tools on any other provider, local or hosted.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { model_call } from 'fascicle';\nimport type {\n Engine,\n GenerateOptions,\n GenerateResult,\n ModelCallInput,\n RunContext,\n Step,\n StreamChunk,\n Tool,\n ToolApprovalHandler,\n} from 'fascicle';\nimport { warn_small_local_context } from './builder/context_check.js';\nimport { step_countdown } from './builder/countdown.js';\nimport { builder_tools, type BashExecutor } from './builder/tools.js';\nimport { CHECK_REJECTED } from './check/command.js';\nimport { accumulate } from './cost.js';\nimport { seat_base_url } from './engine.js';\nimport { prewarm_ollama_model } from './prewarm.js';\nimport { config_error, phase_error } from './types.js';\nimport type { CheckResult, LoopState, ResolvedConfig } from './types.js';\nimport type { ToolSet } from './workspace_tools.js';\nimport { build_root } from './worktree.js';\n\nexport const BUILDER_ALLOWED_TOOLS = [\n 'Read',\n 'Write',\n 'Edit',\n 'MultiEdit',\n 'Bash',\n 'Grep',\n 'Glob',\n 'WebFetch',\n] as const;\n\nexport function compose_builder_system(): string {\n return [\n 'You are the builder inside the volley harness: an autonomous agent',\n 'iterating on a workspace until it satisfies a task and its acceptance',\n 'criteria. Work directly in the current working directory. Plan',\n 'internally, make the changes, and verify your own work before finishing.',\n ].join('\\n');\n}\n\n/** Walk up from this module to the package root (works from src/ under tsx\n * and from dist/ in the published package, which ships src/builder/presets). */\nexport function builder_presets_dir(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const candidate = join(dir, 'src', 'builder', 'presets');\n if (existsSync(candidate)) return candidate;\n dir = dirname(dir);\n }\n throw config_error('builder presets directory not found');\n}\n\n/** The harness append each tool set's builder reads: one naming volley's own\n * tools, or one naming fascicle's workspace tools under `volley acp` and\n * saying what a call the user refused means. */\nconst HARNESS_APPENDS: Record<ToolSet, string> = {\n volley: 'harness_append_local.md',\n acp: 'harness_append_acp.md',\n};\n\n/** Step 2 of \"Work this way\", as both harness appends word it for a builder\n * held to one tool call a turn. */\nconst ONE_CALL_A_TURN = '2. Call one tool at a time and read its result before deciding the next\\n call.';\n\n/** Step 2 for a builder that may make several calls a turn: fascicle runs a\n * turn's calls in order, so a read can't race an edit, but each change or\n * command is still worth reading before the next. Reads don't count toward\n * the cap, so the step names no number. */\nconst BATCHED_CALLS = [\n '2. Batch independent reads into one turn, but make one change or command per',\n ' turn, and read its result before deciding the next call.',\n].join('\\n');\n\n// The CLI system prompt assumes CLI semantics (built-in tools, implicit\n// cwd), so the local builder gets its own — its tool set, the\n// workspace-is-cwd convention, and the harness-enforced `finish` stop.\nexport function compose_builder_system_local(\n tool_set: ToolSet = 'volley',\n max_tool_calls = 1,\n): string {\n const identity = [\n 'You are the builder inside the volley harness: an autonomous agent',\n 'iterating on a workspace until it satisfies a task and its acceptance',\n 'criteria.',\n ].join('\\n');\n const append = readFileSync(join(builder_presets_dir(), HARNESS_APPENDS[tool_set]), 'utf8');\n const worded =\n max_tool_calls > 1 ? append.replace(ONE_CALL_A_TURN, BATCHED_CALLS) : append;\n return `${identity}\\n\\n${worded.trimEnd()}`;\n}\n\n/** The builder system prompt for the active provider: the `claude_cli`\n * prompt (implicit built-in tools, \"the current working directory\") for the\n * CLI builder, which never takes an injected set, or the local prompt naming\n * the seat's tool set for every provider that runs volley's tool loop,\n * `openrouter` included. Mirrors the critic's `resolve_critic_prompt`. */\nfunction resolve_builder_system(config: ResolvedConfig, tool_set?: ToolSet): string {\n return config.builder_provider === 'claude_cli'\n ? compose_builder_system()\n : compose_builder_system_local(tool_set, config.builder_max_tool_calls);\n}\n\n// Salvage budget for a tool call a local model emits as assistant text instead\n// of a structured tool_call (Hermes / json-fenced / Qwen3-Coder XML). Must be\n// > 0 to turn salvage on; the budget is shared across the whole\n// generate call and each salvage is observable on the result for the\n// salvage-rate health metric.\nconst BUILDER_TOOL_CALL_REPAIR_ATTEMPTS = 3;\n\n/** How the step countdown tells the builder to run the check: the command\n * volley gates on, with the digest and without `--json`, the configured\n * command, or the project's own tests when no check gates the run. A\n * workspace can hold checkride with no `check` script, so not `pnpm check`. */\nfunction check_hint(config: ResolvedConfig): string {\n if (config.check_resolved === 'checkride') return 'the check (`pnpm exec checkride --digest`)';\n if (config.check_resolved === 'command') return `the check (\\`${config.check}\\`)`;\n return \"the project's tests\";\n}\n\n/** Per-provider tool wiring for the builder, mirroring `critic_tool_options`.\n * The `claude_cli` builder is confined at the CLI permission layer (allowlist +\n * permission mode) and brings its own built-in tools — this arm is unchanged\n * from v2, and takes no injected tools or approval handler. Every other\n * builder, local or `openrouter`, brings none, so volley supplies its whole\n * workspace tool surface (or the set the caller injected in its place, with\n * the handler that answers its approvals), the per-call loop knobs, the step\n * countdown (`./builder/countdown.ts`), the output cap when one is set, and\n * **no** schema (it produces a workspace, not a verdict); per-call values win\n * over engine defaults. */\nfunction builder_tool_options(\n deps: BuilderDeps,\n): Pick<\n GenerateOptions,\n | 'tools'\n | 'on_tool_approval'\n | 'provider_options'\n | 'max_steps'\n | 'tool_error_policy'\n | 'tool_call_repair_attempts'\n | 'max_tool_calls_per_step'\n | 'prepare_step'\n | 'max_tokens'\n | 'truncated_turn_policy'\n> {\n const { config } = deps;\n const bash_executor = deps.bash_executor ?? null;\n if (config.builder_provider === 'claude_cli') {\n return {\n provider_options: {\n claude_cli: {\n allowed_tools: [...BUILDER_ALLOWED_TOOLS],\n extra_args: ['--permission-mode', config.builder_permission_mode],\n },\n },\n };\n }\n return {\n // Containment root re-points to the worktree under `--worktree`, so\n // the model's writes, edits, and `bash` cwd land there and leave the\n // workspace untouched. When the sandbox is active its `docker exec` executor\n // runs `bash` in the container against the bind-mounted worktree; the\n // host `spawnSync` default stands in otherwise.\n tools:\n deps.tools === undefined\n ? builder_tools(\n build_root(config.workspace, config.worktree),\n bash_executor !== null ? { bash_executor } : {},\n )\n : [...deps.tools],\n ...(deps.on_tool_approval !== undefined ? { on_tool_approval: deps.on_tool_approval } : {}),\n max_steps: config.builder_max_steps,\n tool_error_policy: 'feed_back',\n tool_call_repair_attempts: BUILDER_TOOL_CALL_REPAIR_ATTEMPTS,\n max_tool_calls_per_step: config.builder_max_tool_calls,\n prepare_step: step_countdown(config.builder_max_steps, check_hint(config)),\n // A capped turn that runs out before it calls a tool goes on to the next\n // step instead of ending the session; with no cap, a turn cut off at the\n // provider's own limit still ends it, as one cut off at a full context\n // window would only be cut off again.\n ...(config.builder_max_output_tokens !== null\n ? { max_tokens: config.builder_max_output_tokens, truncated_turn_policy: 'continue' as const }\n : {}),\n };\n}\n\n/** What the builder is told about the iteration before its own, besides the\n * critic's feedback. */\nexport type PreviousRound = {\n /** That iteration's check. Its output goes in the prompt when it failed. */\n check: CheckResult | null;\n /** The step limit that iteration's builder hit before it called finish, or\n * null when it stopped on its own. */\n step_limit_hit: number | null;\n};\n\nexport type BuilderPromptInput = {\n task: string;\n criteria: string;\n feedback: string | null;\n iteration: number;\n checkride: boolean;\n previous: PreviousRound | null;\n};\n\n/** How much of the last check's output the builder's prompt carries: a few KB,\n * whatever the runner. checkride's digest already fits in 8 kB, and the builder\n * can run the check again for the rest. */\nexport const PREVIOUS_CHECK_MAX_CHARS = 6000;\n\n/** The first `max` characters of `text`, saying where it was cut. */\nfunction head(text: string, max: number, rest: string): string {\n return text.length <= max ? text : `${text.slice(0, max)}\\n… (cut at ${String(max)} characters; ${rest})`;\n}\n\n/** The last `max` characters of `text`, saying what came before was cut. */\nfunction tail(text: string, max: number): string {\n return text.length <= max\n ? text\n : `… (the last ${String(max)} characters of ${String(text.length)})\\n${text.slice(-max)}`;\n}\n\n/** The part of a failed check the builder reads first: checkride's digest,\n * else the start of each failing slot's raw output, else the end of a\n * command's output, where test runners and compilers sum up. */\nfunction check_excerpt(check: CheckResult): string {\n const max = PREVIOUS_CHECK_MAX_CHARS;\n if (check.digest !== undefined) {\n return head(check.digest.trimEnd(), max, '.check/digest.md has the rest');\n }\n if (check.detail.length > 0) {\n const slots = check.detail.map((artifact) => {\n const source = artifact.path === null ? '' : ` (.check/${basename(artifact.path)})`;\n return `${artifact.slot}${source}:\\n${artifact.content.trimEnd()}`;\n });\n return head(slots.join('\\n\\n'), max, 'each slot\\'s raw output under .check/ has the rest');\n }\n return tail((check.log ?? '').trimEnd(), max);\n}\n\n/** The check section of a later iteration's prompt: what the deterministic\n * gate itself said about the last session's work, so the builder starts from\n * its words rather than the critic's account of them, or re-running it to\n * find out. Empty unless that check ran and failed. A check the user rejected\n * when it asked to run is recorded as failed but said nothing, and the\n * section says so rather than call the work failed. */\nfunction previous_check_section(check: CheckResult | null): string[] {\n if (check === null || !check.ran || check.ok) return [];\n const heading = ['', 'PREVIOUS CHECK RESULT', '---------------------'];\n if (check.log === CHECK_REJECTED) {\n return [\n ...heading,\n 'The check never ran on the work your last session left: it was rejected when it',\n 'asked to run, so nothing has verified that work yet.',\n ];\n }\n const runner = check.runner === 'checkride' ? 'checkride, ' : '';\n const exit = check.exit_code === null ? 'no exit code' : `exit ${String(check.exit_code)}`;\n const lines = [\n ...heading,\n `The check failed on the work your last session left (${runner}${exit}).`,\n ];\n if (check.failing_slots.length > 0) {\n lines.push(`Failing slots: ${check.failing_slots.join(', ')}.`);\n }\n const excerpt = check_excerpt(check);\n if (excerpt.length > 0) lines.push('', excerpt);\n return lines;\n}\n\n/** The line a later iteration's prompt carries when the last session ran out\n * of steps: it never got to verify, so this one should check first. */\nfunction step_limit_lines(step_limit_hit: number | null): string[] {\n if (step_limit_hit === null) return [];\n return [\n '',\n `Your last session hit its ${String(step_limit_hit)}-step limit before it called finish, so`,\n 'it may never have verified its work. Run the check first this time, and keep',\n 'enough steps in hand to verify again before you finish.',\n ];\n}\n\nexport function compose_builder_prompt(input: BuilderPromptInput): string {\n const parts = [\n 'TASK',\n '----',\n input.task,\n '',\n 'ACCEPTANCE CRITERIA',\n '-------------------',\n input.criteria,\n '',\n `ITERATION: ${input.iteration}`,\n ];\n if (input.iteration > 1 && input.feedback !== null) {\n parts.push(\n '',\n 'PREVIOUS CRITIC FEEDBACK',\n '------------------------',\n input.feedback,\n '',\n 'Address the feedback above. The workspace already contains your prior work;',\n 'read the current state, then make the necessary changes.',\n );\n }\n if (input.iteration > 1 && input.previous !== null) {\n parts.push(\n ...previous_check_section(input.previous.check),\n ...step_limit_lines(input.previous.step_limit_hit),\n );\n }\n if (input.checkride) {\n parts.push(\n '',\n 'The definition of done for this workspace includes checkride exiting 0. Run',\n '`pnpm exec checkride --digest`, the check volley gates on, after each batch of',\n 'edits and again before you finish. When it fails, read .check/digest.md',\n 'first: it lists each failing slot\\'s first findings. Open a slot\\'s raw',\n 'output under .check/ only if the digest isn\\'t enough, then fix and re-run.',\n );\n }\n return parts.join('\\n');\n}\n\n// A `max_steps` cutoff is not an error. The local builder burned its whole\n// step budget without calling `finish`, so its partial workspace goes to check\n// + critic exactly like a `finish`-terminated iteration (the critic sees\n// incomplete work and requests changes, the loop continues). The renderer\n// surfaces this as a warning and `finish_reason: 'max_steps'` is recorded in\n// the iteration summary — non-convergence is data, not an exception.\nfunction builder_max_steps_warning(max_steps: number): string {\n return (\n `builder hit the ${String(max_steps)}-step limit without calling finish; ` +\n 'handing the partial workspace to check + critic (raise --builder-max-steps if this recurs)'\n );\n}\n\nexport type BuilderDeps = {\n engine: Engine;\n config: ResolvedConfig;\n on_chunk: (chunk: StreamChunk) => void;\n /** The `bash` executor for a sandboxed local builder (`docker exec` against\n * the run's container), or null to use the host `spawnSync` default (the\n * unsandboxed escape hatch, or `claude_cli` which supplies no volley tools). */\n bash_executor?: BashExecutor | null;\n /** Tools to hand the builder in place of volley's own set; absent, it gets\n * that set. A `claude_cli` builder brings its own tools and never takes\n * these. */\n tools?: ReadonlyArray<Tool>;\n /** Which set `tools` is, so the prompt names the tools the builder holds;\n * absent, volley's own. */\n tool_set?: ToolSet;\n /** Answers each call to a tool that asks first (`needs_approval`). Like\n * `tools`, it reaches every builder but `claude_cli`. Absent, such a call\n * fails closed. */\n on_tool_approval?: ToolApprovalHandler;\n};\n\n/** The builder's model boundary: one call is one complete agentic session in\n * the build root, and its output is the whole `GenerateResult`, because the\n * phase records usage, cost, timing, and tool calls from it. */\nexport type BuilderStep = Step<ModelCallInput, GenerateResult>;\n\n/** Build the builder leaf for this run. Everything but the prompt is fixed for\n * the whole run, so it is wired once here: the provider's system prompt, its\n * tool surface, and the live chunk stream to the renderer. */\nexport function make_builder_step(deps: BuilderDeps): BuilderStep {\n const { config } = deps;\n return model_call({\n engine: deps.engine,\n id: 'builder',\n description: 'model call: one agentic session in the build root',\n provider: config.builder_provider,\n model: config.builder_model,\n system: resolve_builder_system(config, deps.tool_set),\n on_chunk: deps.on_chunk,\n ...builder_tool_options(deps),\n });\n}\n\nexport type BuilderRunDeps = {\n builder: BuilderStep;\n config: ResolvedConfig;\n warn: (message: string) => void;\n};\n\n/** Run one builder session on the opened iteration `state`, told what the\n * iteration before it left behind (`previous`, null on the first). */\nexport async function run_builder(\n deps: BuilderRunDeps,\n state: LoopState,\n previous: PreviousRound | null,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config } = deps;\n try {\n // Warn at builder start where a too-small context window is detectable —\n // it silently truncates tool schemas (the #1 local tool-calling failure) —\n // then pre-load the model so a cold multi-GB load doesn't blow the real\n // call's first-byte timeout. Both best-effort and Ollama-only; neither\n // blocks the build. Both go to the builder seat's own server.\n if (config.builder_provider === 'ollama') {\n const base_url = seat_base_url('ollama', config.builder_url, process.env);\n await warn_small_local_context(\n config.builder_provider,\n config.builder_model,\n base_url,\n deps.warn,\n ctx.abort,\n );\n await prewarm_ollama_model(base_url, config.builder_model, ctx.abort);\n }\n const result = await ctx.call(\n deps.builder,\n compose_builder_prompt({\n task: config.prompt,\n criteria: config.criteria,\n feedback: state.feedback,\n iteration: state.iteration,\n checkride: config.check_resolved === 'checkride',\n previous,\n }),\n );\n const built = accumulate(state, 'builder', result, config.builder_model);\n // `max_steps` is a backstop, not a failure — surface it, count it, and\n // carry on.\n if (result.finish_reason !== 'max_steps') return built;\n deps.warn(builder_max_steps_warning(config.builder_max_steps));\n return { ...built, builder_max_steps_hits: built.builder_max_steps_hits + 1 };\n } catch (err) {\n throw phase_error('builder', state.iteration, err);\n }\n}\n","/**\n * What the builder changed, and whether it touched the gate.\n *\n * Until now the harness's only view of a builder's work was \"the check exited\n * 0\" — which is exactly the thing a builder can arrange by editing the check.\n * The reckon run (`research/reckon-local-run-finding.md`) closed that hole by\n * hand: after a green all-local run, the salvage commit was inspected to confirm\n * it touched only the four source modules and no test, fixture, or manifest.\n * This module is that inspection, mechanized — diff the build root against a\n * baseline captured before the first iteration, classify every changed path\n * against the gate patterns, and hand the result to the critic prompt, the run\n * summary, and (opt-in) the loop's stopping condition.\n *\n * Everything here is best-effort and non-throwing. A build root that is not a\n * git repository simply has no change set (`null`) and the loop behaves exactly\n * as it did before: change detection is evidence, never a precondition.\n *\n * Deliberately *not* collected: diff hunks. The changed-path list is bounded and\n * cheap, while inlined content would blow a local critic's context (32k on the\n * reckon seats) for the one part of the picture its read tools can already\n * fetch — the critic learns *where* to look, then looks.\n */\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { config_error } from './types.js';\nimport type { ChangeSet, ChangeStatus, ChangedFile } from './types.js';\n\n/**\n * The default gate: paths whose edits change *what passing means* rather than\n * whether the work passes. Tests and fixtures are the executable half of the\n * spec; the check configuration and manifest decide which tests run at all.\n *\n * Deliberately broad and language-general — a false positive costs one line in\n * the critic's prompt, while a miss is the failure mode this exists to prevent.\n * A config's own `gate_paths` replaces the list outright (spec-writing tasks\n * legitimately own their tests).\n */\nexport const DEFAULT_GATE_PATTERNS: string[] = [\n '**/*.test.*',\n '**/*.spec.*',\n '**/*_test.*',\n '**/test/**',\n '**/tests/**',\n '**/__tests__/**',\n '**/spec/**',\n '**/fixtures/**',\n '**/checkride.config.*',\n '**/vitest.config.*',\n '**/jest.config.*',\n '**/playwright.config.*',\n '**/package.json',\n '.github/workflows/**',\n];\n\n/** Harness state, toolchain, and VCS internals: never the builder's work, even\n * when they sit in the build root and show up dirty. `.volley/` is the control\n * plane, `.check/` is the check's own artifacts, `node_modules/` rides in on the\n * worktree symlink. */\nconst EXCLUDED_PREFIXES = ['.volley/', '.volley.bak.', '.check/', '.git/', 'node_modules/'];\n\n/** How many changed paths the set carries. The cap bounds the critic prompt and\n * the archived summary on a sweeping refactor; `gate_edits` and `total` are\n * always computed over the full list, so nothing load-bearing is truncated. */\nconst DEFAULT_LIMIT = 200;\n\ntype GitResult = { status: number; stdout: string };\n\n/** Run git in `root`, best-effort: a missing binary, a broken repo, or a\n * non-zero exit all read as \"no output\". Change detection reports what it can\n * and never fails a run over what it cannot (unlike `worktree.ts`, where git is\n * a precondition the operator asked for). */\nfunction git(root: string, args: string[]): GitResult {\n try {\n const result = spawnSync('git', args, {\n cwd: root,\n env: command_env(process.env),\n encoding: 'utf8',\n maxBuffer: 32 * 1024 * 1024,\n });\n return { status: result.status ?? -1, stdout: result.stdout ?? '' };\n } catch {\n return { status: -1, stdout: '' };\n }\n}\n\n/** Is this directory inside a git repository? Asked of git rather than by\n * looking for `.git`, so a workspace nested under a repo root — and a linked\n * worktree, whose `.git` is a file — both answer correctly. */\nfunction in_git_repo(root: string): boolean {\n return git(root, ['rev-parse', '--git-dir']).status === 0;\n}\n\n/**\n * The commit a run's changes are measured against: the build root's HEAD, read\n * once before the first iteration. Null when the root is not a repository or has\n * no commits yet — in the latter case `collect_changes` still reports untracked\n * files, which is the whole of a from-scratch build.\n */\nexport function capture_baseline(root: string): string | null {\n const head = git(root, ['rev-parse', 'HEAD']);\n if (head.status !== 0) return null;\n const sha = head.stdout.trim();\n return sha.length > 0 ? sha : null;\n}\n\n/**\n * The commit a critique's change is measured from: `rev` (`--baseline`)\n * resolved in `root`, so the change is everything that differs from it,\n * committed or not, untracked files included. With no revision named it's\n * HEAD, so the uncommitted and untracked edits are the change, and, as for a\n * run, null where there's no repository or no commit yet. A named revision\n * that isn't a commit there, or one named where there's no repository, is a\n * config error.\n */\nexport function resolve_baseline(root: string, rev: string | undefined): string | null {\n if (rev === undefined) return capture_baseline(root);\n if (!in_git_repo(root)) {\n throw config_error(`--baseline needs the workspace to be a git repository: ${root}`);\n }\n // `--end-of-options` keeps a revision that starts with `-` from reading as a flag.\n const resolved = git(root, ['rev-parse', '--verify', '--quiet', '--end-of-options', `${rev}^{commit}`]);\n const sha = resolved.stdout.trim();\n if (resolved.status !== 0 || sha.length === 0) {\n throw config_error(`--baseline names no commit in ${root}: ${rev}`);\n }\n return sha;\n}\n\n/** git's status letters, folded onto the four cases worth naming. Rename and\n * copy both record the destination path — where the content lives now. */\nfunction change_status(code: string): ChangeStatus {\n const letter = code.charAt(0);\n if (letter === 'A') return 'added';\n if (letter === 'M' || letter === 'T') return 'modified';\n if (letter === 'D') return 'deleted';\n if (letter === 'R' || letter === 'C') return 'renamed';\n return 'unknown';\n}\n\ntype RawChange = { path: string; status: ChangeStatus };\n\n/**\n * Parse `git diff --name-status -z`: a flat NUL-separated stream of\n * `status, path` pairs, except renames and copies, which carry `status, source,\n * destination`. NUL separation (rather than lines) is what makes paths with\n * spaces or newlines in them safe to read.\n */\nfunction parse_name_status(stdout: string): RawChange[] {\n const tokens = stdout.split('\\0').filter((token) => token.length > 0);\n const changes: RawChange[] = [];\n let index = 0;\n while (index < tokens.length) {\n const code = tokens[index] ?? '';\n const paired = code.startsWith('R') || code.startsWith('C');\n const path = tokens[index + (paired ? 2 : 1)];\n if (path !== undefined) changes.push({ path, status: change_status(code) });\n index += paired ? 3 : 2;\n }\n return changes;\n}\n\n/** Parse a NUL-separated path list (`git ls-files -z`). */\nfunction parse_paths(stdout: string): string[] {\n return stdout.split('\\0').filter((path) => path.length > 0);\n}\n\nfunction excluded(path: string, excluded_dir: string | null): boolean {\n if (excluded_dir !== null && path.startsWith(`${excluded_dir}/`)) return true;\n return EXCLUDED_PREFIXES.some((prefix) => path.startsWith(prefix));\n}\n\n/**\n * Compile one glob to an anchored regular expression. Supports the three forms\n * the gate patterns need — `**` across separators, `*` within a segment, `?` for\n * one character — in a single pass, because sequential string replacement would\n * re-process the regex syntax its own earlier passes emit.\n *\n * A leading globstar-plus-separator collapses to \"any number of leading\n * segments, including none\", so one `test` pattern matches `test/a.mjs` and\n * `src/test/a.mjs` alike instead of needing a rule per depth.\n */\nfunction glob_to_regexp(pattern: string): RegExp {\n let source = '';\n let index = 0;\n while (index < pattern.length) {\n const char = pattern.charAt(index);\n if (char === '*' && pattern.charAt(index + 1) === '*') {\n const slashed = pattern.charAt(index + 2) === '/';\n source += slashed ? '(?:.*/)?' : '.*';\n index += slashed ? 3 : 2;\n continue;\n }\n if (char === '*') {\n source += '[^/]*';\n index += 1;\n continue;\n }\n if (char === '?') {\n source += '[^/]';\n index += 1;\n continue;\n }\n source += /[.+^${}()|[\\]\\\\]/.test(char) ? `\\\\${char}` : char;\n index += 1;\n }\n return new RegExp(`^${source}$`);\n}\n\n/** Does this path match any of these glob patterns? Exported for the gate-path\n * unit tests, which pin the matcher's semantics independently of git. */\nexport function matches_any(path: string, patterns: string[]): boolean {\n return patterns.some((pattern) => glob_to_regexp(pattern).test(path));\n}\n\nexport type CollectChangesOptions = {\n /** Where the builder's effects land — the worktree under `--worktree`, else\n * the workspace (`build_root`). */\n root: string;\n /** The run's baseline commit, from `capture_baseline`. */\n baseline: string | null;\n gate_patterns: string[];\n /** A state root inside `root`, relative to it (`state_root_within`): the\n * harness's files, never the builder's. */\n excluded_dir?: string | null;\n limit?: number;\n};\n\nfunction by_path(left: ChangedFile, right: ChangedFile): number {\n if (left.path < right.path) return -1;\n return left.path > right.path ? 1 : 0;\n}\n\n/**\n * Everything the builder changed in `root` since `baseline`, classified against\n * the gate patterns. Tracked edits come from the diff, brand-new files from the\n * untracked list — together they cover both checkpoint styles, since `--git`\n * commits the builder's work as it goes while a plain run leaves it dirty.\n *\n * Returns null when `root` is not a git repository: the one honest answer, and\n * the signal every consumer uses to omit the section rather than claim the\n * builder changed nothing.\n */\nexport function collect_changes(options: CollectChangesOptions): ChangeSet | null {\n const { root, baseline } = options;\n if (!in_git_repo(root)) return null;\n const limit = options.limit ?? DEFAULT_LIMIT;\n\n // `--relative` + `-- .` keep both halves scoped to the build root and its own\n // path vocabulary, for the case where the workspace sits under a repo root.\n const tracked =\n baseline === null\n ? []\n : parse_name_status(\n git(root, ['diff', '--name-status', '--relative', '-z', baseline, '--', '.']).stdout,\n );\n const untracked: RawChange[] = parse_paths(\n git(root, ['ls-files', '--others', '--exclude-standard', '-z']).stdout,\n ).map((path) => ({ path, status: 'added' }));\n\n const excluded_dir = options.excluded_dir ?? null;\n const seen = new Set<string>();\n const files: ChangedFile[] = [];\n for (const change of [...tracked, ...untracked]) {\n if (excluded(change.path, excluded_dir) || seen.has(change.path)) continue;\n seen.add(change.path);\n files.push({ ...change, gate: matches_any(change.path, options.gate_patterns) });\n }\n const sorted = files.toSorted(by_path);\n\n return {\n baseline,\n // Over the full list, before the cap: truncation must never hide a gate edit.\n gate_edits: sorted.filter((file) => file.gate).map((file) => file.path),\n total: sorted.length,\n files: sorted.slice(0, limit),\n truncated: sorted.length > limit,\n };\n}\n","/**\n * Critic prompt resolution and composition. Presets live as\n * markdown files in ./presets/ — discoverable by listing the directory —\n * and every critic system prompt gets the harness append.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { config_error } from '../types.js';\nimport type {\n ChangeSet,\n ChangeStatus,\n ChangedFile,\n CheckResult,\n ResolvedConfig,\n} from '../types.js';\nimport { state_path } from '../workspace.js';\nimport type { ToolSet } from '../workspace_tools.js';\nimport { build_root } from '../worktree.js';\n\n/** Walk up from this module to the package root (works from src/ under tsx\n * and from dist/ in the published package, which ships src/critic/presets). */\nexport function presets_dir(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const candidate = join(dir, 'src', 'critic', 'presets');\n if (existsSync(candidate)) return candidate;\n const local = join(dir, 'presets');\n if (existsSync(local)) return local;\n dir = dirname(dir);\n }\n throw config_error('critic presets directory not found');\n}\n\n/** The harness append that names the critic's reads. The CLI critic reads\n * via built-in Read/Grep/Glob and never takes an injected set; every other\n * critic, local or `openrouter`, reads via volley's read_file/search_files/\n * list_files, or under `volley acp` via fascicle's read_file/list_files/\n * search. */\nfunction harness_append_file(config: ResolvedConfig, tool_set: ToolSet): string {\n if (config.critic_provider === 'claude_cli') return 'harness_append.md';\n return tool_set === 'acp' ? 'harness_append_acp.md' : 'harness_append_local.md';\n}\n\nexport function resolve_critic_prompt(config: ResolvedConfig, tool_set: ToolSet = 'volley'): string {\n const base =\n config.critic_prompt_path !== null\n ? readFileSync(config.critic_prompt_path, 'utf8')\n : readFileSync(join(presets_dir(), `${config.critic_preset}.md`), 'utf8');\n const append = readFileSync(join(presets_dir(), harness_append_file(config, tool_set)), 'utf8');\n return `${base.trimEnd()}\\n\\n${place_iterations_dir(append, config).trimEnd()}`;\n}\n\nconst ITERATIONS_DIR = '{{iterations_dir}}';\n\n/** Fill the harness append's line about prior iteration state with where the\n * run's `iterations/` sits, relative to the build root the critic reads from,\n * or drop the line when the run's state is outside that root: a confined\n * critic can't reach it, and naming it would only spend the critic's steps on\n * a path it can't open. */\nfunction place_iterations_dir(append: string, config: ResolvedConfig): string {\n const path = relative(\n build_root(config.workspace, config.worktree),\n state_path(config, 'iterations'),\n );\n const outside = path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path);\n return append\n .split('\\n')\n .filter((line) => !(outside && line.includes(ITERATIONS_DIR)))\n .join('\\n')\n .replaceAll(ITERATIONS_DIR, `${path}/`);\n}\n\nexport type CriticPromptInput = {\n criteria: string;\n iteration: number;\n check: CheckResult;\n /** What the builder changed since the run's baseline (`src/changes.ts`), or\n * null when the build root is not a git repository — then the section is\n * omitted rather than claiming the builder changed nothing. */\n changes: ChangeSet | null;\n};\n\n/** One-letter status column, so a hundred-path list stays readable. */\nconst STATUS_MARKS: Record<ChangeStatus, string> = {\n added: 'A',\n modified: 'M',\n deleted: 'D',\n renamed: 'R',\n unknown: '?',\n};\n\nfunction format_change(file: ChangedFile): string {\n return ` ${STATUS_MARKS[file.status]} ${file.path}`;\n}\n\n/**\n * What the builder actually touched, handed to the critic as evidence.\n *\n * Two things this fixes, both surfaced by the reckon run\n * (`research/reckon-local-run-finding.md`). A critic that sees only the finished\n * tree reviews *state* and re-reads code the check already blessed; a critic\n * that sees the change list reviews the *change*, and knows where to point its\n * read tools. And a builder that edited its own tests could previously pass both\n * gates in silence — the check because it was rewritten, the critic because\n * nothing told it that had happened.\n *\n * Paths only, never diff hunks: the list stays bounded for a 32k-context local\n * critic, which can read any file it wants once it knows which ones moved.\n */\nfunction format_changes_section(changes: ChangeSet | null): string | null {\n if (changes === null) return null;\n const scope = changes.baseline === null ? 'this run' : `baseline ${changes.baseline.slice(0, 8)}`;\n if (changes.total === 0) {\n return [\n `BUILDER CHANGES (since ${scope})`,\n '------------------------------',\n 'The builder changed no files. Unless the acceptance criteria were already',\n 'met before this run, that is itself grounds for changes_requested.',\n ].join('\\n');\n }\n const lines = [\n `BUILDER CHANGES (since ${scope})`,\n '------------------------------',\n 'Review the work as a change, not just as a finished tree. Read the files',\n 'below with your tools as needed.',\n '',\n ...changes.files.map(format_change),\n ];\n if (changes.truncated) {\n lines.push(\n ` … showing ${String(changes.files.length)} of ${String(changes.total)} changed paths`,\n );\n }\n if (changes.gate_edits.length > 0) {\n lines.push(\n '',\n `GATE EDITS (${String(changes.gate_edits.length)})`,\n '-----------',\n 'These changed paths are part of the gate — the tests, fixtures, and check',\n 'configuration that decide whether this work passes. A check the builder can',\n 'edit proves less than one it cannot.',\n '',\n ...changes.gate_edits.map((path) => ` ! ${path}`),\n '',\n 'Judge whether each of these edits was necessary and legitimate for the task',\n 'as specified. If any of them weakened the check, deleted a case, or moved a',\n 'target rather than meeting it, the work does not meet the criteria: return',\n 'changes_requested, name the file, and say what was weakened.',\n );\n }\n return lines.join('\\n');\n}\n\nfunction format_check_section(check: CheckResult): string {\n if (!check.ran) {\n return 'No deterministic check ran for this iteration. Base your verdict on workspace inspection alone.';\n }\n const lines = [\n `DETERMINISTIC CHECK (${check.runner})`,\n '------------------------------------',\n `result: ${check.ok ? 'PASSED' : 'FAILED'} (exit ${String(check.exit_code)})`,\n ];\n if (check.failing_slots.length > 0) {\n lines.push(`failing slots: ${check.failing_slots.join(', ')}`);\n }\n if (check.summary !== undefined) {\n lines.push('', 'summary.json:', '```json', JSON.stringify(check.summary, null, 2), '```');\n }\n for (const artifact of check.detail) {\n lines.push(\n '',\n `--- raw output for failing slot \"${artifact.slot}\"${artifact.truncated ? ` (truncated; full output archived at ${artifact.path ?? 'n/a'})` : ''} ---`,\n artifact.content,\n );\n }\n if (check.log !== undefined && check.log.length > 0) {\n lines.push('', 'check output:', '```', check.log, '```');\n }\n return lines.join('\\n');\n}\n\nexport function compose_critic_prompt(input: CriticPromptInput): string {\n const changes = format_changes_section(input.changes);\n return [\n 'ACCEPTANCE CRITERIA',\n '-------------------',\n input.criteria,\n '',\n `ITERATION: ${input.iteration}`,\n '',\n format_check_section(input.check),\n ...(changes === null ? [] : ['', changes]),\n '',\n 'Review the workspace against the acceptance criteria and return your',\n 'structured verdict.',\n ].join('\\n');\n}\n","/**\n * Critic invocation: a read-only session (`claude_cli`, or a local or\n * `openrouter` model with volley's read tools) returning a schema-validated\n * structured verdict. The\n * harness — not the critic — writes the run's `feedback.md` and `verdict`.\n */\nimport { z } from 'zod';\nimport { model_call } from 'fascicle';\nimport type {\n Engine,\n FallbackOutcome,\n GenerateOptions,\n GenerateResult,\n RetryOutcome,\n RunContext,\n Step,\n StreamChunk,\n Tool,\n} from 'fascicle';\nimport { accumulate } from '../cost.js';\nimport { seat_base_url } from '../engine.js';\nimport { prewarm_ollama_model } from '../prewarm.js';\nimport { error_kind, phase_error } from '../types.js';\nimport type { CauseKind, DegradeCause, LoopState, ResolvedConfig } from '../types.js';\nimport type { ToolSet } from '../workspace_tools.js';\nimport { build_root } from '../worktree.js';\nimport { compose_critic_prompt, resolve_critic_prompt } from './prompt.js';\nimport { read_only_tools, workspace_inventory } from './tools.js';\n\nconst CRITIC_ALLOWED_TOOLS = ['Read', 'Grep', 'Glob'] as const;\n\nconst CRITIC_DISALLOWED_TOOLS = 'Write,Edit,MultiEdit,NotebookEdit,Bash';\n\n/** A critic that holds tools isn't constrain-decoded, so nothing stops it\n * answering null for the feedback or the unmet list, as GLM did on approving.\n * Both fields allow null and read it as empty, so that answer is a verdict\n * rather than a schema failure that ends the run. fascicle sends the schema's\n * input side, so the model sees each field as its type or null, still\n * required; `.describe()` comes last so the description stays on the field. */\nexport const verdict_schema = z.object({\n verdict: z.enum(['approved', 'changes_requested']),\n feedback: z\n .string()\n .nullable()\n .transform((feedback) => feedback ?? '')\n .describe(\n 'Free-form markdown for the builder. Concrete and actionable. ' +\n 'Will be passed verbatim into the next iteration.',\n ),\n unmet_criteria: z\n .array(z.string())\n .nullable()\n .transform((unmet) => unmet ?? [])\n .describe(\n 'The specific acceptance criteria judged unmet, verbatim. Empty when approved.',\n ),\n});\n\nexport type VerdictOutput = z.infer<typeof verdict_schema>;\n\nexport type CriticDeps = {\n engine: Engine;\n config: ResolvedConfig;\n on_chunk: (chunk: StreamChunk) => void;\n /** Tools to hand the critic's tool-bearing call in place of volley's reads;\n * absent, it gets those. A `claude_cli` critic reads through the CLI's own\n * tools and never takes these. The critic takes no approval handler, since\n * nothing it reads with should ever ask. */\n tools?: ReadonlyArray<Tool>;\n /** Which set `tools` is, so the harness append names the reads the critic\n * holds; absent, volley's own. */\n tool_set?: ToolSet;\n};\n\n/** Read-only tool wiring per provider. The claude_cli critic is confined at\n * the CLI permission layer (allowlist + explicit disallow); every other critic,\n * local or `openrouter`, gets volley's own workspace-scoped read-only tools (or\n * the set the caller injected in their place) and no write path at all.\n *\n * The providers also enforce `verdict_schema` by different paths, the first\n * two verified live. The claude_cli critic compiles the schema for\n * `claude --json-schema`; that only works because fascicle 0.14.0's\n * `compile_schema` strips the top-level `$schema`/`$id` that zod v4 stamps (the\n * CLI rejects them) — `live_smoke` asserts a structured verdict comes back, so a\n * future fascicle regression there fails loudly rather than silently. The local\n * (ollama/lmstudio) critic instead gets Ollama **constrained decode** —\n * fascicle's ai_sdk default whenever a `schema` is passed — so the verdict is\n * structurally guaranteed at decode time, with no prompt-parse-repair;\n * `live_local_builder` exercises that path. Unchanged in v3: on ai_sdk\n * constrained decode needs no wiring, and under the deferred native flip it\n * would move to `provider_options.ollama.format` (parked). An `openrouter`\n * critic rides fascicle's native OpenAI-compatible core, which has no\n * constrained decode: the schema travels in the prompt, and the reply is parsed\n * and repaired. */\nfunction critic_tool_options(\n config: ResolvedConfig,\n tools?: ReadonlyArray<Tool>,\n): Pick<GenerateOptions<VerdictOutput>, 'tools' | 'provider_options' | 'max_steps'> {\n if (config.critic_provider === 'claude_cli') {\n return {\n provider_options: {\n claude_cli: {\n allowed_tools: [...CRITIC_ALLOWED_TOOLS],\n extra_args: ['--disallowedTools', CRITIC_DISALLOWED_TOOLS],\n },\n },\n };\n }\n // Read the builder's actual output: under `--worktree` that lives in\n // the worktree, so the local critic's read tools resolve through the same\n // re-pointed containment root as the builder's writes.\n return {\n tools:\n tools === undefined\n ? read_only_tools(build_root(config.workspace, config.worktree))\n : [...tools],\n max_steps: CRITIC_MAX_STEPS,\n };\n}\n\n/** The local critic's step budget for its tool-bearing call: reads plus the\n * verdict. Set explicitly rather than inherited from fascicle's engine default\n * (also 10), so a change to that default can't move it silently. */\nexport const CRITIC_MAX_STEPS = 10;\n\n/** Degradation ladder rung 1: how many times a local critic's call\n * is retried on a provider stream death before the ladder moves on. Capped at\n * one — the qwen3.6/Ollama tool-XML parser death is stochastic, so a same-call\n * retry often passes; past one attempt the failure is not transient and the\n * tool-less fallback must take over. */\nexport const MAX_CRITIC_RETRIES = 1;\n\n/** Is this critic failure the transient provider stream death the ladder\n * retries? Every provider but `claude_cli` (that path is proven and its\n * retries cost real money), and fascicle's typed `provider_error` only (no\n * message string-matching). A user abort never gets here: `retry` and\n * `fallback` pass control-flow signals through untouched, and `retry` checks the\n * signal before every attempt, so an abort stays exit-130. */\nfunction is_retryable_critic_error(config: ResolvedConfig, err: unknown): boolean {\n if (config.critic_provider === 'claude_cli') return false;\n return error_kind(err) === 'provider_error';\n}\n\n/** Did a schema call end without a verdict because the tool loop ran out —\n * its step budget spent, or its last turn a tool call — rather than because\n * the response was cut off or blocked? fascicle throws\n * `incomplete_generation_error` for every such finish; only these two are\n * fixed by taking the tools away. Matched on `kind` and `finish_reason`. */\nfunction is_step_exhaustion(err: unknown): boolean {\n if (error_kind(err) !== 'incomplete_generation_error') return false;\n const finish = (err as { finish_reason?: unknown }).finish_reason;\n return finish === 'max_steps' || finish === 'tool_calls';\n}\n\n/** Does this failure send a local critic to the tool-less rung? A stream death\n * the retry rung gave up on, or step exhaustion, which no retry would fix. A\n * `length` or `content_filter` finish is neither, and stays fatal. */\nfunction is_degradable_critic_error(config: ResolvedConfig, err: unknown): boolean {\n if (config.critic_provider === 'claude_cli') return false;\n return error_kind(err) === 'provider_error' || is_step_exhaustion(err);\n}\n\n/** fascicle's `provider_error.cause_kind` is `... | undefined`; fold the\n * missing case into `'unknown'` so a recorded retry always names a cause. */\nfunction retry_cause_kind_of(err: unknown): CauseKind {\n const cause = (err as { cause_kind?: unknown }).cause_kind;\n return cause === 'provider_5xx' || cause === 'network' ? cause : 'unknown';\n}\n\n/** Bookkeeping stamped onto a critic record by the degradation ladder: how many\n * tool-bearing retries preceded this verdict, the last retry's cause, and — on the\n * tool-less rung — the `critic_degraded` mark. */\ntype LadderMark = {\n retries: number;\n retry_cause_kind: CauseKind | undefined;\n critic_degraded?: boolean;\n degrade_cause?: DegradeCause;\n};\n\n/** Fold a successful critic `generate` result into loop state, stamping the\n * ladder bookkeeping onto the critic record. Shared by the tool-bearing path and\n * the tool-less fallback so both shape the record identically (the fallback just\n * adds `critic_degraded: true`). */\nfunction finalize_critic(\n state: LoopState,\n result: GenerateResult<VerdictOutput>,\n model: string,\n mark: LadderMark,\n duration_ms: number,\n): LoopState {\n const next = accumulate(state, 'critic', result, model, duration_ms);\n return {\n ...next,\n critic:\n next.critic === null\n ? null\n : {\n ...next.critic,\n retries: mark.retries,\n ...(mark.retry_cause_kind !== undefined\n ? { retry_cause_kind: mark.retry_cause_kind }\n : {}),\n ...(mark.critic_degraded === true ? { critic_degraded: true } : {}),\n ...(mark.degrade_cause !== undefined ? { degrade_cause: mark.degrade_cause } : {}),\n },\n verdict: result.content.verdict,\n feedback: result.content.feedback,\n unmet_criteria: result.content.unmet_criteria,\n };\n}\n\n/** The tool-less fallback's prompt: the normal critic prompt plus a notice that\n * read tools are gone this pass and a paths+sizes workspace inventory, so\n * the critic still judges from the criteria, the raw check artifacts already in\n * the prompt, and the file layout — grounded, just shallower. */\nexport function toolless_critic_prompt(config: ResolvedConfig, tool_prompt: string): string {\n return [\n tool_prompt,\n '',\n 'NOTE: file-read tools are unavailable for this review. Judge from the',\n 'acceptance criteria, the deterministic check output above, and the workspace',\n 'file inventory below (paths and sizes only — file contents are not shown).',\n '',\n 'WORKSPACE FILE INVENTORY',\n '------------------------',\n workspace_inventory(build_root(config.workspace, config.worktree)),\n ].join('\\n');\n}\n\n/** What the critic arm answers with: the call that produced the verdict, and\n * how the ladder reached it. */\nexport type CriticAnswer = {\n result: GenerateResult<VerdictOutput>;\n mark: LadderMark;\n};\n\n/** The critic's model boundary: the whole degradation ladder behind one step\n * (composed in `../flow.ts`). */\nexport type CriticStep = Step<string, CriticAnswer>;\n\n/** One critic call returning the validated verdict in its `GenerateResult`. */\nexport type CriticCall = Step<string, GenerateResult<VerdictOutput>>;\n\nfunction critic_call_config(deps: CriticDeps) {\n const { config } = deps;\n return {\n engine: deps.engine,\n provider: config.critic_provider,\n model: config.critic_model,\n system: resolve_critic_prompt(config, deps.tool_set),\n schema: verdict_schema,\n on_chunk: deps.on_chunk,\n };\n}\n\n/** Rung 1's leaf: the critic with its read tools (or the CLI's read-only\n * allowlist). */\nexport function make_critic_tools_step(deps: CriticDeps): CriticCall {\n return model_call({\n ...critic_call_config(deps),\n id: 'critic_tools',\n description: 'model call with read-only workspace tools',\n ...critic_tool_options(deps.config, deps.tools),\n });\n}\n\n/** Rung 2's leaf: the same critic with no tools at all, so nothing enters\n * Ollama's broken tool parser; constrained decode (`schema`) still guarantees\n * the verdict. */\nexport function make_critic_toolless_step(deps: CriticDeps): CriticCall {\n return model_call({\n ...critic_call_config(deps),\n id: 'critic_toolless',\n description: 'model call judging from the check output and a file list',\n });\n}\n\n/** What the retry rung knew about the error that ended it: the attempt it\n * died on, and the cause of the stream death it last retried. fascicle's\n * `retry` rethrows that error untouched, so the fallback's projection looks it\n * up here to count the retries behind a degraded verdict. */\ntype LadderTrace = { attempt: number; retried_cause: CauseKind | undefined };\n\nconst ladder_traces = new WeakMap<object, LadderTrace>();\n\n/** The ladder's retry predicate for this run's critic provider: stream deaths\n * only. It also traces every failure it sees, so a degraded verdict can say how\n * many retries preceded it and why. A first attempt starts a fresh critique, so\n * it forgets the last one's retries. */\nexport function critic_retryable(\n config: ResolvedConfig,\n): (err: unknown, attempt: number) => boolean {\n let retried_cause: CauseKind | undefined;\n return (err, attempt) => {\n if (attempt === 1) retried_cause = undefined;\n if (typeof err === 'object' && err !== null) {\n ladder_traces.set(err, { attempt, retried_cause });\n }\n const retryable = is_retryable_critic_error(config, err);\n if (retryable) retried_cause = retry_cause_kind_of(err);\n return retryable;\n };\n}\n\n/** The ladder's fallback predicate: a stream death the retry rung gave up on,\n * or step exhaustion, which it never retries. */\nexport function critic_degradable(config: ResolvedConfig): (err: unknown) => boolean {\n return (err) => is_degradable_critic_error(config, err);\n}\n\n/** Rung 1's projection: a verdict the tool-bearing critic produced, marked with\n * how many stream deaths it took and the last one's cause. */\nexport function with_retries(outcome: RetryOutcome<GenerateResult<VerdictOutput>>): CriticAnswer {\n const last = outcome.errors.at(-1);\n return {\n result: outcome.value,\n mark: {\n retries: outcome.attempts - 1,\n retry_cause_kind: last === undefined ? undefined : retry_cause_kind_of(last),\n },\n };\n}\n\n/** Rung 2's answer, marked degraded so it never passes silently as a full\n * critique. Why it degraded, and the retries before it, are the ladder's to\n * stamp (`with_fallback_cause`), since the tool-less call can't see them. */\nexport function as_degraded(result: GenerateResult<VerdictOutput>): CriticAnswer {\n return {\n result,\n mark: { retries: 0, retry_cause_kind: undefined, critic_degraded: true },\n };\n}\n\n/** The ladder's projection: the tool-less backup cannot see why it ran, so the\n * mark comes from the error that sent it there.\n *\n * - A stream death the retry rung gave up on: every retry was spent, and the\n * cause is that error's own.\n * - Step exhaustion, never retried: the retries are the stream deaths before\n * it, usually none, and the cause is the last of those.\n *\n * An error the retry rung never traced reads as one that spent every retry. */\nexport function with_fallback_cause(outcome: FallbackOutcome<CriticAnswer>): CriticAnswer {\n if (outcome.source === 'primary') return outcome.value;\n const err = outcome.primary_error;\n const trace =\n typeof err === 'object' && err !== null ? ladder_traces.get(err) : undefined;\n const retries = trace === undefined ? MAX_CRITIC_RETRIES : trace.attempt - 1;\n const exhausted = is_step_exhaustion(err);\n const retry_cause_kind = exhausted ? trace?.retried_cause : retry_cause_kind_of(err);\n return {\n ...outcome.value,\n mark: {\n ...outcome.value.mark,\n retries,\n retry_cause_kind,\n degrade_cause: exhausted ? 'step_exhaustion' : 'stream_error',\n },\n };\n}\n\n/** What the `--dry-run` canary learned about the critic seat:\n * `ok` — the tool-bearing call came back; `degraded` — the tool-bearing\n * call died on a provider stream error or ran out of steps, but a tool-less\n * pass survived, so a real run will likely finish via the fallback ladder\n * (`critic_degraded`);\n * `failed` — even the tool-less pass died, so the combo would fail a real run\n * degraded or not. */\nexport type CanaryOutcome =\n | { outcome: 'ok' }\n | { outcome: 'degraded'; detail: string }\n | { outcome: 'failed'; detail: string };\n\n/** The canary must *elicit a real tool call*: the qwen3.6 death happens at\n * tool-markup emission inside Ollama's server-side parser, so a call that never\n * invokes a tool could not fail and would prove nothing. The target path need\n * not exist — a tool error is fed back and the model answers anyway; entering\n * the parser is the test. No token cap: the budget is behavioral (one tool call,\n * then an immediate one-word verdict), because a hard `max_tokens` could\n * truncate a thinking model mid-verdict and report `failed` for a combo that\n * works. A model that skips the tool and just answers passes stochastically —\n * acceptable: the canary is early warning, the ladder is the guarantee. */\nconst CANARY_PROMPT = [\n 'CANARY CHECK — a tiny wiring probe, not a real review.',\n 'First, call the read_file tool on the path \"package.json\".',\n 'Whatever the tool returns (content or an error), immediately answer with',\n 'verdict \"approved\", feedback exactly \"canary\", and empty unmet_criteria.',\n].join('\\n');\n\n/** The canary's tool-less rung: same schema-constrained call, no tool ask. */\nconst CANARY_TOOLLESS_PROMPT = [\n 'CANARY CHECK — a tiny wiring probe, not a real review.',\n 'Answer with verdict \"approved\", feedback exactly \"canary\", and empty',\n 'unmet_criteria.',\n].join('\\n');\n\nfunction canary_detail(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * The `--dry-run` critic-seat canary: one tiny generate through the *real*\n * production tool wiring (`critic_tool_options`) and `verdict_schema`, $0 on a\n * local model. The caller (preflight) gates it to local critics only —\n * `claude_cli` is proven, and its calls and `openrouter`'s cost real money.\n *\n * A tool-bearing death is classified by the same discriminant as the run-time\n * ladder's fallback (a typed `provider_error`, or step exhaustion), then probed\n * tool-less exactly as rung 2 would run, so the canary *predicts the ladder*\n * instead of guessing:\n * tool-less survives → `degraded` (warn — the combo completes a real run,\n * marked); tool-less dies too → `failed` (the endpoint-down / model-missing\n * class that earns exit 5 because not even degradation would save it).\n */\nexport async function critic_canary(\n engine: Engine,\n config: ResolvedConfig,\n env: Record<string, string | undefined> = process.env,\n): Promise<CanaryOutcome> {\n // Same cold-load guard as the real critic phase: without it a disk-cold model\n // would die on the first-byte timeout and the canary would cry wolf.\n if (config.critic_provider === 'ollama') {\n await prewarm_ollama_model(\n seat_base_url('ollama', config.critic_url, env),\n config.critic_model,\n );\n }\n const base: Omit<GenerateOptions<VerdictOutput>, 'prompt' | 'tools' | 'provider_options'> = {\n provider: config.critic_provider,\n model: config.critic_model,\n system: resolve_critic_prompt(config),\n schema: verdict_schema,\n };\n try {\n await engine.generate({\n ...base,\n prompt: CANARY_PROMPT,\n ...critic_tool_options(config),\n });\n return { outcome: 'ok' };\n } catch (err) {\n if (!is_degradable_critic_error(config, err)) {\n return { outcome: 'failed', detail: canary_detail(err) };\n }\n const tool_death = canary_detail(err);\n try {\n await engine.generate({ ...base, prompt: CANARY_TOOLLESS_PROMPT });\n return { outcome: 'degraded', detail: tool_death };\n } catch (fallback_err) {\n return { outcome: 'failed', detail: canary_detail(fallback_err) };\n }\n }\n}\n\nexport type CriticRunDeps = {\n critic: CriticStep;\n config: ResolvedConfig;\n};\n\nexport async function run_critic(\n deps: CriticRunDeps,\n state: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config } = deps;\n if (state.check === null) {\n throw phase_error('critic', state.iteration, new Error('check phase did not run'));\n }\n const check = state.check;\n try {\n // Same cold-load guard as the builder: pre-load an Ollama critic model on\n // the critic seat's own server so a cold multi-GB load doesn't blow the real\n // call's first-byte timeout. Best-effort; when both seats share a server and\n // a model, the builder's warm-up already loaded it and this returns at once.\n if (config.critic_provider === 'ollama') {\n await prewarm_ollama_model(\n seat_base_url('ollama', config.critic_url, process.env),\n config.critic_model,\n ctx.abort,\n );\n }\n const prompt = compose_critic_prompt({\n criteria: config.criteria,\n iteration: state.iteration,\n check,\n changes: state.changes,\n });\n // The phase's duration spans every rung that ran, not just the call that\n // answered: a retried or degraded verdict took that long to get, and no one\n // result's `timing` covers the attempts before it.\n const started = Date.now();\n const { result, mark } = await ctx.call(deps.critic, prompt);\n return finalize_critic(state, result, config.critic_model, mark, Date.now() - started);\n } catch (err) {\n throw phase_error('critic', state.iteration, err);\n }\n}\n","/**\n * Display formatting: glyph taxonomy, role colors, truncation.\n * All human output goes to stderr; these helpers only build strings.\n */\nimport pc from 'picocolors';\n\nexport const GLYPH_TOOL = '🔧';\nexport const GLYPH_OK = '✅';\nexport const GLYPH_ERR = '❌';\nexport const GLYPH_COST = '💰';\nexport const GLYPH_PHASE_START = '▶';\nexport const GLYPH_PHASE_OK = '✓';\nexport const GLYPH_PHASE_FAIL = '✗';\n\nexport const VERBOSE_TRUNCATE_CHARS = 4000;\n\nexport type Role = 'builder' | 'critic' | 'check';\n\nexport function colors_enabled(\n env: Record<string, string | undefined> = process.env,\n is_tty: boolean = process.stderr.isTTY === true,\n): boolean {\n if (env['NO_COLOR'] !== undefined || env['VOLLEY_NO_COLOR'] !== undefined) {\n return false;\n }\n return is_tty;\n}\n\nexport function paint(role: Role | 'cost' | 'error', text: string, color: boolean): string {\n if (!color) return text;\n switch (role) {\n case 'builder':\n return pc.cyan(text);\n case 'critic':\n return pc.yellow(text);\n case 'check':\n return pc.green(text);\n case 'cost':\n return pc.magenta(text);\n case 'error':\n return pc.bold(pc.red(text));\n }\n}\n\nexport function dim(text: string, color: boolean): string {\n return color ? pc.dim(text) : text;\n}\n\nexport function truncate(text: string, max: number, pointer: string): string {\n if (text.length <= max) return text;\n return `${text.slice(0, max)}\\n… [truncated at ${String(max)} chars; ${pointer}]`;\n}\n\n/** Controls, format characters (bidi overrides, zero-widths), and line and\n * paragraph separators: what can move the cursor, hide text, or reorder a line\n * in a terminal. */\nconst UNSAFE_CHARACTERS = /[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}]/gu;\n\n/** A value from a file volley can't vouch for, quoted for a person to judge,\n * with every character that could redraw or reorder the line escaped, so a\n * rewritten config can't make the warning about it say something else. JSON\n * quoting escapes the C0 controls, the quote, and the backslash; the rest are\n * written as `\\u{…}`. */\nexport function shown(value: string): string {\n return JSON.stringify(value).replace(\n UNSAFE_CHARACTERS,\n (character) => `\\\\u{${(character.codePointAt(0) ?? 0).toString(16)}}`,\n );\n}\n\nexport function format_usd(value: number | null): string {\n return value === null ? '$?' : `$${value.toFixed(3)}`;\n}\n\n/** One-line summary of a tool input for the default streaming mode. */\nexport function summarize_value(value: unknown, max = 120): string {\n let text: string;\n try {\n text = typeof value === 'string' ? value : JSON.stringify(value) ?? '';\n } catch {\n text = String(value);\n }\n const flat = text.replace(/\\s+/g, ' ');\n return flat.length > max ? `${flat.slice(0, max)}…` : flat;\n}\n","/**\n * Iteration archiving, run-level summary, and resume-state recovery.\n * `feedback.md` and `verdict` are harness-written projections\n * of the critic's validated structured output.\n */\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { basename, join, resolve } from 'node:path';\nimport { read_failing_artifacts } from './check/checkride.js';\nimport type { CheckrideSummary, CheckrideSummaryCheck } from './check/checkride.js';\nimport { EMPTY_USAGE } from './cost.js';\nimport { shown } from './render/format.js';\nimport { config_error } from './types.js';\nimport type {\n BuilderPermissionMode,\n BuilderProvider,\n CheckArtifact,\n CheckResult,\n CriticProvider,\n LoopState,\n PhaseRecord,\n ResolvedConfig,\n RunResult,\n RunStatus,\n Verdict,\n VolleyConfig,\n} from './types.js';\nimport { detect_containment } from './containment.js';\nimport { config_signed } from './trust.js';\nimport {\n CONFIG_SIGNATURE,\n iteration_dir,\n RUN_ID_PATTERN,\n run_state_dir,\n state_path,\n} from './workspace.js';\nimport type { StateLocation } from './workspace.js';\n\nfunction write_json(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction persist_verdict_files(\n config: ResolvedConfig,\n feedback: string,\n verdict: Verdict,\n): void {\n writeFileSync(state_path(config, 'feedback.md'), feedback.endsWith('\\n') ? feedback : `${feedback}\\n`);\n writeFileSync(state_path(config, 'verdict'), `${verdict}\\n`);\n}\n\nfunction phase_summary(record: PhaseRecord | null): Record<string, unknown> | null {\n if (record === null) return null;\n return {\n provider: record.provider,\n model: record.model,\n session_id: record.session_id,\n duration_ms: record.duration_ms,\n usage: record.usage,\n cost_usd: record.cost_usd,\n cost_source: record.cost_source,\n finish_reason: record.finish_reason,\n tool_calls: record.tool_calls,\n salvaged_tool_calls: record.salvaged_tool_calls,\n // Salvage rate (a health metric): the share of tool calls recovered from\n // assistant text. A high rate on a local run means the model's native\n // tool-call encoding is drifting from its runtime's parser (pin them as one\n // unit). 0 when the phase made no tool calls (the CLI builder's own loop).\n salvage_rate: record.tool_calls === 0 ? 0 : record.salvaged_tool_calls / record.tool_calls,\n // Turns cut off at the builder's output cap before a tool call. Emitted\n // only when there were any. Additive.\n ...(record.truncated_turns !== undefined ? { truncated_turns: record.truncated_turns } : {}),\n // Degradation-ladder bookkeeping, critic-only: the provider-error\n // retries that preceded this verdict, their cause, whether it was rendered\n // by the tool-less fallback, and why. Emitted only when set, so the builder\n // record and old summary consumers are untouched. `critic_degraded` and\n // `degrade_cause` are the on-disk half of the contract — the comparison\n // block reads them back from here.\n ...(record.retries !== undefined ? { retries: record.retries } : {}),\n ...(record.retry_cause_kind !== undefined\n ? { retry_cause_kind: record.retry_cause_kind }\n : {}),\n ...(record.critic_degraded === true ? { critic_degraded: true } : {}),\n ...(record.degrade_cause !== undefined ? { degrade_cause: record.degrade_cause } : {}),\n // Model speed, where fascicle could time the turns (never `claude_cli`).\n // Emitted only when measured. Additive.\n ...(record.throughput !== undefined ? { throughput: record.throughput } : {}),\n };\n}\n\n/** Archive one completed iteration: verdict files, check artifacts, and the\n * per-iteration summary. */\nexport function archive_iteration(config: ResolvedConfig, state: LoopState): void {\n const dir = iteration_dir(config, state.iteration);\n mkdirSync(join(dir, 'check'), { recursive: true });\n\n if (state.verdict !== null && state.feedback !== null) {\n persist_verdict_files(config, state.feedback, state.verdict);\n writeFileSync(join(dir, 'feedback.md'), readFileSync(state_path(config, 'feedback.md')));\n writeFileSync(join(dir, 'verdict'), `${state.verdict}\\n`);\n }\n\n const check = state.check;\n if (check !== null && check.ran) {\n if (check.runner === 'checkride') {\n if (check.summary !== undefined) {\n write_json(join(dir, 'check', 'summary.json'), check.summary);\n }\n for (const artifact of check.detail) {\n if (artifact.path !== null && existsSync(artifact.path)) {\n writeFileSync(join(dir, 'check', basename(artifact.path)), readFileSync(artifact.path));\n }\n }\n if (check.digest !== undefined) {\n writeFileSync(join(dir, 'check', 'digest.md'), check.digest);\n }\n // A checkride check has a log only when it was rejected, and the log\n // says so.\n if (check.log !== undefined) {\n writeFileSync(join(dir, 'check', 'check.log'), check.log);\n }\n } else {\n writeFileSync(join(dir, 'check', 'check.log'), check.log ?? '');\n writeFileSync(join(dir, 'check', 'check.exit'), `${String(check.exit_code)}\\n`);\n }\n }\n\n const completed_at = new Date().toISOString();\n write_json(join(dir, 'summary.json'), {\n iteration: state.iteration,\n started_at: state.iteration_started_at,\n completed_at,\n duration_ms: Date.parse(completed_at) - Date.parse(state.iteration_started_at),\n builder: phase_summary(state.builder),\n check:\n check === null\n ? null\n : {\n ran: check.ran,\n runner: check.runner,\n ok: check.ok,\n exit_code: check.exit_code,\n duration_ms: check.duration_ms,\n failing_slots: check.failing_slots,\n },\n critic: phase_summary(state.critic),\n // What the builder reached for this iteration (`src/changes.ts`), archived\n // beside the check's verdict so the two can be read against each other after\n // the fact: green + a gate edit is a different result from green alone.\n // Null when the build root is not a git repository. Additive.\n changes: state.changes,\n verdict: state.verdict,\n // The criteria the critic judged unmet, verbatim. The run-level summary\n // reads the last iteration's list, so a non-converged run says what it was\n // still missing when it stopped instead of only that it stopped. Additive.\n unmet_criteria: state.unmet_criteria,\n iteration_cost_usd: state.iteration_cost_usd,\n iteration_total_cost_usd: state.total_cost_usd,\n });\n}\n\nexport function run_result_from_state(\n config: ResolvedConfig,\n state: LoopState,\n status: RunStatus,\n completed_at: string | null,\n): RunResult {\n return {\n run_id: config.run_id,\n status,\n started_at: config.started_at,\n completed_at,\n iterations_completed: state.iteration,\n total_usage: state.total_usage,\n total_cost_usd: state.total_cost_usd,\n builder_cost_usd: state.builder_cost_usd,\n critic_cost_usd: state.critic_cost_usd,\n check_duration_ms: state.check_duration_ms,\n builder_max_steps_hits: state.builder_max_steps_hits,\n final_verdict: state.verdict,\n // The loop itself never salvages: the orchestrator re-stamps this after\n // teardown when a converged `--worktree` run's work was kept on its branch,\n // which is the only moment the branch's survival is known.\n salvaged_branch: null,\n run_state_dir: run_state_dir(config),\n mode: config.mode,\n };\n}\n\nexport type ResumeState = {\n raw_config: VolleyConfig;\n run_id: string;\n started_at: string;\n state: LoopState;\n iterations_completed: number;\n /** Whether this machine's signature held over the run's config: false only\n * when `trust_config` let an unsigned one through, and null inside the\n * sandbox, where nothing is checked. */\n config_signed: boolean | null;\n};\n\nexport type ResumeOptions = {\n /** Resume a config this machine didn't sign (`--trust-config`): another\n * machine's, an older volley's, one edited by hand, or a contained run's,\n * whose builder could have rewritten it. */\n trust_config?: boolean;\n env?: Readonly<Record<string, string | undefined>>;\n};\n\n/** Why a host-side resume won't run a config this machine didn't sign. */\nfunction untrusted_config(run_id: string, config_path: string): Error {\n return config_error(\n `run ${run_id}'s config.json has no signature from volley on this machine, so a resume here ` +\n \"won't run it: inside the sandbox a run's builder can rewrite its config, and a resume runs \" +\n 'the check and the seats it names. Resume a contained run inside its container, with the same ' +\n `mount. If ${config_path} is another machine's, an older volley's, or one you edited, read it, ` +\n 'then pass --trust-config.',\n );\n}\n\n/** Whether a host-side resume may run the config in `text`: signed by this\n * machine, or trusted by the caller. Inside the sandbox nothing is checked: a\n * resume there runs only within the container, as the builder already does. */\nfunction check_config_trust(\n text: string,\n run: StateLocation,\n options: ResumeOptions,\n): boolean | null {\n const env = options.env ?? process.env;\n if (detect_containment(env)) return null;\n const signature_path = state_path(run, CONFIG_SIGNATURE);\n const signature = existsSync(signature_path) ? readFileSync(signature_path, 'utf8') : null;\n const signed = config_signed(text, signature, env);\n if (!signed && options.trust_config !== true) {\n throw untrusted_config(run.run_id, state_path(run, 'config.json'));\n }\n return signed;\n}\n\n/** The run id an older volley's `.volley/config.json` records, or null when\n * there is none to read. */\nfunction legacy_run_id(workspace: string): string | null {\n try {\n const recorded = JSON.parse(readFileSync(join(workspace, '.volley', 'config.json'), 'utf8')) as {\n run_id?: unknown;\n };\n return typeof recorded.run_id === 'string' ? recorded.run_id : null;\n } catch {\n return null;\n }\n}\n\n/** Where `volley resume <run_id>` finds a run: under `root` (`--state-dir`,\n * else the default root) at `<root>/<run_id>/`, returned as that root, or, for\n * a run an older volley kept in the workspace, `.volley/`, returned as null so\n * the resumed run stays there. Finding neither is a config error naming both\n * places it looked. The id becomes a path, so it must be one a run could have\n * had. */\nexport function find_run_state(workspace: string, run_id: string, root: string): string | null {\n if (!RUN_ID_PATTERN.test(run_id)) {\n throw config_error(`not a run id: ${run_id} (letters, digits, '-', and '_', starting with a letter or digit)`);\n }\n if (existsSync(join(root, run_id, 'config.json'))) return root;\n const legacy = legacy_run_id(workspace);\n if (legacy === run_id) return null;\n // Read from a file nothing has vouched for, so quoted and escaped.\n const holds = legacy === null ? '' : ` (it holds run ${shown(legacy)})`;\n throw config_error(\n `run ${run_id} not found in ${join(root, run_id)} or in ${join(resolve(workspace), '.volley')}${holds}; ` +\n 'pass --state-dir for the root it ran under, or --workspace for a run kept in .volley/',\n );\n}\n\n/** A resumed run writes into its state directory, and a contained run's\n * builder could have written there first, so a symlink anywhere in it would\n * aim the resume's writes, or its pruning of a half-finished iteration, at a\n * file of the host's. volley never makes one, so any is refused. The walk\n * reads each entry's own type and never descends a link, which Node's\n * recursive `readdirSync` would. */\nfunction refuse_symlinks(dir: string): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isSymbolicLink()) {\n throw config_error(`refusing to resume: ${path} is a symbolic link, which volley never writes`);\n }\n if (entry.isDirectory()) refuse_symlinks(path);\n }\n}\n\n/** The part of an archived iteration's `summary.json` a resumed run reads\n * back. Every field is unknown until checked, since the archive could be torn\n * or older than this volley. */\ntype ArchivedRound = {\n builder?: unknown;\n check?: {\n ran?: unknown;\n runner?: unknown;\n ok?: unknown;\n exit_code?: unknown;\n duration_ms?: unknown;\n failing_slots?: unknown;\n } | null;\n};\n\n/** An archived file's text, or undefined when there's no file to read there. */\nfunction read_text(path: string): string | undefined {\n try {\n return readFileSync(path, 'utf8');\n } catch {\n return undefined;\n }\n}\n\nfunction read_json(path: string): unknown {\n const text = read_text(path);\n if (text === undefined) return null;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return null;\n }\n}\n\n/** The failing slots' raw artifacts from an archived iteration's `check/`,\n * which holds each under its base name, found through the archived checkride\n * summary. */\nfunction archived_artifacts(check_dir: string, failing_slots: string[]): CheckArtifact[] {\n const summary = read_json(join(check_dir, 'summary.json')) as Partial<CheckrideSummary> | null;\n const checks = Array.isArray(summary?.checks) ? summary.checks : [];\n const failing = failing_slots.map((name): CheckrideSummaryCheck => {\n const output_file = checks.find((check) => check.name === name)?.output_file;\n return {\n name,\n adapter: null,\n ok: false,\n exit_code: null,\n duration_ms: 0,\n output_file: typeof output_file === 'string' ? basename(output_file) : null,\n };\n });\n return read_failing_artifacts(check_dir, failing);\n}\n\n/** The check an archived iteration ran, rebuilt from its directory with the\n * output its failure is shown by: the digest and the failing slots' artifacts\n * for checkride, the log for a command or a rejected check. Null when it ran\n * none. */\nfunction archived_check(dir: string, recorded: ArchivedRound['check']): CheckResult | null {\n if (recorded?.ran !== true || typeof recorded.ok !== 'boolean') return null;\n const runner = recorded.runner === 'checkride' ? 'checkride' : 'command';\n const failing_slots = Array.isArray(recorded.failing_slots)\n ? recorded.failing_slots.filter((slot): slot is string => typeof slot === 'string')\n : [];\n const check: CheckResult = {\n ran: true,\n runner,\n ok: recorded.ok,\n exit_code: typeof recorded.exit_code === 'number' ? recorded.exit_code : null,\n duration_ms: typeof recorded.duration_ms === 'number' ? recorded.duration_ms : 0,\n failing_slots,\n detail: [],\n };\n if (check.ok) return check;\n const check_dir = join(dir, 'check');\n const log = read_text(join(check_dir, 'check.log'));\n const logged = log === undefined ? check : { ...check, log };\n if (runner === 'command') return logged;\n const digest = read_text(join(check_dir, 'digest.md'));\n return {\n ...logged,\n detail: archived_artifacts(check_dir, failing_slots),\n ...(digest !== undefined ? { digest } : {}),\n };\n}\n\n/** An archived builder record, as `archive_iteration` wrote it from the\n * phase's own, or null when there is none with a finish reason. */\nfunction archived_builder(recorded: unknown): PhaseRecord | null {\n if (typeof recorded !== 'object' || recorded === null) return null;\n return typeof (recorded as Partial<PhaseRecord>).finish_reason === 'string'\n ? (recorded as PhaseRecord)\n : null;\n}\n\n/** What the last completed iteration left for the next build: its check and\n * its builder's record, which tell the resumed run's first builder what the\n * gate said and whether the last session ran out of steps, as a run that never\n * stopped would have. Null for both before the first iteration. */\nfunction archived_round(\n run: StateLocation,\n completed: number,\n): Pick<LoopState, 'check' | 'builder'> {\n if (completed === 0) return { check: null, builder: null };\n const dir = iteration_dir(run, completed);\n const recorded = read_json(join(dir, 'summary.json')) as ArchivedRound | null;\n return {\n check: archived_check(dir, recorded?.check),\n builder: archived_builder(recorded?.builder),\n };\n}\n\n/** Recover a resumable run from its state directory (`.volley/`, or\n * `<state_dir>/<run_id>/` under a state root): settings from config.json,\n * totals from summary.json, feedback from feedback.md. An iteration directory\n * without a summary.json was interrupted mid-phase and is discarded. A\n * directory with a symlink in it is refused before anything is read. */\nexport function load_resume_state(\n workspace: string,\n run_id: string,\n state_dir: string | null = null,\n options: ResumeOptions = {},\n): ResumeState {\n const run = { workspace, state_dir, run_id };\n const run_dir = run_state_dir(run);\n if (existsSync(run_dir)) {\n if (lstatSync(run_dir).isSymbolicLink()) {\n throw config_error(`refusing to resume: ${run_dir} is a symbolic link, which volley never writes`);\n }\n refuse_symlinks(run_dir);\n }\n const config_path = state_path(run, 'config.json');\n if (!existsSync(config_path)) {\n throw config_error(`no resumable run found: ${config_path} missing`);\n }\n const config_text = readFileSync(config_path, 'utf8');\n const signed = check_config_trust(config_text, run, options);\n const recorded = JSON.parse(config_text) as Record<string, unknown>;\n if (recorded['run_id'] !== run_id) {\n throw config_error(\n `run ${run_id} not found in ${run_state_dir(run)} (recorded run: ${String(recorded['run_id'])})`,\n );\n }\n if (recorded['mode'] === 'critique') {\n throw config_error(\n `run ${run_id} is a critique, which has one round and nothing to resume; run volley critique again`,\n );\n }\n\n const iterations_root = state_path(run, 'iterations');\n const dirs = existsSync(iterations_root)\n ? readdirSync(iterations_root).filter((d) => /^\\d{3}$/.test(d)).toSorted()\n : [];\n let completed = 0;\n for (const dir of dirs) {\n const full = join(iterations_root, dir);\n if (existsSync(join(full, 'summary.json'))) {\n completed = Number(dir);\n } else {\n rmSync(full, { recursive: true, force: true });\n }\n }\n\n const summary_path = state_path(run, 'summary.json');\n const summary = existsSync(summary_path)\n ? (JSON.parse(readFileSync(summary_path, 'utf8')) as RunResult)\n : null;\n\n const feedback_path = state_path(run, 'feedback.md');\n const feedback = existsSync(feedback_path) ? readFileSync(feedback_path, 'utf8') : null;\n\n const raw_config: VolleyConfig = {\n prompt: String(recorded['prompt']),\n workspace: String(recorded['workspace']),\n criteria: String(recorded['criteria']),\n check: String(recorded['check']),\n builder_model: String(recorded['builder_model']),\n builder_provider: (recorded['builder_provider'] ?? 'claude_cli') as BuilderProvider,\n ...(typeof recorded['builder_url'] === 'string'\n ? { builder_url: recorded['builder_url'] }\n : {}),\n ...(recorded['builder_max_steps'] === undefined\n ? {}\n : { builder_max_steps: Number(recorded['builder_max_steps']) }),\n ...(recorded['builder_max_tool_calls'] === undefined\n ? {}\n : { builder_max_tool_calls: Number(recorded['builder_max_tool_calls']) }),\n // Null when the run left it unset, as any run before it was recorded did.\n ...(typeof recorded['builder_max_output_tokens'] === 'number'\n ? { builder_max_output_tokens: recorded['builder_max_output_tokens'] }\n : {}),\n critic_model: String(recorded['critic_model']),\n critic_provider: (recorded['critic_provider'] ?? 'claude_cli') as CriticProvider,\n ...(typeof recorded['critic_url'] === 'string' ? { critic_url: recorded['critic_url'] } : {}),\n builder_permission_mode: recorded['builder_permission_mode'] as BuilderPermissionMode,\n critic:\n recorded['critic_preset'] === 'custom'\n ? String(recorded['critic_prompt_path'])\n : String(recorded['critic_preset']),\n max_iterations: Number(recorded['max_iterations']),\n max_cost_usd: recorded['max_cost_usd'] as number | null,\n git_checkpoints: recorded['git_checkpoints'] === true,\n worktree: recorded['worktree'] === true,\n discard_worktree: recorded['discard_worktree'] === true,\n ...(Array.isArray(recorded['gate_paths'])\n ? { gate_paths: recorded['gate_paths'] as string[] }\n : {}),\n fail_on_gate_edit: recorded['fail_on_gate_edit'] === true,\n ...(recorded['sandbox_image'] === undefined\n ? {}\n : { sandbox_image: recorded['sandbox_image'] as string }),\n ...(typeof recorded['state_dir'] === 'string' ? { state_dir: recorded['state_dir'] } : {}),\n };\n\n const state: LoopState = {\n iteration: completed,\n iteration_started_at: new Date().toISOString(),\n feedback,\n verdict: null,\n unmet_criteria: [],\n ...archived_round(run, completed),\n // Re-measured by the resumed run's first `build` step, against a baseline\n // captured at resume — a resumed run reports what it changes from there.\n changes: null,\n critic: null,\n total_usage: summary?.total_usage ?? EMPTY_USAGE,\n total_cost_usd: summary?.total_cost_usd ?? 0,\n builder_cost_usd: summary?.builder_cost_usd ?? 0,\n critic_cost_usd: summary?.critic_cost_usd ?? 0,\n check_duration_ms: summary?.check_duration_ms ?? 0,\n // An older volley's summary has no count.\n builder_max_steps_hits: summary?.builder_max_steps_hits ?? 0,\n iteration_cost_usd: 0,\n halt: null,\n cost_warned: false,\n };\n\n return {\n raw_config,\n run_id,\n started_at: String(recorded['started_at']),\n state,\n iterations_completed: completed,\n config_signed: signed,\n };\n}\n","/**\n * Enriched run summary (the run's `summary.json`): the `RunResult` projection plus\n * a `comparison` block that makes the two blessed examples' runs diff-able.\n * The block gathers the seven comparison metrics — transport,\n * iterations-to-converge, wall-clock, cost, verdict, the deterministic check\n * trajectory, and the local salvage rate — into one self-contained surface so\n * the model-vs-transport write-up (verification §4) reads them from a single\n * object rather than re-deriving them from the per-iteration archive.\n *\n * This is the only writer of `summary.json`; the flow's `record` step calls it\n * every iteration (status `running`, `completed_at` still null), the orchestrator\n * once more with the final status, and — when a `--worktree` run's work was\n * salvaged onto its branch rather than integrated — a third time, to stamp the\n * surviving branch on `salvaged_branch`, which teardown only names after the\n * final status is known.\n * Each write recomputes the comparison from what is currently archived under\n * the run's `iterations/`, so the trajectory grows as the run does.\n */\nimport { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';\nimport type {\n BuilderProvider,\n CriticProvider,\n DegradeCause,\n ResolvedConfig,\n RunResult,\n Verdict,\n} from './types.js';\nimport { state_path } from './workspace.js';\n\n/** How a role reached the model. volley stays on the `ai_sdk` transport for the\n * local providers (fascicle 0.14.0 defaults `transport` to `'ai_sdk'`, so\n * volley sets no field); `openrouter` runs on fascicle's `native` transport\n * (`src/engine.ts` sets it); `claude_cli` drives Claude through its own CLI\n * subprocess, not an ai-sdk transport at all. Recording each keeps the\n * transport a clean second variable in the comparison (model vs transport). */\nexport type Transport = 'ai_sdk' | 'native' | 'claude_cli';\n\nexport function transport_of(provider: BuilderProvider | CriticProvider): Transport {\n switch (provider) {\n case 'claude_cli':\n return 'claude_cli';\n case 'openrouter':\n return 'native';\n case 'ollama':\n case 'lmstudio':\n return 'ai_sdk';\n }\n}\n\n/** One iteration's deterministic-gate outcome, in run order. */\nexport type CheckTrajectoryPoint = {\n iteration: number;\n ran: boolean;\n ok: boolean;\n failing_slots: string[];\n};\n\n/** Run-level salvage aggregate (a health metric): the share of builder tool\n * calls recovered from assistant text rather than returned structurally. A high\n * rate on a local run means the model's native tool-call encoding is drifting\n * from its runtime's parser. `rate` is 0 when the builder made no tool calls\n * (the `claude_cli` builder runs its own loop and reports none). */\nexport type SalvageStats = {\n tool_calls: number;\n salvaged_tool_calls: number;\n rate: number;\n};\n\n/** The self-contained comparison surface the two blessed examples are read\n * through. Cost and verdict echo the `RunResult` top level on\n * purpose — this block is the single object the write-up diffs, so it carries\n * every comparison metric rather than pointing back out for some of them. */\nexport type ComparisonSummary = {\n /** Null for a critique, which has no builder. */\n builder_transport: Transport | null;\n critic_transport: Transport;\n /** The iteration the run converged on (check green + critic approved); null\n * when it never converged (budget/cap/interrupt/error). */\n iterations_to_converge: number | null;\n /** Total wall-clock across the run; null until `completed_at` is stamped. */\n wall_clock_ms: number | null;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n final_verdict: Verdict | null;\n check_trajectory: CheckTrajectoryPoint[];\n local_salvage: SalvageStats;\n /** Every gate path any iteration's builder edited — the tests, fixtures, and\n * check configuration that decide whether its own work passes (`src/changes.ts`).\n * Empty on a run that only touched the implementation, which is the shape of\n * the by-hand verification `research/reckon-local-run-finding.md` recommends\n * making routine: a green check plus an empty list is worth more than a green\n * check alone. Sorted and de-duplicated across iterations. */\n gate_edits: string[];\n /** What the critic still judged unmet when the run stopped — the last\n * iteration's `unmet_criteria`, verbatim. Empty on a converged run. This is the\n * \"why not\" a non-success status alone cannot give: `budget_exhausted` says the\n * run ran out of iterations, not what it was still missing. */\n unmet_criteria: string[];\n /** Any iteration's critic verdict was rendered by the tool-less fallback:\n * the tool-bearing critique kept dying on the provider's stream, so\n * the critic judged without read access — real, but shallower. The run's\n * headline honesty flag, and the \"degraded\" column the matrix runner\n * reads straight from this block. */\n critic_degraded: boolean;\n /** Why the degraded verdicts degraded, each cause once, in the order the\n * iterations first hit it. Empty when no verdict degraded. Additive. */\n critic_degrade_causes: DegradeCause[];\n};\n\n/** `RunResult` plus the comparison block; the run's `summary.json` mirrors this. */\nexport type RunSummary = RunResult & { comparison: ComparisonSummary };\n\n/** The subset of an archived per-iteration summary (written by\n * `archive_iteration`) the comparison block reads. Every field is optional so a\n * half-written or older archive degrades to zeros/empties rather than throwing. */\ntype IterationArchive = {\n iteration?: number;\n builder?: { tool_calls?: number; salvaged_tool_calls?: number } | null;\n check?: { ran?: boolean; ok?: boolean; failing_slots?: string[] } | null;\n changes?: { gate_edits?: string[] } | null;\n critic?: { critic_degraded?: boolean; degrade_cause?: DegradeCause } | null;\n unmet_criteria?: string[];\n};\n\n/** Read the archived per-iteration summaries in order. A missing archive root\n * (a run that failed before the first `record`) or an unreadable entry yields an\n * empty/short list — the run summary still writes, just without that trajectory\n * detail. */\nfunction read_iteration_archives(config: ResolvedConfig): IterationArchive[] {\n const root = state_path(config, 'iterations');\n if (!existsSync(root)) return [];\n const dirs = readdirSync(root)\n .filter((dir) => /^\\d{3}$/.test(dir))\n .toSorted();\n const archives: IterationArchive[] = [];\n for (const dir of dirs) {\n const path = state_path(config, 'iterations', dir, 'summary.json');\n if (!existsSync(path)) continue;\n try {\n archives.push(JSON.parse(readFileSync(path, 'utf8')) as IterationArchive);\n } catch {\n // A torn/half-written archive is skipped, never fatal to the run summary.\n }\n }\n return archives;\n}\n\nfunction check_trajectory(archives: IterationArchive[]): CheckTrajectoryPoint[] {\n return archives.map((archive, index) => ({\n iteration: typeof archive.iteration === 'number' ? archive.iteration : index + 1,\n ran: archive.check?.ran === true,\n ok: archive.check?.ok === true,\n failing_slots: archive.check?.failing_slots ?? [],\n }));\n}\n\n/** The run degraded if any archived iteration's critic verdict came from the\n * tool-less fallback. Reads the same on-disk archives as the other\n * comparison metrics, so it grows with the run. */\nfunction any_critic_degraded(archives: IterationArchive[]): boolean {\n return archives.some((archive) => archive.critic?.critic_degraded === true);\n}\n\n/** Each distinct reason an archived critic verdict degraded. An archive from\n * before the cause was recorded reads as a stream error, the only way a verdict\n * could degrade then. */\nfunction critic_degrade_causes(archives: IterationArchive[]): DegradeCause[] {\n const causes = archives\n .filter((archive) => archive.critic?.critic_degraded === true)\n .map((archive) => archive.critic?.degrade_cause ?? 'stream_error');\n return [...new Set(causes)];\n}\n\n/** Every gate path the run's builder touched, across all iterations: an edit in\n * iteration 1 that a later iteration reverted still happened, so the run-level\n * answer is the union rather than the last iteration's list. */\nfunction all_gate_edits(archives: IterationArchive[]): string[] {\n const edits = new Set<string>();\n for (const archive of archives) {\n for (const path of archive.changes?.gate_edits ?? []) edits.add(path);\n }\n return [...edits].toSorted();\n}\n\nfunction salvage_stats(archives: IterationArchive[]): SalvageStats {\n let tool_calls = 0;\n let salvaged_tool_calls = 0;\n for (const archive of archives) {\n tool_calls += archive.builder?.tool_calls ?? 0;\n salvaged_tool_calls += archive.builder?.salvaged_tool_calls ?? 0;\n }\n return {\n tool_calls,\n salvaged_tool_calls,\n rate: tool_calls === 0 ? 0 : salvaged_tool_calls / tool_calls,\n };\n}\n\n/** Fold the comparison block onto a `RunResult`, reading the per-iteration\n * archive for the check trajectory and salvage aggregate. Pure over its inputs\n * plus the on-disk archive; `write_run_summary` persists the result. */\nexport function build_run_summary(config: ResolvedConfig, result: RunResult): RunSummary {\n const archives = read_iteration_archives(config);\n const wall_clock_ms =\n result.completed_at === null\n ? null\n : Date.parse(result.completed_at) - Date.parse(result.started_at);\n return {\n ...result,\n comparison: {\n builder_transport: config.mode === 'critique' ? null : transport_of(config.builder_provider),\n critic_transport: transport_of(config.critic_provider),\n iterations_to_converge:\n result.status === 'success' ? result.iterations_completed : null,\n wall_clock_ms,\n total_cost_usd: result.total_cost_usd,\n builder_cost_usd: result.builder_cost_usd,\n critic_cost_usd: result.critic_cost_usd,\n final_verdict: result.final_verdict,\n check_trajectory: check_trajectory(archives),\n gate_edits: all_gate_edits(archives),\n unmet_criteria: archives.at(-1)?.unmet_criteria ?? [],\n local_salvage: salvage_stats(archives),\n critic_degraded: any_critic_degraded(archives),\n critic_degrade_causes: critic_degrade_causes(archives),\n },\n };\n}\n\n/** Write the enriched summary to the run's `summary.json` (the projection the\n * examples' comparison is read from). */\nexport function write_run_summary(config: ResolvedConfig, result: RunResult): void {\n writeFileSync(\n state_path(config, 'summary.json'),\n `${JSON.stringify(build_run_summary(config, result), null, 2)}\\n`,\n );\n}\n","/**\n * The step bodies behind the nodes of `./flow.ts`, one function per node. Each\n * takes the loop's carry-state and returns the next one. The phase modules they\n * call (`./builder.ts`, `./check/`, `./critic/`) do the work; these bodies add\n * what surrounds it: the renderer lines an operator watches, change detection,\n * git checkpoints, the per-iteration archive, and the progress events a\n * trajectory reader follows the run by.\n */\nimport { aborted_error } from 'fascicle';\nimport type { RunContext, StreamChunk, ToolApprovalHandler } from 'fascicle';\nimport { run_builder } from './builder.js';\nimport type { BuilderStep, PreviousRound } from './builder.js';\nimport { collect_changes } from './changes.js';\nimport { run_checkride } from './check/checkride.js';\nimport { CHECK_REJECTED, rejected_check, run_command_check, skipped_check } from './check/command.js';\nimport { run_critic } from './critic/run.js';\nimport { command_env } from './engine.js';\nimport type { CriticStep } from './critic/run.js';\nimport { archive_iteration, run_result_from_state } from './iteration.js';\nimport type { Renderer } from './render/renderer.js';\nimport { write_run_summary } from './summary.js';\nimport { error_kind, phase_error } from './types.js';\nimport type { ChangeSet, CheckResult, LoopState, ResolvedConfig, Verdict } from './types.js';\nimport { git_checkpoint, state_root_within } from './workspace.js';\nimport { build_root } from './worktree.js';\n\n/** A round starting, emitted as the build opens it. */\nexport type RoundStartEvent = { volley: 'round_start'; round: number };\n\n/** The check starting, with the command line it runs. */\nexport type CheckStartEvent = { volley: 'check_start'; round: number; command: string };\n\n/** The check's outcome. */\nexport type CheckEndEvent = {\n volley: 'check_end';\n round: number;\n ok: boolean;\n exit_code: number | null;\n failing_slots: string[];\n duration_ms: number;\n};\n\n/** The critic's verdict, with what it still found missing, and whether it\n * came from the tool-less fallback. */\nexport type VerdictEvent = {\n volley: 'verdict';\n round: number;\n verdict: Verdict;\n feedback: string;\n unmet_criteria: string[];\n degraded: boolean;\n};\n\n/** The progress events the phases emit through `ctx.emit`, discriminated by\n * `volley`, since `ctx.emit` overwrites `kind` with `'emit'`. A CLI run's\n * trajectory keeps them for a viewer, and under acp they become the round\n * lines, the verdict thought, and the rest of what the editor shows. */\nexport type PhaseEvent = RoundStartEvent | CheckStartEvent | CheckEndEvent | VerdictEvent;\n\n/** The step id the check's card is recorded under: the check step's own, in\n * `./flow.ts`, so each round's check counts as a fresh run of it and opens a\n * card of its own. */\nexport const CHECK_STEP_ID = 'check';\n\n/** The raw call id and tool name of the check's card. The name sits outside\n * the workspace tools, so nothing dresses the card as one of theirs. */\nconst CHECK_CALL = { id: 'check', name: 'check' } as const;\n\nfunction emit(ctx: RunContext, event: PhaseEvent): void {\n ctx.emit(event);\n}\n\n/** Record one chunk of the check's card, the way `model_call` records a tool\n * call's, under a streamed run only, since nothing reads a card otherwise. */\nfunction record_check_chunk(ctx: RunContext, chunk: StreamChunk): void {\n if (ctx.streaming) ctx.trajectory.record({ kind: 'model_chunk', step_id: CHECK_STEP_ID, chunk });\n}\n\n/** The command line the check runs, or null when no check is configured. */\nfunction check_command(config: ResolvedConfig): string | null {\n if (config.check_resolved === 'checkride') return 'pnpm exec checkride --json --digest';\n if (config.check_resolved === 'command') return config.check;\n return null;\n}\n\n/** How the check runs when the caller sets it, as `volley acp` does. Left\n * out, the check runs unasked with volley's environment less the seats' keys,\n * as on the CLI. */\nexport type CheckGate = {\n /** The whole environment the check runs with, in place of volley's own less\n * the seats' keys. */\n env?: Readonly<Record<string, string>>;\n /** Asked on the check's card before each check, the way a model call asks\n * before a gated tool runs. Anything short of an allow keeps the check from\n * running, and it's recorded as failed. */\n on_approval?: ToolApprovalHandler;\n};\n\n/** What every step body closes over, fixed for the whole run. */\nexport type PhaseDeps = {\n config: ResolvedConfig;\n renderer: Renderer;\n /** The commit every iteration's change set is measured against, read after\n * the worktree exists and before the builder writes anything. Null when the\n * build root is not a git repo — then the run reports no changes at all\n * rather than guessing at them. */\n baseline: string | null;\n check?: CheckGate;\n};\n\n/** How many gate edits a warning names before it summarises the rest. */\nconst LISTED_GATE_EDITS = 5;\n\n/**\n * Say what the builder reached for, every iteration. The count is an info line;\n * a gate edit is a warning, because it is the fact that changes how much a green\n * check is worth — and the operator should hear it from the harness rather than\n * discover it in the diff afterwards (the by-hand check that\n * `research/reckon-local-run-finding.md` recommends making routine).\n */\nfunction report_changes(\n config: ResolvedConfig,\n renderer: Renderer,\n changes: ChangeSet | null,\n): void {\n if (changes === null) return;\n renderer.info(\n `changes: ${String(changes.total)} file(s) changed since the run baseline` +\n (changes.truncated ? ` (listing the first ${String(changes.files.length)})` : ''),\n );\n if (changes.gate_edits.length === 0) return;\n const hidden = changes.gate_edits.length - LISTED_GATE_EDITS;\n const listed = changes.gate_edits.slice(0, LISTED_GATE_EDITS).join(', ');\n // A critique's change has no builder behind it, as far as volley knows.\n const [who, whose, edits] =\n config.mode === 'critique'\n ? ['the change under review touches', 'whether it passes', 'the change edits']\n : ['the builder changed', 'whether its work passes', 'the builder can edit'];\n renderer.warn(\n `gate edit: ${who} ${String(changes.gate_edits.length)} file(s) that decide ` +\n `${whose} — ${listed}${hidden > 0 ? ` (+${String(hidden)} more)` : ''}. ` +\n `A green check proves less when ${edits} the gate; the critic is told about ` +\n 'this and the run summary records it.' +\n // The halt lands at the loop guard, after this iteration's check and\n // critic have had their say — so promise the outcome, not the timing.\n (config.fail_on_gate_edit\n ? ' This run will end without success (--fail-on-gate-edit, exit 8).'\n : ''),\n );\n}\n\n/** Run the configured check, checkride or a command, with the environment\n * the caller set for it, else volley's own less the seats' keys, since the\n * check runs code the builder wrote. */\nasync function execute_check(deps: PhaseDeps, abort: AbortSignal): Promise<CheckResult> {\n const { config } = deps;\n // The check gates the tree the builder actually wrote: the worktree\n // under `--worktree`, else the workspace.\n const root = build_root(config.workspace, config.worktree);\n const options = { abort, env: deps.check?.env ?? command_env(process.env) };\n return config.check_resolved === 'checkride'\n ? run_checkride({ ...options, workspace: root })\n : run_command_check({ ...options, command: config.check, workspace: root });\n}\n\n/** Whether the check may run `command`: yes, unless the caller set an\n * approval and it answers no. It asks on the check's card under the command\n * line as its tool name, which titles the prompt the way the card is titled,\n * and which names none of fascicle's gated tools, so the prompt offers Allow\n * and Reject alone, never an \"always\" that would cover the builder's commands\n * too. A stop while it asks ends the check as a stop, not a rejection. */\nasync function check_allowed(\n deps: PhaseDeps,\n command: string,\n abort: AbortSignal,\n): Promise<boolean> {\n const approve = deps.check?.on_approval;\n if (approve === undefined) return true;\n const allowed = await approve({\n tool_name: command,\n input: { command },\n tool_call_id: CHECK_CALL.id,\n step_index: 0,\n abort,\n });\n if (abort.aborted) throw new aborted_error('check aborted');\n return allowed;\n}\n\n/** Open the next iteration: advance the counter and clear every per-iteration\n * field, so nothing from the last round leaks into this one. */\nfunction next_iteration(s: LoopState): LoopState {\n return {\n ...s,\n iteration: s.iteration + 1,\n iteration_started_at: new Date().toISOString(),\n iteration_cost_usd: 0,\n builder: null,\n critic: null,\n check: null,\n verdict: null,\n unmet_criteria: [],\n };\n}\n\n/** What the builder of the iteration after `s` hears about it beyond the\n * critic's feedback: its check, and whether its builder ran out of steps. Null\n * before the first iteration. A resumed run's state carries both, read back\n * from the last archived iteration. */\nfunction previous_round(config: ResolvedConfig, s: LoopState): PreviousRound | null {\n if (s.iteration === 0) return null;\n return {\n check: s.check,\n step_limit_hit: s.builder?.finish_reason === 'max_steps' ? config.builder_max_steps : null,\n };\n}\n\n/** What changed in the build root since the baseline, reported as it's\n * measured: the count, and a warning for any gate edit. A run measures the\n * builder's work this way after every build, and a critique measures the\n * change under review the same way, so the critic is shown one shape either\n * way. */\nfunction measure_changes(deps: PhaseDeps, root: string): ChangeSet | null {\n const { config, renderer } = deps;\n const changes = collect_changes({\n root,\n baseline: deps.baseline,\n gate_patterns: config.gate_paths,\n excluded_dir: state_root_within(root, config.state_dir),\n });\n report_changes(config, renderer, changes);\n return changes;\n}\n\n/** `build`: one builder session edits the build root, then volley measures what\n * it changed and, under `--git`, checkpoints it. */\nexport async function build_phase(\n deps: PhaseDeps,\n builder: BuilderStep,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config, renderer } = deps;\n const next = next_iteration(s);\n emit(ctx, { volley: 'round_start', round: next.iteration });\n renderer.phase_start(next.iteration, 'builder');\n const built = await run_builder(\n { builder, config, warn: renderer.warn },\n next,\n previous_round(config, s),\n ctx,\n );\n renderer.phase_end(built.iteration, 'builder', true);\n renderer.cost_line(\n built.iteration,\n 'builder',\n built.builder?.cost_usd ?? null,\n built.total_cost_usd,\n );\n if (built.cost_warned && !s.cost_warned) {\n renderer.warn('cost unavailable for this phase; recording null (run totals sum what is known)');\n }\n // What the builder actually did, measured before the check runs — so the\n // check's verdict and the builder's reach are two independent facts about\n // the same iteration rather than one inferred from the other.\n const root = build_root(config.workspace, config.worktree);\n const changes = measure_changes(deps, root);\n if (config.git_checkpoints) {\n git_checkpoint(\n root,\n `volley iter ${String(built.iteration)}: build`,\n state_root_within(root, config.state_dir),\n );\n }\n return { ...built, changes };\n}\n\n/** `measure`: a critique's one round opens, and the change under review is\n * measured from the baseline, as a run measures the builder's work. */\nexport function measure_phase(deps: PhaseDeps, s: LoopState, ctx: RunContext): LoopState {\n const next = next_iteration(s);\n emit(ctx, { volley: 'round_start', round: next.iteration });\n const root = build_root(deps.config.workspace, deps.config.worktree);\n return { ...next, changes: measure_changes(deps, root) };\n}\n\n/** `skip_verify`: the build alone crossed the cost cap, so the check is recorded\n * as skipped and no critic is called — a doomed iteration spends nothing more.\n * The loop guard then halts the run on the cap. */\nexport function skip_verify_phase(deps: PhaseDeps, s: LoopState): LoopState {\n deps.renderer.warn('cost cap crossed during build; skipping check and critic');\n return { ...s, check: skipped_check('cost_cap') };\n}\n\n/** Open the check's card on a streamed run: the call's start, then the\n * command as its input, the two chunks `model_call` records for a tool call\n * before it runs. */\nfunction open_check_card(ctx: RunContext, command: string): void {\n record_check_chunk(ctx, { kind: 'tool_call_start', ...CHECK_CALL, step_index: 0 });\n record_check_chunk(ctx, { kind: 'tool_call_end', id: CHECK_CALL.id, input: { command }, step_index: 0 });\n}\n\n/** Close the check's card with its result, which the card's reader renders,\n * or with the error that stopped the check before it had one. */\nfunction close_check_card(ctx: RunContext, outcome: { result: CheckResult } | { error: unknown }): void {\n record_check_chunk(\n ctx,\n 'result' in outcome\n ? { kind: 'tool_result', id: CHECK_CALL.id, output: outcome.result, step_index: 0 }\n : {\n kind: 'tool_result',\n id: CHECK_CALL.id,\n error: {\n message: outcome.error instanceof Error ? outcome.error.message : String(outcome.error),\n },\n step_index: 0,\n },\n );\n}\n\n/** `check`: the deterministic gate over the tree the builder wrote. A check\n * that runs a command emits its start and end, and on a streamed run also\n * records its card as a tool call, so a reader of the stream shows it running\n * while it runs. When the caller set an approval, the check asks on that card\n * first, and a rejected check closes it failed and is recorded as failed. */\nexport async function check_phase(\n deps: PhaseDeps,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config, renderer } = deps;\n renderer.phase_start(s.iteration, 'check');\n const command = check_command(config);\n if (command === null) {\n renderer.info('no deterministic check configured; loop is critic-gated only');\n return { ...s, check: skipped_check('none') };\n }\n emit(ctx, { volley: 'check_start', round: s.iteration, command });\n open_check_card(ctx, command);\n try {\n const allowed = await check_allowed(deps, command, ctx.abort);\n const result = allowed\n ? await execute_check(deps, ctx.abort)\n : rejected_check(config.check_resolved);\n close_check_card(ctx, allowed ? { result } : { error: CHECK_REJECTED });\n emit(ctx, {\n volley: 'check_end',\n round: s.iteration,\n ok: result.ok,\n exit_code: result.exit_code,\n failing_slots: result.failing_slots,\n duration_ms: result.duration_ms,\n });\n renderer.phase_end(\n s.iteration,\n 'check',\n result.ok,\n !allowed\n ? 'rejected'\n : result.failing_slots.length > 0\n ? `failing: ${result.failing_slots.join(', ')}`\n : undefined,\n );\n return {\n ...s,\n check: result,\n check_duration_ms: s.check_duration_ms + result.duration_ms,\n };\n } catch (err) {\n close_check_card(ctx, { error: err });\n if (error_kind(err) === 'check_error') throw err;\n throw phase_error('check', s.iteration, err);\n }\n}\n\n/** `critique`: the read-only critic's verdict, feedback, and unmet criteria. */\nexport async function critique_phase(\n deps: PhaseDeps,\n critic: CriticStep,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { renderer } = deps;\n renderer.phase_start(s.iteration, 'critic');\n const critiqued = await run_critic({ critic, config: deps.config }, s, ctx);\n if (critiqued.verdict !== null) {\n emit(ctx, {\n volley: 'verdict',\n round: critiqued.iteration,\n verdict: critiqued.verdict,\n feedback: critiqued.feedback ?? '',\n unmet_criteria: critiqued.unmet_criteria,\n degraded: critiqued.critic?.critic_degraded === true,\n });\n }\n renderer.phase_end(\n critiqued.iteration,\n 'critic',\n critiqued.verdict === 'approved',\n critiqued.verdict ?? undefined,\n );\n renderer.cost_line(\n critiqued.iteration,\n 'critic',\n critiqued.critic?.cost_usd ?? null,\n critiqued.total_cost_usd,\n );\n return critiqued;\n}\n\n/** `record`: archive the iteration and rewrite the run summary, so the on-disk\n * state is consistent after every round (resume reads it back). */\nexport function record_phase(deps: PhaseDeps, s: LoopState): LoopState {\n const { config } = deps;\n archive_iteration(config, s);\n write_run_summary(config, run_result_from_state(config, s, 'running', null));\n if (config.git_checkpoints) {\n const root = build_root(config.workspace, config.worktree);\n git_checkpoint(\n root,\n `volley iter ${String(s.iteration)}: critique (${s.verdict ?? 'skipped'})`,\n state_root_within(root, config.state_dir),\n );\n }\n return s;\n}\n","/**\n * What a volley turn reads from the editor's thread, and what it shows there.\n *\n * In: the turn's task is the conversation so far, oldest first, then the new\n * prompt. A stopped turn says so where it stopped, an earlier prompt's\n * attached files shrink to a line naming each (they are still on disk), and\n * an earlier reply keeps only its end, where the run's summary sits.\n *\n * Out: `progress_updates` wraps fascicle's `to_session_updates`, so every\n * event still reaches it, and adds what volley's own events say:\n *\n * round_start a **Round N** line in the reply\n * the check's chunks the card fascicle opens, given the look of a command:\n * titled with the command line, closed with its output\n * verdict a thought: the verdict, the feedback, the unmet criteria\n * summary the turn's last message: how the run ended, or failed\n *\n * `check_start` and `check_end` add nothing here, since the card says both.\n */\nimport { StringDecoder } from 'node:string_decoder';\nimport type { TrajectoryEvent, TrajectoryLogger } from 'fascicle';\nimport { to_session_updates } from 'fascicle/acp';\nimport type { AcpHistoryEntry, AcpMapperState, AcpTurn } from 'fascicle/acp';\nimport type { CheckrideSummary } from './check/checkride.js';\nimport { CHECK_STEP_ID } from './phases.js';\nimport type { PhaseEvent, VerdictEvent } from './phases.js';\nimport type { RunSummary } from './summary.js';\nimport { error_kind } from './types.js';\nimport type { CheckResult, PhaseError, RunStatus, Verdict, VolleyPhase } from './types.js';\n\ntype SessionUpdate = ReturnType<typeof to_session_updates>[number];\n\n/** How a run that returned ended, read from its summary: whether it\n * converged, in how many rounds, with what last verdict, and what the editor\n * hears nowhere else (the unmet criteria, gate edits, a degraded verdict),\n * since stderr reaches only the agent log. */\nexport type FinishedSummary = {\n volley: 'summary';\n outcome: 'finished';\n status: RunStatus;\n rounds: number;\n verdict: Verdict | null;\n unmet_criteria: string[];\n gate_edits: string[];\n critic_degraded: boolean;\n};\n\n/** How a run that threw failed: the round it reached, the phase that threw,\n * when the error names one, and what went wrong. */\nexport type FailedSummary = {\n volley: 'summary';\n outcome: 'failed';\n round: number;\n phase: VolleyPhase | null;\n error: string;\n};\n\ntype SummaryEvent = FinishedSummary | FailedSummary;\n\n/** Everything volley emits that this module reads. */\ntype ProgressEvent = PhaseEvent | SummaryEvent;\n\n/** What the model reads after the last text of a turn the user stopped, in\n * fascicle's acp-agent wording. */\nconst STOPPED = '[The user stopped this turn here. Leave what it asked for unless they ask again.]';\n\n/** How much of an earlier reply the task keeps: its end, where the summary sits. */\nexport const AGENT_TAIL_CHARS = 2000;\n\n/** The most of the check's output a card shows, as `run_command` cuts its own. */\nexport const CHECK_OUTPUT_LIMIT_BYTES = 32_000;\n\n/** Where a turn's attached files start: fascicle puts each file's\n * `<context ref=\"…\">` block after the prompt, a blank line before each. */\nconst FIRST_CONTEXT = '\\n\\n<context ref=\"';\n\n/** The seam between two attached files' blocks. A file's own text can hold a\n * `</context>`, so a block ends only where the next one starts. */\nconst CONTEXT_SEAM = /\\n<\\/context>\\n\\n(?=<context ref=\")/;\n\nconst VERDICT_WORDS: Record<Verdict, string> = {\n approved: 'approved',\n changes_requested: 'changes requested',\n};\n\nconst PHASE_WORDS: Record<VolleyPhase, string> = {\n builder: 'the build',\n check: 'the check',\n critic: 'the critique',\n};\n\nfunction rounds(count: number): string {\n return `${String(count)} ${count === 1 ? 'round' : 'rounds'}`;\n}\n\nfunction verdict_words(verdict: Verdict | null): string {\n return verdict === null ? 'none' : VERDICT_WORDS[verdict];\n}\n\nfunction bullets(items: readonly string[]): string {\n return items.map((item) => `- ${item}`).join('\\n');\n}\n\n/** An earlier prompt without its attached files' text, and a line naming each. */\nfunction without_context(text: string): string {\n const start = text.indexOf(FIRST_CONTEXT);\n if (start === -1) return text;\n const refs = text\n .slice(start + 2)\n .split(CONTEXT_SEAM)\n .map((block) => `[attached: ${/^<context ref=\"([^\"]*)\">/.exec(block)?.[1] ?? 'a file'}]`);\n return [text.slice(0, start), ...refs].join('\\n');\n}\n\n/** An earlier reply's end, marked as cut when it was. */\nfunction agent_tail(text: string): string {\n return text.length <= AGENT_TAIL_CHARS ? text : `…${text.slice(-AGENT_TAIL_CHARS)}`;\n}\n\nfunction history_entry(entry: AcpHistoryEntry): string {\n const said =\n entry.role === 'user'\n ? `User: ${without_context(entry.text)}`\n : `Volley: ${agent_tail(entry.text)}`;\n return entry.cancelled === true ? `${said}\\n\\n${STOPPED}` : said;\n}\n\n/** A turn's task, and its criteria: the conversation so far, then the new\n * prompt with its attached files whole. A first turn is its prompt alone. */\nexport function turn_task(turn: AcpTurn): string {\n if (turn.history.length === 0) return turn.text;\n return [\n 'The conversation so far, oldest first:',\n ...turn.history.map(history_entry),\n 'The request now:',\n turn.text,\n ].join('\\n\\n');\n}\n\n/** The summary of a run that returned. */\nexport function summary_event(summary: RunSummary): FinishedSummary {\n return {\n volley: 'summary',\n outcome: 'finished',\n status: summary.status,\n rounds: summary.iterations_completed,\n verdict: summary.final_verdict,\n unmet_criteria: summary.comparison.unmet_criteria,\n gate_edits: summary.comparison.gate_edits,\n critic_degraded: summary.comparison.critic_degraded,\n };\n}\n\nfunction message_of(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** The summary of a run that threw in `round` (0 before the first). A phase\n * error names its phase and carries the error underneath, which is the part\n * worth saying; a check error comes from the check. */\nexport function failure_event(err: unknown, round: number): FailedSummary {\n const kind = error_kind(err);\n if (kind === 'phase_error') {\n const { phase, cause } = err as PhaseError;\n return { volley: 'summary', outcome: 'failed', round, phase, error: message_of(cause) };\n }\n const phase = kind === 'check_error' ? 'check' : null;\n return { volley: 'summary', outcome: 'failed', round, phase, error: message_of(err) };\n}\n\n/** `sink`, and the last round a run started while recording through it, read\n * off its `round_start` events as they pass. */\nexport function follow_rounds(sink: TrajectoryLogger): {\n sink: TrajectoryLogger;\n round: () => number;\n} {\n let round = 0;\n return {\n sink: {\n ...sink,\n record: (event) => {\n if (event.kind === 'emit' && event['volley'] === 'round_start') {\n const started = event['round'];\n if (typeof started === 'number') round = started;\n }\n sink.record(event);\n },\n },\n round: () => round,\n };\n}\n\n/** Text in a `console` code block whose fence outruns any backticks that\n * open one of its lines, so nothing the check printed can close it early. */\nfunction console_block(text: string): string {\n const longest = Math.max(2, ...Array.from(text.matchAll(/^`+/gm), ([run]) => run.length));\n const fence = '`'.repeat(longest + 1);\n return `${fence}console\\n${text}\\n${fence}`;\n}\n\n/** At most `CHECK_OUTPUT_LIMIT_BYTES` of `text`, with a marker when it was\n * cut. A cut inside a character drops its partial bytes. */\nfunction cut(text: string): string {\n const size = Buffer.byteLength(text);\n if (size <= CHECK_OUTPUT_LIMIT_BYTES) return text;\n const kept = new StringDecoder('utf8').write(\n Buffer.from(text).subarray(0, CHECK_OUTPUT_LIMIT_BYTES),\n );\n return `${kept}\\n[output cut at ${String(CHECK_OUTPUT_LIMIT_BYTES)} bytes of ${String(size)}]`;\n}\n\n/** checkride's run as text: each slot and how it went, then each failing\n * slot's own output. */\nfunction checkride_text(result: CheckResult): string {\n const checks = (result.summary as CheckrideSummary | undefined)?.checks ?? [];\n const slots = checks\n .map((check) => `${check.skipped === true ? 'skip' : check.ok ? 'ok ' : 'FAIL'} ${check.name}`)\n .join('\\n');\n const outputs = result.detail.map(\n (artifact) =>\n `── ${artifact.slot} ──\\n${artifact.content.trimEnd()}` +\n (artifact.truncated ? `\\n[cut; the whole output is in ${artifact.path ?? 'the run state'}]` : ''),\n );\n return [slots, ...outputs].filter((part) => part !== '').join('\\n\\n');\n}\n\n/** What the check's card shows: what it printed, cut as `run_command`'s\n * output is, then how it exited. */\nfunction check_text(result: CheckResult): string {\n const printed = (result.runner === 'checkride' ? checkride_text(result) : (result.log ?? '')).trimEnd();\n const exit = result.exit_code === null ? '[ended by a signal]' : `[exit code ${String(result.exit_code)}]`;\n return `${printed === '' ? '[no output]' : cut(printed)}\\n${exit}`;\n}\n\nfunction as_record(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {};\n}\n\n/** One of the check card's updates, given a command's look: opened as an\n * `execute` card, titled with the command line once its input arrives, and\n * closed `completed` or `failed` with its output. A check that threw closes\n * as fascicle closes any failed call, with the error's text. */\nfunction dress_check_update(update: SessionUpdate, chunk: Record<string, unknown>): SessionUpdate {\n if (update.sessionUpdate === 'tool_call') return { ...update, kind: 'execute' };\n if (update.sessionUpdate !== 'tool_call_update') return update;\n if (chunk['kind'] === 'tool_call_end') {\n const command = as_record(chunk['input'])['command'];\n return typeof command === 'string' ? { ...update, title: command } : update;\n }\n if (chunk['kind'] !== 'tool_result' || chunk['error'] !== undefined) return update;\n const result = chunk['output'] as CheckResult;\n return {\n ...update,\n status: result.ok ? 'completed' : 'failed',\n rawOutput: { ok: result.ok, exit_code: result.exit_code, failing_slots: result.failing_slots },\n content: [{ type: 'content', content: { type: 'text', text: console_block(check_text(result)) } }],\n };\n}\n\nfunction message(text: string): SessionUpdate {\n return { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text } };\n}\n\nfunction thought(text: string): SessionUpdate {\n return { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text } };\n}\n\n/** A round's opening line, apart from the reply before it. */\nfunction round_line(round: number): string {\n return `${round === 1 ? '' : '\\n\\n'}**Round ${String(round)}**\\n\\n`;\n}\n\n/** The critic's verdict as a thought: the verdict, the feedback, and what it\n * still found missing. */\nfunction verdict_text(event: VerdictEvent): string {\n const head = `**Round ${String(event.round)} verdict: ${verdict_words(event.verdict)}**`;\n const parts = [\n event.degraded ? `${head} (judged without its tools)` : head,\n event.feedback.trim(),\n event.unmet_criteria.length > 0 ? `Unmet criteria:\\n${bullets(event.unmet_criteria)}` : '',\n ];\n return `\\n\\n${parts.filter((part) => part !== '').join('\\n\\n')}`;\n}\n\nconst ENDINGS: Partial<Record<RunStatus, (count: number) => string>> = {\n success: (count) => `**Converged** in ${rounds(count)}.`,\n budget_exhausted: (count) => `**Not converged** after ${rounds(count)}, the most this run allows.`,\n cost_cap_reached: (count) => `**Not converged**: the run reached its cost cap after ${rounds(count)}.`,\n gate_edit_blocked: (count) =>\n `**Stopped** after ${rounds(count)}: the builder edited the gate, and --fail-on-gate-edit ends the run.`,\n};\n\nfunction finished_text(event: FinishedSummary): string {\n const ending =\n ENDINGS[event.status]?.(event.rounds) ?? `**Ended ${event.status}** after ${rounds(event.rounds)}.`;\n const converged = event.status === 'success';\n return [\n `${ending} Last verdict: ${verdict_words(event.verdict)}.`,\n !converged && event.unmet_criteria.length > 0\n ? `Still unmet:\\n${bullets(event.unmet_criteria)}`\n : '',\n event.gate_edits.length > 0\n ? `The builder edited files that decide whether its work passes: ${event.gate_edits.join(', ')}.`\n : '',\n event.critic_degraded\n ? 'At least one verdict came from a critic that judged without its tools, so it saw less than usual.'\n : '',\n ]\n .filter((part) => part !== '')\n .join('\\n\\n');\n}\n\nfunction failed_text(event: FailedSummary): string {\n const where = event.round === 0 ? 'before the first round' : `in round ${String(event.round)}`;\n const during = event.phase === null ? '' : `, during ${PHASE_WORDS[event.phase]}`;\n return `**Run failed** ${where}${during}: ${event.error}`;\n}\n\n/** The turn's last message: how the run ended, or how it failed. */\nfunction summary_text(event: SummaryEvent): string {\n return `\\n\\n${event.outcome === 'finished' ? finished_text(event) : failed_text(event)}`;\n}\n\n/** An `emit` event's payload, when volley emitted it. */\nfunction progress_event(event: TrajectoryEvent): ProgressEvent | null {\n return event.kind === 'emit' && typeof event['volley'] === 'string'\n ? (event as unknown as ProgressEvent)\n : null;\n}\n\nfunction progress_of(event: ProgressEvent): SessionUpdate[] {\n switch (event.volley) {\n case 'round_start':\n return [message(round_line(event.round))];\n case 'verdict':\n return [thought(verdict_text(event))];\n case 'summary':\n return [message(summary_text(event))];\n case 'check_start':\n case 'check_end':\n return [];\n }\n}\n\n/** volley's `to_updates`: fascicle's own mapping for every event, the check's\n * card dressed as a command, and volley's progress events added. */\nexport function progress_updates(event: TrajectoryEvent, state: AcpMapperState): SessionUpdate[] {\n const updates = to_session_updates(event, state);\n if (event.kind === 'model_chunk' && event['step_id'] === CHECK_STEP_ID) {\n const chunk = as_record(event['chunk']);\n return updates.map((update) => dress_check_update(update, chunk));\n }\n const progress = progress_event(event);\n return progress === null ? updates : [...updates, ...progress_of(progress)];\n}\n","/**\n * The seats' tool sets under `volley acp`.\n *\n * Volley's own `write_file`, `edit_file`, and `bash` set no `needs_approval`,\n * so served to an editor they would edit and run commands unasked in every\n * mode. Under acp the builder gets fascicle's workspace tools instead, whose\n * writes and `run_command` ask as the session's mode says, plus volley's\n * `finish`; the critic gets that set's three reads, which never ask. Neither\n * gets `fetch`, which would reach the network unasked.\n *\n * Both sets are built from the session itself, since fascicle keys a\n * session's cards and prompts on it: a copy would lose each edit's diff, each\n * command's terminal, and the \"always\" a prompt offers. The session holds\n * `session.cwd` alone, because volley serves no additional directories\n * (`./acp.ts`), and both sets skip volley's `IGNORED_DIRS` rather than\n * fascicle's shorter default, so a seat sees the same tree under acp as on the\n * CLI.\n *\n * The builder's commands and the check run with the agent's environment less\n * every key a seat reads, so nothing the builder writes can read them. The\n * check asks, through the session, exactly when `run_command`'s own gate would\n * ask before the same command; outside a container, with no opt-out, Auto\n * isn't offered, so that gate asks in every mode the user can pick.\n */\nimport { workspace_tools } from 'fascicle/acp';\nimport type { AcpSession } from 'fascicle/acp';\nimport type { Tool, ToolApprovalHandler } from 'fascicle';\nimport { finish_tool } from './builder/tools.js';\nimport { command_env } from './engine.js';\nimport type { CheckGate } from './phases.js';\nimport { IGNORED_DIRS } from './workspace_tools.js';\nimport type { ToolSet } from './workspace_tools.js';\n\n/** The reads the critic takes from the session's set. */\nconst CRITIC_READS: ReadonlySet<string> = new Set(['read_file', 'list_files', 'search']);\n\ntype Env = Readonly<Record<string, string | undefined>>;\n\ntype AcpToolOptions = {\n /** The agent's environment, which the builder's commands and the check run\n * with, less the seats' keys; default: the process's. */\n env?: Env;\n};\n\n/** One seat's tools, with the name of their set, which its prompt names. */\ntype AcpSeatTools = { tools: ReadonlyArray<Tool>; tool_set: ToolSet };\n\n/** Whether `tool` asks before a call with `input`. A set without the tool\n * asks, so a check never runs unasked by mistake. */\nasync function asks_before(tool: Tool | undefined, input: unknown): Promise<boolean> {\n if (tool === undefined) return true;\n const needs = tool.needs_approval;\n return typeof needs === 'function' ? needs(input) : needs === true;\n}\n\n/** What one session gives the seats and the check: the builder's six\n * workspace tools plus `finish`, asking through `session.approve`; the\n * critic's three reads out of the same set; and the check's environment,\n * the same as the builder's commands get, with an approval that asks through\n * the session exactly when the builder's `run_command` would ask before\n * running the same command. */\nexport function acp_seat_tools(\n session: AcpSession,\n options: AcpToolOptions = {},\n): {\n builder: AcpSeatTools & { on_tool_approval: ToolApprovalHandler };\n critic: AcpSeatTools;\n check: CheckGate;\n} {\n const env = command_env(options.env ?? process.env);\n const tools = workspace_tools(session, { ignore: [...IGNORED_DIRS], command_env: env });\n const run_command = tools.find((tool) => tool.name === 'run_command');\n return {\n builder: {\n tools: [...tools, finish_tool()],\n tool_set: 'acp',\n on_tool_approval: session.approve,\n },\n critic: { tools: tools.filter((tool) => CRITIC_READS.has(tool.name)), tool_set: 'acp' },\n check: {\n env,\n on_approval: async (request) =>\n (await asks_before(run_command, request.input)) ? session.approve(request) : true,\n },\n };\n}\n","/**\n * `--check` resolution: `auto` detects checkride in the workspace;\n * `none` disables the gate; anything else is a shell command — unless it is\n * recognizably checkride itself, which gets the structured runner.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { CheckMode, CheckRunnerKind } from '../types.js';\n\nfunction package_check_script_is_checkride(workspace: string): boolean {\n const path = join(workspace, 'package.json');\n if (!existsSync(path)) return false;\n try {\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as {\n scripts?: Record<string, string>;\n };\n const script = pkg.scripts?.['check'];\n return typeof script === 'string' && /(^|\\s)checkride(\\s|$)/.test(script);\n } catch {\n return false;\n }\n}\n\nexport function checkride_detected(workspace: string): boolean {\n return (\n existsSync(join(workspace, 'checkride.config.json')) ||\n package_check_script_is_checkride(workspace) ||\n existsSync(join(workspace, 'node_modules', '.bin', 'checkride'))\n );\n}\n\nexport function resolve_check_runner(\n check: CheckMode,\n workspace: string,\n): CheckRunnerKind {\n if (check === 'none') return 'none';\n if (check === 'auto') {\n return checkride_detected(workspace) ? 'checkride' : 'none';\n }\n return /(^|\\s)checkride(\\s|$)/.test(check.trim()) ? 'checkride' : 'command';\n}\n","/**\n * Config resolution: merge CLI flags over an optional config file\n * over defaults, expand `@file` references, validate, and produce the\n * immutable `ResolvedConfig` that the run's `config.json` records.\n */\nimport { accessSync, constants, existsSync, readFileSync, statSync } from 'node:fs';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { randomUUID } from 'node:crypto';\nimport { DEFAULT_GATE_PATTERNS } from './changes.js';\nimport { resolve_check_runner } from './check/detect.js';\nimport { detect_containment } from './containment.js';\nimport { openrouter_api_key, SEAT_URL_PROVIDERS, takes_seat_url } from './engine.js';\nimport { config_error } from './types.js';\nimport { default_state_root, RUN_ID_PATTERN } from './workspace.js';\nimport type {\n RunMode,\n BuilderPermissionMode,\n BuilderProvider,\n CriticPreset,\n CriticProvider,\n ResolvedConfig,\n VolleyConfig,\n} from './types.js';\n\nexport const DEFAULT_BUILDER_MODEL = 'opus';\nconst DEFAULT_CRITIC_MODEL = 'opus';\nexport const DEFAULT_MAX_ITERATIONS = 10;\nexport const DEFAULT_BUILDER_MAX_STEPS = 50;\nexport const DEFAULT_BUILDER_MAX_TOOL_CALLS = 1;\nexport const DEFAULT_BUILDER_MAX_OUTPUT_TOKENS = 16384;\nexport const DEFAULT_CHECK = 'auto';\nconst DEFAULT_CRITIC = 'reviewer';\nconst DEFAULT_BUILDER_PROVIDER: BuilderProvider = 'claude_cli';\nconst DEFAULT_CRITIC_PROVIDER: CriticProvider = 'claude_cli';\nconst DEFAULT_PERMISSION_MODE: BuilderPermissionMode = 'acceptEdits';\n/** The image volley's own `Dockerfile` builds; the local-builder sandbox runs\n * it unless `--sandbox-image` / `VOLLEY_SANDBOX_IMAGE` overrides it. */\nexport const DEFAULT_SANDBOX_IMAGE = 'volley-sandbox:latest';\n\nconst BUILDER_PROVIDERS: ReadonlyArray<BuilderProvider> = [\n 'claude_cli',\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\n/** Builder providers that drive their model through volley's own tool loop —\n * a real `bash` (write + exec), wherever the model runs. Refused unless volley\n * is running inside a container (the correct blast-radius default) or the\n * operator explicitly opts out; `claude_cli` has its own permission model and\n * is exempt. */\nconst TOOL_LOOP_BUILDER_PROVIDERS: ReadonlyArray<BuilderProvider> = [\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\nconst CRITIC_PROVIDERS: ReadonlyArray<CriticProvider> = [\n 'claude_cli',\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\nconst CRITIC_PRESETS: ReadonlyArray<CriticPreset> = [\n 'reviewer',\n 'optimizer',\n 'researcher',\n];\n\nconst PERMISSION_MODES: ReadonlyArray<BuilderPermissionMode> = [\n 'acceptEdits',\n 'bypassPermissions',\n];\n\n/** `@path/to/file` reads the file; any other string passes through. */\nexport function expand_at_file(value: string, cwd: string): string {\n if (!value.startsWith('@')) return value;\n const path = resolve(cwd, value.slice(1));\n if (!existsSync(path)) {\n throw config_error(`file not found: ${path} (from ${value})`);\n }\n return readFileSync(path, 'utf8');\n}\n\nfunction is_critic_preset(value: string): value is CriticPreset {\n return (CRITIC_PRESETS as ReadonlyArray<string>).includes(value);\n}\n\n/** Load a `volley.config.ts` / `.js` file's default export. */\nexport async function load_config_file(path: string): Promise<VolleyConfig> {\n const abs = resolve(path);\n if (!existsSync(abs)) {\n throw config_error(`config file not found: ${abs}`);\n }\n let loaded: unknown;\n try {\n const mod = (await import(pathToFileURL(abs).href)) as {\n default?: unknown;\n };\n loaded = mod.default;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw config_error(`failed to load config file ${abs}: ${detail}`);\n }\n if (typeof loaded !== 'object' || loaded === null) {\n throw config_error(`config file ${abs} must default-export a VolleyConfig object`);\n }\n return loaded as VolleyConfig;\n}\n\nfunction validate_workspace(workspace: string): string {\n const abs = isAbsolute(workspace) ? workspace : resolve(workspace);\n if (!existsSync(abs)) {\n throw config_error(`workspace not found: ${abs}`);\n }\n if (!statSync(abs).isDirectory()) {\n throw config_error(`workspace is not a directory: ${abs}`);\n }\n try {\n accessSync(abs, constants.W_OK);\n } catch {\n throw config_error(`workspace not writable: ${abs}`);\n }\n return abs;\n}\n\nfunction resolve_critic(\n critic: string,\n cwd: string,\n): { critic_preset: CriticPreset | 'custom'; critic_prompt_path: string | null } {\n if (is_critic_preset(critic)) {\n return { critic_preset: critic, critic_prompt_path: null };\n }\n const path = resolve(cwd, critic);\n if (!existsSync(path)) {\n throw config_error(\n `--critic must be one of ${CRITIC_PRESETS.join(', ')} or a path to a prompt file; got: ${critic}`,\n );\n }\n return { critic_preset: 'custom', critic_prompt_path: path };\n}\n\nexport type ResolveOptions = {\n cwd?: string;\n run_id?: string;\n started_at?: string;\n env?: Record<string, string | undefined>;\n /** What happens to a tool-loop builder with nothing between its commands\n * and the host (`unguarded_builder`): the CLI `refuse`s it, the default,\n * while under `volley acp` each of its commands `ask`s a person first, which\n * takes the container's place. */\n uncontained_builder?: 'refuse' | 'ask';\n /** Where the run's state goes, in place of what the config says: `volley\n * resume` passes the root it found the run under, or null for a run an older\n * volley kept in the workspace's `.volley/`, which resumes there. */\n state_dir?: string | null;\n /** A run (the default), or a critique, which has no builder or loop. */\n mode?: RunMode;\n};\n\n/** What only a builder, or the loop around it, uses, with the flag that sets\n * each: a critique has no use for any of them, so naming one is an error\n * rather than something quietly ignored. */\nconst CRITIQUE_REFUSED: ReadonlyArray<readonly [keyof VolleyConfig, string]> = [\n ['builder_model', '--builder-model'],\n ['builder_provider', '--builder-provider'],\n ['builder_url', '--builder-url'],\n ['builder_max_steps', '--builder-max-steps'],\n ['builder_max_tool_calls', '--builder-max-tool-calls'],\n ['builder_max_output_tokens', '--builder-max-output-tokens'],\n ['builder_permission_mode', '--builder-permission-mode'],\n ['allow_unsandboxed_builder', '--allow-unsandboxed-builder'],\n ['sandbox_image', '--sandbox-image'],\n ['max_iterations', '--max-iterations'],\n ['max_cost_usd', '--max-cost-usd'],\n ['git_checkpoints', '--git'],\n ['worktree', '--worktree'],\n ['discard_worktree', '--discard-worktree'],\n ['fail_on_gate_edit', '--fail-on-gate-edit'],\n];\n\nfunction refuse_builder_settings(raw: VolleyConfig): void {\n for (const [field, flag] of CRITIQUE_REFUSED) {\n if (raw[field] !== undefined && raw[field] !== false) {\n throw config_error(\n `volley critique refuses ${flag} (${field}): a critique runs no builder and no loop`,\n );\n }\n }\n}\n\n/** A tool-loop builder's count: its step cap, its tool calls per turn, or\n * its output tokens per turn, with the value it takes when nothing sets it. */\ntype BuilderCount<fallback extends number | null = number> = {\n flag: string;\n env_var: string;\n fallback: fallback;\n};\n\nconst BUILDER_MAX_STEPS: BuilderCount = {\n flag: '--builder-max-steps',\n env_var: 'VOLLEY_BUILDER_MAX_STEPS',\n fallback: DEFAULT_BUILDER_MAX_STEPS,\n};\n\nconst BUILDER_MAX_TOOL_CALLS: BuilderCount = {\n flag: '--builder-max-tool-calls',\n env_var: 'VOLLEY_BUILDER_MAX_TOOL_CALLS',\n fallback: DEFAULT_BUILDER_MAX_TOOL_CALLS,\n};\n\n/** The builders whose turns are capped when nothing sets a cap: the local\n * ones, where nothing else bounds a turn. Ollama's MLX runner lets an unset\n * `num_predict` run to the model's trained context less the prompt, which is\n * how one qwen3.8 turn spent 30,847 tokens thinking. A hosted model on\n * OpenRouter has its own output limit, and a request for more than it allows\n * can be refused, so it's capped only when asked. */\nconst CAPPED_BY_DEFAULT: ReadonlyArray<BuilderProvider> = ['ollama', 'lmstudio'];\n\n/** The output cap's flag and env var, and its default for `provider`: 16k\n * tokens on a local builder, else the provider's own limit (null). */\nfunction builder_max_output_tokens_count(provider: BuilderProvider): BuilderCount<number | null> {\n return {\n flag: '--builder-max-output-tokens',\n env_var: 'VOLLEY_BUILDER_MAX_OUTPUT_TOKENS',\n fallback: CAPPED_BY_DEFAULT.includes(provider) ? DEFAULT_BUILDER_MAX_OUTPUT_TOKENS : null,\n };\n}\n\n/** A builder count's flag or config value wins over its env var, which wins\n * over the default, and either must be a positive integer. Local builder\n * only; ignored by the `claude_cli` arm. */\nfunction resolve_builder_count<fallback extends number | null>(\n value: number | undefined,\n env: Record<string, string | undefined>,\n count: BuilderCount<fallback>,\n): number | fallback {\n if (value !== undefined) return positive_count(value, value, count);\n const env_value = env[count.env_var];\n if (env_value !== undefined && env_value !== '') {\n return positive_count(Number(env_value), env_value, count);\n }\n return count.fallback;\n}\n\nfunction positive_count(\n value: number,\n original: unknown,\n count: Pick<BuilderCount, 'flag' | 'env_var'>,\n): number {\n if (!Number.isInteger(value) || value < 1) {\n throw config_error(\n `${count.flag} / ${count.env_var} must be a positive integer; got: ${String(original)}`,\n );\n }\n return value;\n}\n\n/** `--sandbox-image` (a merged flag/config value) wins over the\n * `VOLLEY_SANDBOX_IMAGE` env var, which wins over the default image. Used only\n * on the local-builder Docker sandbox path; the `claude_cli` path never\n * runs Docker. */\nfunction resolve_sandbox_image(\n raw: VolleyConfig,\n env: Record<string, string | undefined>,\n): string {\n if (raw.sandbox_image !== undefined && raw.sandbox_image !== '') {\n return raw.sandbox_image;\n }\n const env_value = env['VOLLEY_SANDBOX_IMAGE'];\n if (env_value !== undefined && env_value !== '') {\n return env_value;\n }\n return DEFAULT_SANDBOX_IMAGE;\n}\n\n/** The `--allow-unsandboxed-builder` flag/config value wins; otherwise\n * `VOLLEY_ALLOW_UNSANDBOXED_BUILDER=1` (or `=true`) opts out. Any other value\n * (incl. `0`/`false`/unset) leaves a tool-loop builder refused unless\n * contained. */\nfunction resolve_allow_unsandboxed_builder(\n raw: Pick<VolleyConfig, 'allow_unsandboxed_builder'>,\n env: Record<string, string | undefined>,\n): boolean {\n if (raw.allow_unsandboxed_builder === true) return true;\n const env_value = env['VOLLEY_ALLOW_UNSANDBOXED_BUILDER'];\n return env_value === '1' || env_value === 'true';\n}\n\n/** A seat's own model server URL (`--builder-url` / `--critic-url`), trimmed,\n * or null when unset; an empty value counts as unset, as it does for the env\n * vars it overrides. Only a provider volley reaches at a base URL takes one: on\n * a `claude_cli` seat the setting would silently do nothing, so it is refused.\n * The URL must be plain http(s), with no credentials, query, or fragment:\n * volley appends API paths to it for prewarm and the context probe, which a\n * query or fragment would break, and it is persisted and printed, which\n * credentials must never be. */\nfunction resolve_seat_url(\n seat: 'builder' | 'critic',\n value: unknown,\n provider: BuilderProvider | CriticProvider,\n): string | null {\n const setting = `--${seat}-url (${seat}_url)`;\n if (value === undefined || value === null) return null;\n if (typeof value !== 'string') {\n throw config_error(`${setting} must be a URL string; got a ${typeof value}`);\n }\n const url = value.trim();\n if (url === '') return null;\n if (!takes_seat_url(provider)) {\n const url_providers = new Intl.ListFormat('en', { type: 'disjunction' }).format(\n SEAT_URL_PROVIDERS,\n );\n throw config_error(\n `${setting} applies only to a ${seat} on ${url_providers}; ` +\n `${seat}-provider is ${provider}`,\n );\n }\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw config_error(`${setting} must be an http(s) URL; got: ${url}`);\n }\n // Checked first, so no later message echoes the credentials back.\n if (parsed.username !== '' || parsed.password !== '') {\n throw config_error(`${setting} must not carry credentials`);\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw config_error(`${setting} must be an http(s) URL; got: ${url}`);\n }\n if (parsed.search !== '' || parsed.hash !== '') {\n throw config_error(`${setting} must not carry a query or fragment; got: ${url}`);\n }\n return url;\n}\n\n/** `--state-dir` (`state_dir`): the root each run's state sits under at\n * `<root>/<run_id>/`, resolved against `cwd` so a resumed run finds the same\n * place. Unset, or empty as a seat URL may be, it's the default root,\n * `$XDG_STATE_HOME/volley`, else `~/.local/state/volley`: outside the\n * workspace, where no check that reads every file can trip over the run's own\n * feedback. */\nfunction resolve_state_dir(\n value: unknown,\n cwd: string,\n env: Record<string, string | undefined>,\n): string {\n if (value === undefined || value === null) return default_state_root(env);\n if (typeof value !== 'string') {\n throw config_error(`--state-dir (state_dir) must be a path string; got a ${typeof value}`);\n }\n const path = value.trim();\n return path === '' ? default_state_root(env) : resolve(cwd, path);\n}\n\nfunction is_writable_dir(path: string): boolean {\n try {\n if (!statSync(path).isDirectory()) return false;\n accessSync(path, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/** The run's state directory must be one volley can write: the directory\n * itself when it's there, as a contained run's mount is, else the nearest\n * directory above it, where volley creates it. Checked before any spend,\n * because otherwise the run dies as it starts on a raw EROFS or EACCES. Inside\n * the sandbox the root filesystem is read-only, so that is what an unmounted\n * run directory looks like, and the message says what to mount. */\nfunction validate_run_state_dir(dir: string, contained: boolean): void {\n let existing = dir;\n while (!existsSync(existing) && dirname(existing) !== existing) existing = dirname(existing);\n if (is_writable_dir(existing)) return;\n throw config_error(\n contained\n ? `run state directory not writable: ${dir}. Inside the sandbox, mount the run's own host ` +\n `directory there (sandbox_run_args run_state, or -v <root>/<run id>:${dir}), created on the ` +\n 'host first, and pass volley the same --run-id; or point --state-dir at a writable mount'\n : `run state directory not writable: ${dir}. Point --state-dir at a directory volley can write`,\n );\n}\n\n/** Whether a tool-loop builder's commands would reach the host with nothing in\n * between: volley isn't contained, and the operator hasn't opted out with\n * `--allow-unsandboxed-builder` or `VOLLEY_ALLOW_UNSANDBOXED_BUILDER`. */\nexport function unguarded_builder(\n raw: Pick<VolleyConfig, 'allow_unsandboxed_builder'>,\n env: Record<string, string | undefined>,\n): boolean {\n return !detect_containment(env) && !resolve_allow_unsandboxed_builder(raw, env);\n}\n\n/** A caller's run id, held to `RUN_ID_PATTERN`; none gets a fresh UUID. */\nfunction resolve_run_id(run_id: string | undefined): string {\n if (run_id === undefined) return randomUUID();\n if (!RUN_ID_PATTERN.test(run_id)) {\n throw config_error(\n `--run-id must be letters, digits, '-', and '_', starting with a letter or digit; got: ${run_id}`,\n );\n }\n return run_id;\n}\n\n/** Merge, expand, and validate a raw `VolleyConfig` into a `ResolvedConfig`.\n * `check_resolved` comes from check detection against the workspace, so the\n * SDK and the CLI resolve `auto` and a command check the same way. */\nexport function resolve_config(\n raw: VolleyConfig,\n options: ResolveOptions = {},\n): ResolvedConfig {\n const cwd = options.cwd ?? process.cwd();\n const env = options.env ?? process.env;\n // A critique runs no builder, so it reads nothing a run reads for one: the\n // builder's settings are refused, its env vars go unread, and its seat keeps\n // the defaults.\n const critique = options.mode === 'critique';\n if (critique) refuse_builder_settings(raw);\n const builder_env = critique ? {} : env;\n\n const has_prompt = typeof raw.prompt === 'string' && raw.prompt.length > 0;\n if (!has_prompt && !critique) {\n throw config_error('missing required option: --prompt');\n }\n if (typeof raw.workspace !== 'string' || raw.workspace.length === 0) {\n throw config_error('missing required option: --workspace');\n }\n if (typeof raw.criteria !== 'string' || raw.criteria.length === 0) {\n throw config_error('missing required option: --criteria');\n }\n\n const workspace = validate_workspace(resolve(cwd, raw.workspace));\n const prompt = has_prompt ? expand_at_file(raw.prompt, cwd) : '';\n const criteria = expand_at_file(raw.criteria, cwd);\n\n const max_iterations = raw.max_iterations ?? (critique ? 1 : DEFAULT_MAX_ITERATIONS);\n if (!Number.isInteger(max_iterations) || max_iterations < 1) {\n throw config_error(`--max-iterations must be a positive integer; got: ${String(raw.max_iterations)}`);\n }\n\n const max_cost_usd = raw.max_cost_usd ?? null;\n if (max_cost_usd !== null && !(typeof max_cost_usd === 'number' && max_cost_usd > 0)) {\n throw config_error(`--max-cost-usd must be a positive number; got: ${String(raw.max_cost_usd)}`);\n }\n\n const builder_permission_mode = raw.builder_permission_mode ?? DEFAULT_PERMISSION_MODE;\n if (!PERMISSION_MODES.includes(builder_permission_mode)) {\n throw config_error(\n `--builder-permission-mode must be one of ${PERMISSION_MODES.join(', ')}; got: ${String(raw.builder_permission_mode)}`,\n );\n }\n\n const { critic_preset, critic_prompt_path } = resolve_critic(\n raw.critic ?? DEFAULT_CRITIC,\n cwd,\n );\n\n const builder_provider = raw.builder_provider ?? DEFAULT_BUILDER_PROVIDER;\n if (!BUILDER_PROVIDERS.includes(builder_provider)) {\n throw config_error(\n `--builder-provider must be one of ${BUILDER_PROVIDERS.join(', ')}; got: ${String(raw.builder_provider)}`,\n );\n }\n\n // Safety gate: a tool-loop builder gets a real `bash` (write + exec), local\n // model or hosted, so refuse it — before any model spend — unless volley is\n // running *inside* a container (the correct blast-radius default) or the\n // operator explicitly opts out to run uncontained on the host. Under acp,\n // a person approves each command instead, so nothing is refused here.\n const allow_unsandboxed_builder = resolve_allow_unsandboxed_builder(raw, builder_env);\n const contained = detect_containment(env);\n if (\n TOOL_LOOP_BUILDER_PROVIDERS.includes(builder_provider) &&\n options.uncontained_builder !== 'ask' &&\n unguarded_builder(raw, builder_env)\n ) {\n throw config_error(\n `builder-provider '${builder_provider}' runs volley's tool loop with a real bash ` +\n `(write + exec) — refused unless contained. Launch volley inside its sandbox container ` +\n `(docker run <hardened flags> <image> volley run …, which sets VOLLEY_CONTAINED=1), or pass ` +\n `--allow-unsandboxed-builder (VOLLEY_ALLOW_UNSANDBOXED_BUILDER=1) to run uncontained on the host.`,\n );\n }\n\n const builder_max_steps = resolve_builder_count(raw.builder_max_steps, builder_env, BUILDER_MAX_STEPS);\n const builder_max_tool_calls = resolve_builder_count(\n raw.builder_max_tool_calls,\n builder_env,\n BUILDER_MAX_TOOL_CALLS,\n );\n const builder_max_output_tokens = resolve_builder_count(\n raw.builder_max_output_tokens,\n builder_env,\n builder_max_output_tokens_count(builder_provider),\n );\n\n const critic_provider = raw.critic_provider ?? DEFAULT_CRITIC_PROVIDER;\n if (!CRITIC_PROVIDERS.includes(critic_provider)) {\n throw config_error(\n `--critic-provider must be one of ${CRITIC_PROVIDERS.join(', ')}; got: ${String(raw.critic_provider)}`,\n );\n }\n\n const builder_url = resolve_seat_url('builder', raw.builder_url, builder_provider);\n const critic_url = resolve_seat_url('critic', raw.critic_url, critic_provider);\n\n // An openrouter seat sends `OPENROUTER_API_KEY`, so an unset key is refused\n // here, naming the variable, before any work rather than at the first call.\n if (builder_provider === 'openrouter' || critic_provider === 'openrouter') {\n openrouter_api_key(env);\n }\n\n // Containment auth gate: `claude_cli`'s subscription/OAuth credentials\n // do not survive containerization — the token is mangled inside the container —\n // so a contained run may drive Claude only by API key (a plain env var that\n // travels the boundary). Refuse a contained `claude_cli` role (builder and/or\n // critic) that is not explicitly in `api_key` mode; the all-Claude path stays\n // on the host and Docker-free by design, where subscription auth works.\n if (contained) {\n const claude_roles = [\n builder_provider === 'claude_cli' && !critique ? 'builder' : null,\n critic_provider === 'claude_cli' ? 'critic' : null,\n ].filter((role): role is string => role !== null);\n const auth_mode = env['VOLLEY_AUTH_MODE'] ?? 'auto';\n if (claude_roles.length > 0 && auth_mode !== 'api_key') {\n throw config_error(\n `claude_cli (${claude_roles.join(', ')}) cannot use its subscription/OAuth token inside a ` +\n `container — it is mangled there. Set VOLLEY_AUTH_MODE=api_key (with ANTHROPIC_API_KEY) to ` +\n `drive Claude contained, or run claude_cli on the host uncontained.`,\n );\n }\n }\n\n if (raw.git_checkpoints === true && !existsSync(resolve(workspace, '.git'))) {\n throw config_error(`--git requires the workspace to be a git repository: ${workspace}`);\n }\n\n // A worktree is checked out from the workspace's git history, so refuse the\n // flag before any model spend when the workspace is not a repository.\n const worktree = raw.worktree ?? false;\n if (worktree && !existsSync(resolve(workspace, '.git'))) {\n throw config_error(`--worktree requires the workspace to be a git repository: ${workspace}`);\n }\n\n // `--discard-worktree`: opt in to the throw-away mode — a converged run's\n // effects go away with its branch instead of being kept on it. Only meaningful\n // under `--worktree`, so a lone flag is refused rather than silently ignored:\n // it would otherwise read as isolation the run does not have.\n const discard_worktree = raw.discard_worktree ?? false;\n if (discard_worktree && !worktree) {\n throw config_error(\n '--discard-worktree applies only to a --worktree run: there is no worktree to discard',\n );\n }\n\n // What counts as the gate is the task's call, so a config's own list replaces\n // the defaults outright rather than extending them: a test-writing task owns\n // its tests, and an empty list turns the report off entirely.\n const gate_paths = raw.gate_paths ?? DEFAULT_GATE_PATTERNS;\n if (!Array.isArray(gate_paths) || gate_paths.some((glob) => typeof glob !== 'string')) {\n throw config_error('gate_paths must be an array of glob strings');\n }\n\n const sandbox_image = resolve_sandbox_image(raw, builder_env);\n const state_dir =\n options.state_dir !== undefined ? options.state_dir : resolve_state_dir(raw.state_dir, cwd, env);\n // Each run's folder would land among the workspace's own files, where no\n // exclusion can tell earlier runs' state from the builder's work.\n if (state_dir === workspace) {\n throw config_error(`--state-dir (state_dir) can't be the workspace itself: ${workspace}`);\n }\n const run_id = resolve_run_id(options.run_id);\n // A legacy `.volley/` lives in the workspace, already checked writable.\n if (state_dir !== null) validate_run_state_dir(join(state_dir, run_id), contained);\n const check = raw.check ?? DEFAULT_CHECK;\n\n return {\n version: 2,\n run_id,\n started_at: options.started_at ?? new Date().toISOString(),\n mode: critique ? 'critique' : 'run',\n prompt,\n criteria,\n check,\n check_resolved: resolve_check_runner(check, workspace),\n builder_model: raw.builder_model ?? DEFAULT_BUILDER_MODEL,\n builder_provider,\n builder_url,\n builder_max_steps,\n builder_max_tool_calls,\n builder_max_output_tokens,\n allow_unsandboxed_builder,\n critic_model: raw.critic_model ?? DEFAULT_CRITIC_MODEL,\n critic_provider,\n critic_url,\n builder_permission_mode,\n critic_preset,\n critic_prompt_path,\n max_iterations,\n max_cost_usd,\n git_checkpoints: raw.git_checkpoints ?? false,\n worktree,\n discard_worktree,\n gate_paths: [...gate_paths],\n fail_on_gate_edit: raw.fail_on_gate_edit ?? false,\n sandbox_image,\n state_dir,\n workspace,\n verbose: raw.verbose ?? false,\n quiet: raw.quiet ?? false,\n json: raw.json ?? false,\n show_thinking: raw.show_thinking ?? true,\n };\n}\n","/**\n * The loop's carry-state across its life: the fresh state a run starts from,\n * the stopping rule the loop guard applies after every iteration, and the run\n * status the final state resolves to. Pure functions over `LoopState`; the\n * flow (`./flow.ts`) plugs them in.\n */\nimport { cost_cap_hit, EMPTY_USAGE } from './cost.js';\nimport type { LoopState, ResolvedConfig, RunStatus } from './types.js';\n\nexport function initial_state(): LoopState {\n return {\n iteration: 0,\n iteration_started_at: new Date().toISOString(),\n feedback: null,\n verdict: null,\n unmet_criteria: [],\n check: null,\n changes: null,\n builder: null,\n critic: null,\n total_usage: EMPTY_USAGE,\n total_cost_usd: 0,\n builder_cost_usd: 0,\n critic_cost_usd: 0,\n check_duration_ms: 0,\n builder_max_steps_hits: 0,\n iteration_cost_usd: 0,\n halt: null,\n cost_warned: false,\n };\n}\n\n/** How many rounds the loop may still run: the whole budget on a fresh run, what\n * the resumed run's completed iterations left of it otherwise. */\nexport function remaining_iterations(\n config: ResolvedConfig,\n resume_from: LoopState | null,\n): number {\n return config.max_iterations - (resume_from?.iteration ?? 0);\n}\n\n/** Did this iteration's builder edit the gate that judges it, with the operator\n * having asked for that to stop the run? Reported either way (the critic prompt\n * and the summary always carry it); only `--fail-on-gate-edit` makes it fatal. */\nfunction gate_edit_halt(config: ResolvedConfig, state: LoopState): boolean {\n return config.fail_on_gate_edit && (state.changes?.gate_edits.length ?? 0) > 0;\n}\n\n/** All stopping conditions live here: acceptance, cost cap, the gate\n * edit refusal, and — implicitly via `max_rounds` — the iteration budget.\n * Success wins when it and the cap land on the same iteration.\n *\n * A gate edit is the one condition that *beats* success rather than losing to\n * it: the run passed a check the builder had rewritten, so the pass is exactly\n * what is in question. It stops the run instead of iterating, because a model\n * that just edited the gate is not a promising candidate to be asked again. */\nexport function gate(\n config: ResolvedConfig,\n state: LoopState,\n): { stop: boolean; state: LoopState } {\n const gate_edit = gate_edit_halt(config, state);\n const success = state.check?.ok === true && state.verdict === 'approved' && !gate_edit;\n const cap = cost_cap_hit(config, state);\n const halt = gate_edit ? 'gate_edit' : !success && cap ? 'cost_cap' : null;\n return {\n stop: success || cap || gate_edit,\n state: { ...state, halt },\n };\n}\n\nexport function status_of(value: LoopState, converged: boolean): RunStatus {\n if (value.halt === 'gate_edit') return 'gate_edit_blocked';\n if (value.halt === 'cost_cap') return 'cost_cap_reached';\n return converged ? 'success' : 'budget_exhausted';\n}\n","/**\n * The volley flow: the whole topology of one run, and nothing else. Step bodies\n * live in `./phases.ts`, the model boundaries in `./builder.ts` and\n * `./critic/run.ts`, the stopping rule in `./loop_state.ts`, and the shell\n * around the flow (workspace setup, the worktree lifecycle, `run`, the final\n * summary) in `./orchestrator.ts`.\n *\n * A critique (`build_critique_flow`) is one round over a change already made,\n * so it has no builder, no loop, and no guard: `measure`, which opens the\n * round and measures the change from its baseline, then the same `check`,\n * `critique`, and `record` a run's round ends with.\n *\n * fascicle's `describe.diagram` draws the tree below from the flow itself, and\n * `test/unit/flow_diagram.test.ts` holds it to the code: change a row by changing\n * its step's `description`, then paste `pnpm diagram --prefix ' * '` over it.\n *\n * volley loop: one round per iteration, up to max_iterations\n * ├─ iteration sequence\n * │ ├─ build open the iteration, run the builder, measure the change\n * │ │ └─ builder model call: one agentic session in the build root\n * │ ├─ verify branch: did the build alone cross the cost cap?\n * │ │ ├─ then skip_verify record the check as skipped and call no critic\n * │ │ └─ else sequence\n * │ │ ├─ check the deterministic gate: checkride, a command, or none\n * │ │ └─ critique the read-only critic's verdict and feedback\n * │ │ └─ critic fallback: judge without tools if a critic on any provider but claude_cli keeps dying or runs out of steps\n * │ │ ├─ retry one more try after a stream death, on any provider but claude_cli\n * │ │ │ └─ critic_tools model call with read-only workspace tools\n * │ │ └─ pipe mark the verdict degraded\n * │ │ └─ critic_toolless model call judging from the check output and a file list\n * │ └─ record archive the iteration and rewrite the run summary\n * └─ guard gate stop on approval over a green check, the cost cap, or a gate edit\n */\nimport { branch, fallback, loop, pipe, retry, sequence, step } from 'fascicle';\nimport type { Step } from 'fascicle';\nimport { make_builder_step } from './builder.js';\nimport type { BuilderDeps } from './builder.js';\nimport type { BashExecutor } from './builder/tools.js';\nimport { cost_cap_hit } from './cost.js';\nimport {\n as_degraded,\n critic_degradable,\n critic_retryable,\n make_critic_toolless_step,\n make_critic_tools_step,\n MAX_CRITIC_RETRIES,\n toolless_critic_prompt,\n with_fallback_cause,\n with_retries,\n} from './critic/run.js';\nimport type { CriticDeps, CriticStep } from './critic/run.js';\nimport { gate, initial_state, remaining_iterations } from './loop_state.js';\nimport {\n build_phase,\n check_phase,\n critique_phase,\n measure_phase,\n record_phase,\n skip_verify_phase,\n} from './phases.js';\nimport type { PhaseDeps } from './phases.js';\nimport type { LoopState, RunInput } from './types.js';\n\n/** The builder seat: the engine its calls go through, and, when the caller\n * injects them, the tools that replace volley's own set, the name of that set\n * (which its prompt names), and the handler that answers their approval\n * requests. */\nexport type BuilderSeat = Pick<BuilderDeps, 'engine' | 'tools' | 'tool_set' | 'on_tool_approval'>;\n\n/** The critic seat: its engine and, when injected, the tools that replace its\n * reads and the name of their set. It takes no approval handler, since its\n * reads never ask. */\nexport type CriticSeat = Pick<CriticDeps, 'engine' | 'tools' | 'tool_set'>;\n\n/** What the flow is built from: the step bodies' dependencies, plus each\n * seat's model wiring and the builder's `bash` executor. The two seats share\n * one engine unless they reach one provider at different URLs. */\nexport type FlowDeps = PhaseDeps & {\n seats: { builder: BuilderSeat; critic: CriticSeat };\n /** The local builder's `bash` executor, or null for the host `spawnSync`\n * default (and for `claude_cli`, which supplies no volley tools). */\n bash_executor: BashExecutor | null;\n};\n\n/** What the flow resolves to: the final state, and whether the guard stopped the\n * loop (success, the cost cap, a gate edit) rather than the round budget. */\nexport type LoopOutcome = { value: LoopState; converged: boolean };\n\n/** The critic arm: the degradation ladder. A critic on any provider but\n * `claude_cli` whose tool-bearing stream dies is retried at once (the death is\n * stochastic parser failure, not load, so waiting buys nothing), then judged\n * once without tools. One that runs out of steps skips the retry, since\n * another identical tool loop would only run out again, and goes straight to\n * the tool-less pass. Anything else propagates from either rung untouched. */\nexport function build_critic(deps: CriticDeps): CriticStep {\n const retryable = critic_retryable(deps.config);\n return fallback(\n retry(make_critic_tools_step(deps), {\n description: 'one more try after a stream death, on any provider but claude_cli',\n max_attempts: MAX_CRITIC_RETRIES + 1,\n backoff_ms: 0,\n when: retryable,\n project: with_retries,\n }),\n pipe(make_critic_toolless_step(deps), as_degraded, {\n description: 'mark the verdict degraded',\n }),\n {\n name: 'critic',\n description: 'judge without tools if a critic on any provider but claude_cli keeps dying or runs out of steps',\n when: critic_degradable(deps.config),\n handoff: (prompt) => toolless_critic_prompt(deps.config, prompt),\n project: with_fallback_cause,\n },\n );\n}\n\n/** The steps a run and a critique share, built one way for both. */\nfunction check_step(deps: PhaseDeps): Step<LoopState, LoopState> {\n return step('check', (s: LoopState, ctx) => check_phase(deps, s, ctx), {\n description: 'the deterministic gate: checkride, a command, or none',\n });\n}\n\nfunction critique_step(deps: PhaseDeps, seat: CriticSeat): Step<LoopState, LoopState> {\n const critic = build_critic({ ...seat, config: deps.config, on_chunk: deps.renderer.critic_chunk });\n return step('critique', (s: LoopState, ctx) => critique_phase(deps, critic, s, ctx), {\n description: \"the read-only critic's verdict and feedback\",\n arm: critic,\n });\n}\n\nfunction record_step(deps: PhaseDeps): Step<LoopState, LoopState> {\n return step('record', (s: LoopState) => record_phase(deps, s), {\n description: 'archive the iteration and rewrite the run summary',\n });\n}\n\nexport function build_flow(\n deps: FlowDeps,\n resume_from: LoopState | null,\n): Step<RunInput, LoopOutcome> {\n const { config, renderer } = deps;\n\n const builder = make_builder_step({\n ...deps.seats.builder,\n config,\n on_chunk: renderer.builder_chunk,\n bash_executor: deps.bash_executor,\n });\n\n // `build` and `critique` hand their model boundary to `ctx.call` from inside\n // the body, because the prompt comes from the carried state and the result\n // folds back into it. Each declares that boundary as its `arm`, so it shows\n // up under the step in `describe` and the trajectory's flow structure.\n const build = step('build', (s: LoopState, ctx) => build_phase(deps, builder, s, ctx), {\n description: 'open the iteration, run the builder, measure the change',\n arm: builder,\n });\n const skip_verify = step('skip_verify', (s: LoopState) => skip_verify_phase(deps, s), {\n description: 'record the check as skipped and call no critic',\n });\n const check = check_step(deps);\n const critique = critique_step(deps, deps.seats.critic);\n const record = record_step(deps);\n\n const verify: Step<LoopState, LoopState> = branch({\n name: 'verify',\n description: 'did the build alone cross the cost cap?',\n when: (s: LoopState) => cost_cap_hit(config, s),\n // fascicle names this arm `then`. It holds a Step object, never a function,\n // so nothing can mistake the config for a thenable.\n // oxlint-disable-next-line unicorn/no-thenable\n then: skip_verify,\n otherwise: sequence([check, critique]),\n });\n\n const iteration: Step<LoopState, LoopState> = sequence([build, verify, record], {\n name: 'iteration',\n });\n\n return loop<RunInput, LoopState, LoopOutcome>({\n name: 'volley',\n description: 'one round per iteration, up to max_iterations',\n init: (input) => input.resume_from ?? initial_state(),\n body: iteration,\n guard: step('gate', (s: LoopState) => gate(config, s), {\n description: 'stop on approval over a green check, the cost cap, or a gate edit',\n }),\n finish: (s, { converged }) => ({ value: s, converged }),\n max_rounds: remaining_iterations(config, resume_from),\n });\n}\n\n/** What a critique's flow is built from: the step bodies' dependencies and the\n * critic seat. There's no builder seat, so no builder is ever constructed. */\nexport type CritiqueFlowDeps = PhaseDeps & { critic: CriticSeat };\n\n/** A critique: one round over a change already made. `measure` opens it and\n * measures the change from the baseline, then the check, the critic, and the\n * record, as in a run's round. No loop and no guard: there is nothing to\n * iterate on, and the caller reads the outcome off the final state. */\nexport function build_critique_flow(deps: CritiqueFlowDeps): Step<LoopState, LoopState> {\n const measure = step('measure', (s: LoopState, ctx) => measure_phase(deps, s, ctx), {\n description: 'open the round and measure the change under review',\n });\n return sequence([measure, check_step(deps), critique_step(deps, deps.critic), record_step(deps)], {\n name: 'critique_run',\n });\n}\n","/**\n * The shell around the volley flow (`./flow.ts`): set up the workspace, wrap\n * the run in the worktree lifecycle, execute the flow with a single `run` call,\n * and turn its outcome into the run summary. No hand-rolled runner — rounds,\n * abort threading, signal handlers, and cleanup order all belong to the\n * substrate.\n *\n * run_volley\n * ├─ initialize the run's state (or preserve it, on resume)\n * ├─ with_worktree off unless --worktree\n * │ ├─ capture the change baseline\n * │ ├─ run_loop run the flow (streamed when a sink is given), then the final summary\n * │ └─ integrate a successful --worktree --git run only\n * └─ report a kept checkout, or a salvaged branch (re-stamping the summary)\n *\n * run_critique\n * ├─ resolve the baseline --baseline, else HEAD; a bad revision exits 5\n * ├─ initialize the run's state\n * └─ run the critique flow one round on the critic's engine alone, then the final summary\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { run } from 'fascicle';\nimport { filesystem_logger, tee_logger } from 'fascicle/adapters';\nimport type { Engine, RunOptions, Step, TrajectoryLogger } from 'fascicle';\nimport type { BashExecutor } from './builder/tools.js';\nimport { capture_baseline, resolve_baseline } from './changes.js';\nimport { detect_containment } from './containment.js';\nimport { create_seat_engines, create_volley_engine, dispose_seat_engines } from './engine.js';\nimport type { SeatEngines } from './engine.js';\nimport { build_critique_flow, build_flow } from './flow.js';\nimport type { BuilderSeat, CriticSeat } from './flow.js';\nimport type { CheckGate } from './phases.js';\nimport { run_result_from_state } from './iteration.js';\nimport { initial_state, status_of } from './loop_state.js';\nimport { write_run_summary } from './summary.js';\nimport { trust_key_path } from './trust.js';\nimport type { Renderer } from './render/renderer.js';\nimport { config_error, error_kind } from './types.js';\nimport type { LoopState, ResolvedConfig, RunResult, RunStatus } from './types.js';\nimport {\n initialize_run_state,\n integrate_worktree,\n run_state_dir,\n state_path,\n write_resolved_config,\n} from './workspace.js';\nimport {\n build_root,\n report_worktree_fate,\n with_worktree,\n worktree_branch,\n worktree_fate,\n} from './worktree.js';\n\nexport type OrchestratorDeps = {\n renderer: Renderer;\n /** An engine to run both seats on in place of the ones built from the\n * config. It serves both seats as-is, so the seat URLs then steer only\n * volley's own requests (prewarm and the context probe), not model calls. */\n engine?: Engine;\n /** What to hand each seat in place of volley's own wiring: the builder's\n * tools and the handler that answers their approval requests, and the\n * critic's tools. A seat or a field left out keeps today's wiring, and a\n * `claude_cli` seat, which brings its own tools, takes none of it. */\n seats?: {\n builder?: Omit<BuilderSeat, 'engine'>;\n critic?: Omit<CriticSeat, 'engine'>;\n };\n /** A second sink for the run's trajectory, beside the run's\n * `trajectory.jsonl`. With one, the flow runs through `run.stream`, so the\n * sink also receives each model call's streamed chunks as `model_chunk`\n * events, which the file never keeps. */\n trajectory?: TrajectoryLogger;\n /** The environment the check runs with and the approval it asks first, in\n * place of inheriting volley's environment and running unasked. */\n check?: CheckGate;\n abort?: AbortSignal;\n install_signal_handlers?: boolean;\n};\n\nexport async function run_volley(\n config: ResolvedConfig,\n deps: OrchestratorDeps,\n resume_from: LoopState | null = null,\n): Promise<RunResult> {\n const { renderer } = deps;\n\n if (resume_from === null) {\n initialize_run_state(config);\n // Unsigned on the host only when the machine's key can't be read or made.\n if (!write_resolved_config(config) && !detect_containment(process.env)) {\n renderer.warn(\n `could not sign this run's config with this machine's key (${trust_key_path(process.env)}), ` +\n 'so resuming it here will need --trust-config',\n );\n }\n } else {\n initialize_run_state(config, { preserve: true });\n }\n renderer.info(`state: ${run_state_dir(config)}`);\n\n // Say what this run will do with its effects before it spends anything — the\n // same notice `--dry-run` prints, repeated here so a run started without a dry\n // run still hears it (the same predict-then-warn shape).\n report_worktree_fate(config, renderer);\n\n // The worktree lifecycle wraps the whole builder loop: created before the\n // first iteration, torn down after the last. Off unless `--worktree` is set\n // (config.worktree), so the default path never touches git here.\n const branch = worktree_branch(config.run_id);\n const fate = worktree_fate(config);\n const outcome = await with_worktree<RunResult>(\n {\n enabled: config.worktree,\n workspace: config.workspace,\n branch,\n log: (message) => renderer.info(message),\n // The one case teardown must keep rather than force-delete: a converged run\n // that integrated nothing, whose only copy of its work is the worktree.\n salvage: (result) => fate === 'salvage' && result.status === 'success',\n },\n async () => {\n // Whole-process containment: volley runs *inside* its hardened\n // container already — the operator/example's `docker run … <volley args>`\n // launched it — so there is no container lifecycle to orchestrate here. `bash`\n // is the local `host_bash_executor` running in-container (null executor,\n // the host `spawnSync` default) and the file tools write straight to the\n // bind-mounted worktree; the retired `docker exec` path is gone. The\n // hardened `docker run` invocation spec the example uses lives in\n // `src/sandbox.ts`.\n // The commit every iteration's change set is measured against, read after\n // the worktree exists and before the builder writes anything. Null when the\n // build root is not a git repo — then the run reports no changes at all\n // rather than guessing at them.\n const baseline = capture_baseline(build_root(config.workspace, config.worktree));\n const result = await run_loop(config, deps, resume_from, null, baseline);\n // Integration: a *successful* `--worktree --git` run squash-merges the\n // phase branch's checkpoints onto the workspace branch before teardown\n // discards it. Any non-success outcome (cost cap, budget, interrupt,\n // error) is abandoned — teardown discards the branch wholesale, nothing\n // integrated. Gated on `--git` too (`fate === 'integrate'`), so volley only\n // commits to the workspace branch when the operator opted into checkpoints;\n // without it the same work is salvaged onto its own branch instead.\n if (fate === 'integrate' && result.status === 'success') {\n integrate_worktree(config.workspace, branch, `volley run ${config.run_id}: integrate worktree (squash)`);\n renderer.info(`worktree: squash-merged ${branch} onto the workspace branch`);\n }\n return result;\n },\n );\n\n if (outcome.kept_path !== null) {\n renderer.warn(\n `worktree: could not commit this run's work onto ${branch}, so the checkout at ` +\n `${outcome.kept_path} was left standing rather than deleted — its files are intact, and ` +\n 'the next --worktree run rotates the directory aside instead of destroying it.',\n );\n }\n if (outcome.salvaged_branch === null) return outcome.value;\n renderer.info(\n `worktree: this run was not integrated; its work is preserved on branch ` +\n `${outcome.salvaged_branch} (git switch ${outcome.salvaged_branch}, or cherry-pick it).`,\n );\n // Teardown salvaged the branch *after* `run_loop` wrote the final summary, so\n // re-stamp it: the run's `summary.json` and `--json` both name the survivor.\n const salvaged: RunResult = { ...outcome.value, salvaged_branch: outcome.salvaged_branch };\n write_run_summary(config, salvaged);\n return salvaged;\n}\n\nasync function run_loop(\n config: ResolvedConfig,\n deps: OrchestratorDeps,\n resume_from: LoopState | null,\n bash_executor: BashExecutor | null,\n baseline: string | null,\n): Promise<RunResult> {\n const { renderer } = deps;\n\n // The Claude session runs in the build root (the worktree under `--worktree`),\n // because that is where the check, the change report, the checkpoints, and the\n // critic all look. The run's state stays where `state_dir` puts it either\n // way. The seats share one engine unless they reach one provider at\n // different URLs.\n const engines: SeatEngines =\n deps.engine === undefined\n ? await create_seat_engines({\n workspace: build_root(config.workspace, config.worktree),\n builder_provider: config.builder_provider,\n builder_url: config.builder_url,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n })\n : { builder: deps.engine, critic: deps.engine };\n\n const seats = {\n builder: { ...deps.seats?.builder, engine: engines.builder },\n critic: { ...deps.seats?.critic, engine: engines.critic },\n };\n const flow = build_flow(\n {\n seats,\n config,\n renderer,\n bash_executor,\n baseline,\n ...(deps.check !== undefined ? { check: deps.check } : {}),\n },\n resume_from,\n );\n\n try {\n const { value, converged } = await execute_flow(config, deps, flow, { resume_from });\n const status = status_of(value, converged);\n const result = run_result_from_state(config, value, status, new Date().toISOString());\n write_run_summary(config, result);\n return result;\n } catch (err) {\n finalize_failed_run(config, err);\n throw err;\n } finally {\n await dispose_seat_engines(engines);\n }\n}\n\n/** Run the flow into its file trajectory and, when the caller passed one, its\n * own sink. Without a sink this is the one `run` it has always been. With one,\n * it goes through `run.stream`, because only a streamed run records each model\n * call's chunks as `model_chunk` events, which are what an outer consumer maps\n * to text, tool cards, and approval prompts. The sink is that consumer, so the\n * handle's own event stream is closed at once rather than left to buffer, and\n * the file skips the chunks, so it holds the same kinds of event either way.\n *\n * The file goes first in the tee because the first sink's span ids are the\n * ones the run hands out as parents, so the file's parent links stay whole.\n * The sink sees parent ids it never issued, which costs an ACP consumer\n * nothing: it counts a step's runs by the `id` on each `span_start`. */\nfunction execute_flow<I, O>(\n config: ResolvedConfig,\n deps: Pick<OrchestratorDeps, 'trajectory' | 'abort' | 'install_signal_handlers'>,\n flow: Step<I, O>,\n input: I,\n): Promise<O> {\n const file = filesystem_logger({\n output_path: state_path(config, 'trajectory.jsonl'),\n });\n const options: RunOptions = {\n ...(deps.abort !== undefined ? { abort: deps.abort } : {}),\n ...(deps.install_signal_handlers !== undefined\n ? { install_signal_handlers: deps.install_signal_handlers }\n : {}),\n };\n if (deps.trajectory === undefined) return run(flow, input, { ...options, trajectory: file });\n const handle = run.stream(flow, input, {\n ...options,\n trajectory: tee_logger(without_model_chunks(file), deps.trajectory),\n });\n void handle.events[Symbol.asyncIterator]().return?.();\n return handle.result;\n}\n\n/** A logger that passes `inner` every event but a model call's streamed\n * chunks. */\nfunction without_model_chunks(inner: TrajectoryLogger): TrajectoryLogger {\n return {\n ...inner,\n record: (event) => {\n if (event.kind !== 'model_chunk') inner.record(event);\n },\n };\n}\n\n/** Best-effort status stamp on the run summary when the loop threw; the\n * on-disk iteration state is already consistent (record runs per round). */\nfunction finalize_failed_run(config: ResolvedConfig, err: unknown): void {\n const kind = error_kind(err);\n const cause = kind === 'phase_error' ? error_kind((err as { cause?: unknown }).cause) : null;\n const status: RunStatus =\n kind === 'aborted_error' || cause === 'aborted_error' ? 'interrupted' : 'error';\n try {\n // Preserve accumulated totals when `record` already wrote a summary.\n const summary_path = state_path(config, 'summary.json');\n const prior = existsSync(summary_path)\n ? (JSON.parse(readFileSync(summary_path, 'utf8')) as RunResult)\n : run_result_from_state(config, initial_state(), status, null);\n // A summary an older volley wrote, resumed here, has no run_state_dir\n // and no step-limit count.\n write_run_summary(config, {\n ...prior,\n builder_max_steps_hits: (prior.builder_max_steps_hits as number | undefined) ?? 0,\n run_state_dir: run_state_dir(config),\n status,\n completed_at: new Date().toISOString(),\n });\n } catch {\n // Never mask the original failure with a bookkeeping error.\n }\n}\n\n/** What a critique runs with: what a run does, less the builder's seat, plus\n * the revision its change is measured from. */\nexport type CritiqueDeps = Omit<OrchestratorDeps, 'seats'> & {\n /** The revision the change under review is measured from (`--baseline`):\n * everything that differs from it, committed or not, untracked files\n * included. HEAD when absent, so the uncommitted edits are the change. */\n baseline?: string;\n /** The critic's tools in place of volley's reads, as for a run's critic. */\n critic?: Omit<CriticSeat, 'engine'>;\n};\n\n/**\n * `volley critique`: the check and the critic, once, over a change already\n * made. No builder is constructed, and the engine serves the critic's seat\n * alone, so a critic can be measured on fixed, labeled changes without paying\n * for builder turns. It writes the state a one-round run does, with the mode\n * recorded, and ends `success` on approval over a green check, else\n * `rejected`.\n */\nexport async function run_critique(config: ResolvedConfig, deps: CritiqueDeps): Promise<RunResult> {\n if (config.mode !== 'critique') {\n throw config_error(\"run_critique needs a config resolved with mode 'critique'\");\n }\n const { renderer } = deps;\n // First, so a revision that isn't a commit fails before any state is written.\n const baseline = resolve_baseline(config.workspace, deps.baseline);\n initialize_run_state(config);\n write_resolved_config(config);\n renderer.info(`state: ${run_state_dir(config)}`);\n renderer.info(\n baseline === null\n ? 'baseline: none (not a git repository, or no commit yet); the critic reviews the tree'\n : `baseline: ${baseline}`,\n );\n\n const engine =\n deps.engine ??\n create_volley_engine({\n workspace: config.workspace,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n });\n const flow = build_critique_flow({\n config,\n renderer,\n baseline,\n critic: { ...deps.critic, engine },\n ...(deps.check !== undefined ? { check: deps.check } : {}),\n });\n try {\n const value = await execute_flow(config, deps, flow, initial_state());\n const passed = value.check?.ok === true && value.verdict === 'approved';\n const result = run_result_from_state(\n config,\n value,\n passed ? 'success' : 'rejected',\n new Date().toISOString(),\n );\n write_run_summary(config, result);\n return result;\n } catch (err) {\n finalize_failed_run(config, err);\n throw err;\n } finally {\n await engine.dispose();\n }\n}\n","/**\n * Live output renderer: consumes `StreamChunk`s from each\n * `generate` call plus volley's own phase/cost lines, and writes human\n * progress to stderr. Streaming is a display concern only — the trajectory\n * jsonl is the durable record.\n */\nimport type { StreamChunk } from 'fascicle';\nimport type { RunResult } from '../types.js';\nimport {\n GLYPH_COST,\n GLYPH_ERR,\n GLYPH_OK,\n GLYPH_PHASE_FAIL,\n GLYPH_PHASE_OK,\n GLYPH_PHASE_START,\n GLYPH_TOOL,\n VERBOSE_TRUNCATE_CHARS,\n dim,\n format_usd,\n paint,\n summarize_value,\n truncate,\n} from './format.js';\nimport type { Role } from './format.js';\n\nexport type RenderMode = 'default' | 'verbose' | 'quiet' | 'json';\n\nexport type RendererOptions = {\n mode: RenderMode;\n show_thinking: boolean;\n color: boolean;\n max_cost_usd: number | null;\n /** Where the run's trajectory is written, named when verbose output is cut\n * short (default: \"the run's trajectory.jsonl\"). */\n trajectory_path?: string;\n write?: (text: string) => void;\n};\n\nexport type Renderer = {\n builder_chunk: (chunk: StreamChunk) => void;\n critic_chunk: (chunk: StreamChunk) => void;\n phase_start: (iteration: number, phase: Role) => void;\n phase_end: (iteration: number, phase: Role, ok: boolean, detail?: string) => void;\n cost_line: (iteration: number, phase: Role, phase_cost: number | null, run_total: number) => void;\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n final_summary: (result: RunResult) => void;\n};\n\nexport function create_renderer(options: RendererOptions): Renderer {\n const write = options.write ?? ((text: string) => process.stderr.write(text));\n const { mode, color } = options;\n const see_trajectory = `see ${options.trajectory_path ?? \"the run's trajectory.jsonl\"}`;\n const silent = mode === 'json';\n const streaming = mode === 'default' || mode === 'verbose';\n\n // Tracks whether streamed prose left the cursor mid-line, so glyph lines\n // start on their own line.\n let mid_line = false;\n\n const line = (text: string): void => {\n if (silent) return;\n write(`${mid_line ? '\\n' : ''}${text}\\n`);\n mid_line = false;\n };\n\n const chunk_renderer = (role: Role) => (chunk: StreamChunk): void => {\n if (!streaming) return;\n switch (chunk.kind) {\n case 'text': {\n write(paint(role, chunk.text, color));\n mid_line = !chunk.text.endsWith('\\n');\n return;\n }\n case 'reasoning': {\n if (!options.show_thinking) return;\n write(dim(chunk.text, color));\n mid_line = !chunk.text.endsWith('\\n');\n return;\n }\n case 'tool_call_end': {\n const summary =\n mode === 'verbose'\n ? truncate(\n JSON.stringify(chunk.input, null, 2) ?? '',\n VERBOSE_TRUNCATE_CHARS,\n see_trajectory,\n )\n : summarize_value(chunk.input);\n line(`${GLYPH_TOOL} ${paint(role, chunk.id, color)} ${summary}`);\n return;\n }\n case 'tool_result': {\n const ok = chunk.error === undefined;\n if (mode === 'verbose') {\n const body = ok ? summarize_output(chunk.output) : chunk.error?.message ?? '';\n line(`${ok ? GLYPH_OK : GLYPH_ERR} ${truncate(body, VERBOSE_TRUNCATE_CHARS, see_trajectory)}`);\n } else {\n line(`${ok ? GLYPH_OK : GLYPH_ERR} ${ok ? '' : summarize_value(chunk.error?.message)}`);\n }\n return;\n }\n case 'tool_call_start': {\n line(`${GLYPH_TOOL} ${paint(role, chunk.name, color)} …`);\n return;\n }\n default:\n return;\n }\n };\n\n return {\n builder_chunk: chunk_renderer('builder'),\n critic_chunk: chunk_renderer('critic'),\n phase_start: (iteration, phase) => {\n if (mode === 'json') return;\n line(paint(phase, `${GLYPH_PHASE_START} [iter ${String(iteration)}] ${phase}`, color));\n },\n phase_end: (iteration, phase, ok, detail) => {\n if (mode === 'json') return;\n const glyph = ok ? GLYPH_PHASE_OK : GLYPH_PHASE_FAIL;\n const suffix = detail !== undefined ? ` — ${detail}` : '';\n line(paint(phase, `${glyph} [iter ${String(iteration)}] ${phase}${suffix}`, color));\n },\n cost_line: (iteration, phase, phase_cost, run_total) => {\n if (mode === 'json') return;\n const cap = options.max_cost_usd !== null ? ` / ${format_usd(options.max_cost_usd)}` : '';\n line(\n paint(\n 'cost',\n `${GLYPH_COST} [iter ${String(iteration)}] [${phase}] phase: ${format_usd(phase_cost)} | run: ${format_usd(run_total)}${cap}`,\n color,\n ),\n );\n },\n info: (message) => {\n line(message);\n },\n warn: (message) => {\n line(paint('critic', `warning: ${message}`, color));\n },\n error: (message) => {\n if (silent) {\n // Errors still surface in json mode — stderr stays human, stdout machine.\n write(`error: ${message}\\n`);\n return;\n }\n line(paint('error', `error: ${message}`, color));\n },\n final_summary: (result) => {\n if (silent) return;\n line('');\n line(`run ${result.run_id}: ${result.status}`);\n line(\n `iterations: ${String(result.iterations_completed)} | verdict: ${result.final_verdict ?? 'n/a'}`,\n );\n line(\n paint(\n 'cost',\n `${GLYPH_COST} total: ${format_usd(result.total_cost_usd)} (builder ${format_usd(result.builder_cost_usd)}, critic ${format_usd(result.critic_cost_usd)})`,\n color,\n ),\n );\n line(\n `tokens: ${String(result.total_usage.input_tokens)} in / ${String(result.total_usage.output_tokens)} out`,\n );\n line(`state: ${result.run_state_dir}`);\n },\n };\n}\n\nfunction summarize_output(output: unknown): string {\n if (typeof output === 'string') return output;\n try {\n return JSON.stringify(output) ?? '';\n } catch {\n return String(output);\n }\n}\n","/**\n * `volley acp`: volley served to an editor over the Agent Client Protocol,\n * through fascicle's `serve_acp`. Each prompt in the editor's agent panel is\n * a fresh volley run, in place, on the folder the editor has open.\n *\n * serve_acp\n * └─ per session/new: acp_turn one step, whose id no model call shares\n * └─ per prompt: run_volley on session.cwd, its state under the state root\n * ├─ builder fascicle's workspace tools + finish, asking through session.approve\n * ├─ critic that set's three reads\n * └─ trajectory the turn's own logger, so the builder's text,\n * cards, and approval prompts reach the editor\n *\n * The task is the conversation so far, then the prompt, and the run's progress\n * events become the round lines, the check's card, the verdict thought, and\n * the summary that ends the turn (`./acp_progress.ts`). A run that fails ends\n * the turn with a summary saying so, rather than as an error, which would\n * leave it out of the session's history; a stopped turn still ends cancelled.\n *\n * Outside a container, unless the operator opted out, a person approving each\n * command takes the container's place: Auto isn't offered, so every builder\n * command and every check asks first in either mode that is. Neither sees the\n * keys the seats spend, and a session reaches the folder it opened on alone.\n *\n * The flags are checked once at startup, and every config error exits 5\n * before serving, so it shows in the editor's agent log once rather than\n * failing every prompt. Stdout carries the protocol alone: the run's renderer\n * writes to stderr, and `--json` is refused.\n */\nimport { tmpdir } from 'node:os';\nimport { step } from 'fascicle';\nimport type { RunContext, Step } from 'fascicle';\nimport type { AcpMode, AcpSession, AcpStreamRoute, AcpTurn, ServeAcpConfig } from 'fascicle/acp';\nimport {\n failure_event,\n follow_rounds,\n progress_updates,\n summary_event,\n turn_task,\n} from './acp_progress.js';\nimport { acp_seat_tools } from './acp_tools.js';\nimport { resolve_config, unguarded_builder } from './config.js';\nimport { run_volley } from './orchestrator.js';\nimport type { OrchestratorDeps } from './orchestrator.js';\nimport type { CheckGate } from './phases.js';\nimport { create_renderer } from './render/renderer.js';\nimport { build_run_summary } from './summary.js';\nimport { config_error } from './types.js';\nimport type { ResolvedConfig, RunResult, VolleyConfig } from './types.js';\n\ntype Env = Record<string, string | undefined>;\n\n/** `volley acp`'s flags as config: everything but the workspace and the task,\n * which each prompt supplies. */\ntype AcpFlags = Omit<VolleyConfig, 'prompt' | 'workspace' | 'criteria'>;\n\n/** `--max-iterations` under acp. A prompt is one short exchange, which the\n * user can follow with another, and `--max-cost-usd` caps what a prompt\n * spends. */\nexport const ACP_MAX_ITERATIONS = 3;\n\n/** The seat flags `volley acp` requires, by the config field each sets. The\n * CLI's defaults (`claude_cli` on `opus`) would refuse themselves here, and a\n * default hosted model would spend money on a model the editor's entry never\n * names. */\nconst REQUIRED_SEAT_FLAGS: ReadonlyArray<readonly [keyof AcpFlags, string]> = [\n ['builder_provider', '--builder-provider'],\n ['builder_model', '--builder-model'],\n ['critic_provider', '--critic-provider'],\n ['critic_model', '--critic-model'],\n];\n\n/** The run command's options `volley acp` declares only to refuse, by the\n * config field each sets, with the reason it gives. */\nconst REFUSED_FLAGS: ReadonlyArray<readonly [keyof AcpFlags, string, string]> = [\n ['worktree', '--worktree', 'a sibling worktree sits outside the project the editor has open'],\n [\n 'git_checkpoints',\n '--git',\n 'it commits to the open repo after every phase, which no permission prompt covers',\n ],\n ['json', '--json', 'stdout carries the protocol alone'],\n];\n\n/** What the startup check resolves in place of a prompt, which no session has\n * sent yet. */\nconst STAND_IN_TASK = 'volley acp: startup check';\n\n/** Unset, or set to nothing but whitespace. Any other value goes on to\n * `resolve_config`, which says what's wrong with it. */\nfunction is_blank(value: unknown): boolean {\n return value === undefined || (typeof value === 'string' && value.trim() === '');\n}\n\n/** A refusal or a missing seat flag, as one config error. */\nfunction refuse_unservable(raw: AcpFlags): void {\n for (const [field, flag, reason] of REFUSED_FLAGS) {\n if (raw[field] === true) throw config_error(`volley acp refuses ${flag}: ${reason}`);\n }\n const missing = REQUIRED_SEAT_FLAGS.filter(([field]) => is_blank(raw[field])).map(\n ([, flag]) => flag,\n );\n if (missing.length > 0) {\n throw config_error(`volley acp requires every seat flag, and these are missing: ${missing.join(', ')}`);\n }\n if (raw.builder_provider === 'claude_cli') {\n throw config_error(\n 'volley acp refuses a claude_cli builder: the Claude CLI runs its own tools under its own ' +\n \"permission model, so its edits would never reach the editor's prompts\",\n );\n }\n}\n\n/** The flags `volley acp` was started with, with acp's default filled in:\n * three rounds. Run state goes under the default root, outside the workspace,\n * unless `--state-dir` names one, as it does for any run. Each refusal, a\n * missing seat flag, and any other config error, an unwritable state root\n * among them, throws here, before serving: the whole config resolves once\n * against the system temp directory with a stand-in task, since no session has\n * named a workspace yet. */\nexport function acp_base_config(raw: AcpFlags, env: Env = process.env): AcpFlags {\n refuse_unservable(raw);\n const base: AcpFlags = {\n ...raw,\n max_iterations: raw.max_iterations ?? ACP_MAX_ITERATIONS,\n };\n resolve_config(\n { ...base, workspace: tmpdir(), prompt: STAND_IN_TASK, criteria: STAND_IN_TASK },\n { env, uncontained_builder: 'ask' },\n );\n return base;\n}\n\n/** One prompt's run config: the base flags resolved against the session's\n * workspace, with the turn as both the task and the criteria. Those two are\n * set after resolving, because resolving reads a value that starts with `@` as\n * a file to load, and text typed in the editor is never that. */\nfunction turn_config(base: AcpFlags, workspace: string, task: string, env: Env): ResolvedConfig {\n const resolved = resolve_config(\n { ...base, workspace, prompt: STAND_IN_TASK, criteria: STAND_IN_TASK },\n { env, uncontained_builder: 'ask' },\n );\n return { ...resolved, prompt: task, criteria: task };\n}\n\n/** Only the builder's text is the reply. The critic's calls stream raw verdict\n * JSON, and nothing else in the run streams text. */\nfunction stream_route(step_id: string): AcpStreamRoute {\n return step_id === 'builder' ? 'message' : 'none';\n}\n\n/** What one session's turns share: the flags, the environment each turn's\n * config reads, the session's workspace, both seats' tools, and how the check\n * runs. */\ntype TurnDeps = {\n base: AcpFlags;\n env: Env;\n workspace: string;\n seats: NonNullable<OrchestratorDeps['seats']>;\n check: CheckGate;\n};\n\n/** One prompt: a volley run on the session's workspace, its events flowing\n * into the turn's own trajectory, then its summary as the turn's last event.\n * A failure is summarized too, naming the round it reached, and the turn ends\n * normally, so the session's history keeps the request for a retry. A turn\n * whose own signal fired rethrows, and ends cancelled. Resolves to the run's\n * result, or null when it failed. */\nasync function run_turn(deps: TurnDeps, turn: AcpTurn, ctx: RunContext): Promise<RunResult | null> {\n const rounds = follow_rounds(ctx.trajectory);\n try {\n const config = turn_config(deps.base, deps.workspace, turn_task(turn), deps.env);\n const result = await run_volley(config, {\n renderer: create_renderer({\n mode: 'quiet',\n show_thinking: false,\n color: false,\n max_cost_usd: config.max_cost_usd,\n }),\n seats: deps.seats,\n check: deps.check,\n trajectory: rounds.sink,\n abort: ctx.abort,\n install_signal_handlers: false,\n });\n ctx.emit(summary_event(build_run_summary(config, result)));\n return result;\n } catch (err) {\n if (ctx.abort.aborted) throw err;\n ctx.emit(failure_event(err, rounds.round()));\n return null;\n }\n}\n\n/** The flow for one session: both seats' tools and the check's gate are\n * built once, from the session, and each prompt runs volley on the session's\n * `cwd` with them. */\nfunction session_flow(\n base: AcpFlags,\n env: Env,\n): (session: AcpSession) => Step<AcpTurn, RunResult | null> {\n return (session) => {\n const { builder, critic, check } = acp_seat_tools(session, { env });\n const deps: TurnDeps = { base, env, workspace: session.cwd, seats: { builder, critic }, check };\n return step('acp_turn', (turn: AcpTurn, ctx) => run_turn(deps, turn, ctx), {\n description: \"one volley run on the session's workspace, per prompt\",\n });\n };\n}\n\ntype AcpServeOptions = {\n /** Reported to the client as the agent's version. */\n version: string;\n /** Where each turn's config reads its environment; default: the process's. */\n env?: Env;\n};\n\n/** The modes a session offers outside a container with no opt-out, where\n * nothing but a person stands between a command and the host: Auto, which\n * runs every command unasked, is left out. */\nconst HOST_MODES: ReadonlyArray<AcpMode> = ['manual', 'accept_edits'];\n\n/** What `serve_acp` serves: volley, per session, starting each in Manual, on\n * the folder the session opened alone, since the check, the change list, and\n * the critic look nowhere else. The builder's streamed text and volley's own\n * lines make the whole reply, ending with the summary, so `to_text` adds\n * nothing. */\nexport function acp_serve_config(\n base: AcpFlags,\n options: AcpServeOptions,\n): ServeAcpConfig<AcpTurn, RunResult | null> {\n const env = options.env ?? process.env;\n return {\n name: 'volley',\n version: options.version,\n default_mode: 'manual',\n additional_directories: false,\n ...(unguarded_builder(base, env) ? { modes: HOST_MODES } : {}),\n flow: session_flow(base, env),\n to_input: (turn) => turn,\n stream: stream_route,\n to_updates: progress_updates,\n to_text: () => '',\n };\n}\n","/**\n * Exit codes and the mapping from fascicle's error taxonomy plus\n * volley's own tagged errors onto them.\n */\nimport { error_kind } from './types.js';\nimport type { PhaseError, RunStatus } from './types.js';\n\nexport const EXIT_SUCCESS = 0;\nexport const EXIT_BUDGET_EXHAUSTED = 2;\nexport const EXIT_BUILDER_ERROR = 3;\nexport const EXIT_CHECK_ERROR = 4;\nexport const EXIT_CONFIG_ERROR = 5;\nexport const EXIT_CRITIC_ERROR = 6;\nexport const EXIT_COST_CAP = 7;\n/** The builder edited the gate that judges it and `--fail-on-gate-edit` was set:\n * distinct from a failed check (4) and from a budget exhaustion (2), because\n * nothing failed — the run refused to count a pass it could not trust. */\nexport const EXIT_GATE_EDIT = 8;\nexport const EXIT_INTERRUPTED = 130;\n\nexport function exit_code_for_status(status: RunStatus): number {\n switch (status) {\n case 'success':\n return EXIT_SUCCESS;\n case 'budget_exhausted':\n // A critique that didn't pass exits as a run that didn't converge does.\n case 'rejected':\n return EXIT_BUDGET_EXHAUSTED;\n case 'cost_cap_reached':\n return EXIT_COST_CAP;\n case 'gate_edit_blocked':\n return EXIT_GATE_EDIT;\n case 'interrupted':\n return EXIT_INTERRUPTED;\n default:\n return EXIT_BUILDER_ERROR;\n }\n}\n\n/** Error kinds fascicle raises for provider-level failures. */\nconst PROVIDER_ERROR_KINDS = new Set([\n 'provider_error',\n 'provider_auth_error',\n 'provider_not_configured_error',\n 'provider_capability_error',\n 'claude_cli_error',\n 'rate_limit_error',\n 'engine_disposed_error',\n 'timeout_error',\n]);\n\nexport function exit_code_for_error(err: unknown): number {\n const kind = error_kind(err);\n if (kind === 'aborted_error') return EXIT_INTERRUPTED;\n if (kind === 'config_error' || kind === 'engine_config_error') {\n return EXIT_CONFIG_ERROR;\n }\n if (kind === 'check_error') return EXIT_CHECK_ERROR;\n if (kind === 'schema_validation_error') return EXIT_CRITIC_ERROR;\n if (kind === 'phase_error') {\n const phase = (err as PhaseError).phase;\n const cause_kind = error_kind((err as PhaseError).cause);\n if (cause_kind === 'aborted_error') return EXIT_INTERRUPTED;\n if (phase === 'critic') return EXIT_CRITIC_ERROR;\n if (phase === 'check') return EXIT_CHECK_ERROR;\n return EXIT_BUILDER_ERROR;\n }\n if (kind !== null && PROVIDER_ERROR_KINDS.has(kind)) {\n return EXIT_BUILDER_ERROR;\n }\n return EXIT_BUILDER_ERROR;\n}\n","/**\n * `volley matrix` (v0.4.1): sweep a set of builder×critic *model*\n * combinations serially over one otherwise-fixed config, then aggregate every\n * run's `comparison` block into a single table. A subcommand — not a bash\n * wrapper around `docker run` — so it reuses `resolve_config`, the forced\n * per-combo worktree reset, and the enriched summary writer instead of\n * reimplementing them.\n *\n * Execution is serial by design: the local providers share one GPU, so\n * parallel combos would thrash the Ollama model loader. Each combo forces\n * `--worktree --discard-worktree` for a clean per-combo reset: a sweep\n * wants verdicts, not effects, so every seat's work is thrown away with its\n * branch — never salvaged onto one, never squash-merged onto the operator's\n * branch.\n *\n * **A seat is measured over `repeat` attempts, not one.** A single run answers\n * \"did this pairing converge that time\", which is the only question n=1 can\n * answer honestly: local runs are stochastic, so one sample supports a *hard*\n * failure (`research/v3-comparison-finding.md` reproduced the qwen3.6 critic\n * death 2/2) and nothing else — not iterations-to-converge, not wall clock. With\n * `--repeat` the row reports a pass *rate* and averages over the attempts behind\n * it, and every attempt's own summary is kept.\n *\n * **A row says why a seat fell off**, not just that it did. `budget_exhausted`\n * is a status, not a diagnosis; the failing check slots, the criteria still\n * unmet, a cost cap, or a gate edit are. Each is read from the attempt's\n * `comparison` block and folded into one `reason`.\n *\n * Sweep-level exit semantics: an attempt that *runs* — even to a\n * non-success status — is a *result*, shown in the table; the sweep only\n * \"breaks\" (nonzero) when an attempt yields no recoverable summary at all.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { resolve_config } from './config.js';\nimport { run_volley } from './orchestrator.js';\nimport type { Renderer } from './render/renderer.js';\nimport { build_run_summary } from './summary.js';\nimport type { RunSummary } from './summary.js';\nimport { config_error } from './types.js';\nimport type { DegradeCause, ResolvedConfig, RunStatus, Verdict, VolleyConfig } from './types.js';\nimport { state_path } from './workspace.js';\n\n/** The sweep's nonzero exit: at least one attempt produced no summary at all.\n * Distinct from an attempt that merely did not converge — that is still a\n * result and the sweep exits 0. Kept matrix-local (not a phase exit code) so the\n * existing exit-code semantics are untouched. */\nexport const EXIT_MATRIX_INCOMPLETE = 1;\n\n/** How many times each seat runs when `--repeat` is not given. One attempt is\n * enough to smoke-test a pairing and is what a quick sweep wants; anything that\n * compares seats should raise it. */\nconst DEFAULT_REPEAT = 1;\n\n/** One builder×critic model pairing in the cross product. */\nexport type MatrixCombo = { builder: string; critic: string };\n\n/** One run of one seat: what the sweep reads back from that attempt's summary.\n * `status: 'broke'` means the attempt produced no summary at all — the only\n * outcome that fails the sweep. */\nexport type MatrixAttempt = {\n attempt: number;\n status: RunStatus | 'broke';\n converged: boolean;\n iterations_to_converge: number | null;\n wall_clock_ms: number | null;\n total_cost_usd: number | null;\n final_verdict: Verdict | null;\n /** The check slots failing on the last iteration that ran one. */\n failing_slots: string[];\n /** What the critic still judged unmet when the run stopped. */\n unmet_criteria: string[];\n gate_edits: string[];\n critic_degraded: boolean;\n /** Why this attempt's degraded verdicts degraded; empty when none did. */\n critic_degrade_causes: DegradeCause[];\n tool_calls: number;\n salvaged_tool_calls: number;\n error: string | null;\n /** Why this attempt did not converge, in a few words; null when it did. */\n reason: string | null;\n};\n\n/** One table row: a seat, aggregated over its attempts, with every attempt kept\n * for `--json` consumers that want the spread rather than the average. */\nexport type MatrixRow = {\n builder: string;\n critic: string;\n /** Attempts made, and how many converged: the row's headline. */\n runs: number;\n converged: number;\n /** Mean over *converged* attempts — averaging in a run that never converged\n * would report an iteration count that never happened. Null when none did. */\n mean_iterations: number | null;\n /** Mean over every attempt that reported a wall clock, converged or not: a\n * seat that burns twenty minutes before giving up costs you that either way. */\n mean_wall_clock_ms: number | null;\n mean_cost_usd: number | null;\n /** Salvaged tool calls over total tool calls across all attempts — a ratio of\n * totals, not a mean of ratios, so a busy attempt weighs more than a quiet one. */\n salvage_rate: number | null;\n /** True when *any* attempt's critic degraded to the tool-less rung. */\n critic_degraded: boolean;\n /** Every reason any attempt's critic degraded, each once. */\n critic_degrade_causes: DegradeCause[];\n /** Every gate path any attempt's builder edited (`src/changes.ts`). */\n gate_edits: string[];\n /** The most recent non-converged attempt's reason; null when all converged. */\n reason: string | null;\n attempts: MatrixAttempt[];\n};\n\nexport type MatrixOutcome = { rows: MatrixRow[]; ok: boolean };\n\n/** Runs one attempt at one seat and returns its enriched summary. Injected in\n * tests so the cross product, repeats, persistence, and table can be exercised\n * with stubbed runs. */\nexport type ComboRunner = (\n base: VolleyConfig,\n combo: MatrixCombo,\n renderer: Renderer,\n attempt: number,\n) => Promise<RunSummary>;\n\nexport type RunMatrixOptions = {\n base: VolleyConfig;\n builders: string[];\n critics: string[];\n matrix_dir: string;\n renderer: Renderer;\n repeat?: number;\n run_combo?: ComboRunner;\n};\n\n/** Split a `--builders`/`--critics` value into a trimmed, non-empty model\n * list. Empty or all-whitespace is a config error, refused before any spend. */\nexport function parse_model_list(value: string | undefined, flag: string): string[] {\n const items = (value ?? '')\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n if (items.length === 0) {\n throw config_error(`${flag} must be a comma-separated list of at least one model`);\n }\n return items;\n}\n\n/** Validate `--repeat`: attempts per seat, a positive integer. Refused before\n * any spend, like every other cap. */\nexport function parse_repeat(value: number | string | undefined): number {\n if (value === undefined) return DEFAULT_REPEAT;\n const repeat = Number(value);\n if (!Number.isInteger(repeat) || repeat < 1) {\n throw config_error(`--repeat must be a positive integer; got: ${String(value)}`);\n }\n return repeat;\n}\n\n/** The config one seat runs under: the base task with this combo's models and a\n * forced throw-away worktree — `--worktree` isolates the seat's effects and\n * `--discard-worktree` throws them away at teardown, so a sweep of N seats leaves\n * neither N branches behind nor N squash commits on the operator's branch. */\nexport function combo_config(base: VolleyConfig, combo: MatrixCombo): VolleyConfig {\n return {\n ...base,\n builder_model: combo.builder,\n critic_model: combo.critic,\n worktree: true,\n discard_worktree: true,\n };\n}\n\n/** The default combo runner: resolve this seat's config, run the loop, and fold\n * on the comparison block.\n * If the run throws (an unsalvageable phase failure), recover the best-effort\n * `summary.json` the orchestrator wrote so the attempt is still a result;\n * rethrow only when nothing is recoverable — then the sweep breaks. */\nconst default_run_combo: ComboRunner = async (base, combo, renderer) => {\n const config = resolve_config(combo_config(base, combo));\n try {\n const result = await run_volley(config, { renderer });\n return build_run_summary(config, result);\n } catch (err) {\n const recovered = read_run_summary(config);\n if (recovered === null) throw err;\n return recovered;\n }\n};\n\n/** Read a run's `summary.json` from its state directory (a base config's\n * `state_dir` moves it there), or null if it is missing/unparseable — the\n * signal `default_run_combo` uses to tell a merely-errored attempt (summary on\n * disk) from a truly broken one (nothing to recover). */\nfunction read_run_summary(config: ResolvedConfig): RunSummary | null {\n const path = state_path(config, 'summary.json');\n if (!existsSync(path)) return null;\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as RunSummary;\n } catch {\n return null;\n }\n}\n\n/** How much of a criterion or an error a `reason` carries before it is cut —\n * enough to recognise which one, short enough for a table cell. */\nconst REASON_MAX = 44;\n\nfunction clip(text: string): string {\n const flat = text.replaceAll(/\\s+/g, ' ').trim();\n return flat.length > REASON_MAX ? `${flat.slice(0, REASON_MAX - 1)}…` : flat;\n}\n\n/** The check slots failing on the last iteration that ran a check. */\nfunction last_failing_slots(summary: RunSummary): string[] {\n const ran = summary.comparison.check_trajectory.filter((point) => point.ran);\n return ran.at(-1)?.failing_slots ?? [];\n}\n\n/**\n * Why this attempt did not converge, in a few words — the column that turns a\n * sweep from \"which seats passed\" into \"where each one falls off\".\n *\n * Ordered by how *specific* the answer is: a halt names itself, a failing check\n * names its slots, and a run that was gated only by the critic names what it\n * still judged unmet. `budget_exhausted` with nothing else to say means the loop\n * ran out of iterations while the critic kept asking for changes it did not\n * enumerate — worth seeing as exactly that.\n */\nexport function failure_reason(summary: RunSummary): string | null {\n if (summary.status === 'success') return null;\n if (summary.status === 'cost_cap_reached') return 'cost cap';\n if (summary.status === 'interrupted') return 'interrupted';\n if (summary.status === 'gate_edit_blocked') {\n return clip(`gate edit: ${summary.comparison.gate_edits.join(', ')}`);\n }\n const failing = last_failing_slots(summary);\n if (failing.length > 0) return clip(`check: ${failing.join(', ')}`);\n const unmet = summary.comparison.unmet_criteria;\n if (unmet.length === 1) return clip(`unmet: ${unmet[0] ?? ''}`);\n if (unmet.length > 1) return clip(`unmet: ${String(unmet.length)} criteria`);\n return summary.status === 'error' ? 'run error' : String(summary.status);\n}\n\nfunction attempt_from_summary(attempt: number, summary: RunSummary): MatrixAttempt {\n const c = summary.comparison;\n return {\n attempt,\n status: summary.status,\n converged: summary.status === 'success',\n iterations_to_converge: c.iterations_to_converge,\n wall_clock_ms: c.wall_clock_ms,\n total_cost_usd: c.total_cost_usd,\n final_verdict: c.final_verdict,\n failing_slots: last_failing_slots(summary),\n unmet_criteria: c.unmet_criteria,\n gate_edits: c.gate_edits,\n critic_degraded: c.critic_degraded,\n critic_degrade_causes: c.critic_degrade_causes,\n tool_calls: c.local_salvage.tool_calls,\n salvaged_tool_calls: c.local_salvage.salvaged_tool_calls,\n error: null,\n reason: failure_reason(summary),\n };\n}\n\nfunction broke_attempt(attempt: number, message: string): MatrixAttempt {\n return {\n attempt,\n status: 'broke',\n converged: false,\n iterations_to_converge: null,\n wall_clock_ms: null,\n total_cost_usd: null,\n final_verdict: null,\n failing_slots: [],\n unmet_criteria: [],\n gate_edits: [],\n critic_degraded: false,\n critic_degrade_causes: [],\n tool_calls: 0,\n salvaged_tool_calls: 0,\n error: message,\n reason: clip(`broke: ${message}`),\n };\n}\n\nfunction mean(values: number[]): number | null {\n if (values.length === 0) return null;\n return values.reduce((total, value) => total + value, 0) / values.length;\n}\n\nfunction defined_numbers(values: Array<number | null>): number[] {\n return values.filter((value): value is number => value !== null);\n}\n\n/** Fold a seat's attempts into one row. Every aggregate names the population it\n * is over (see `MatrixRow`), because averaging the wrong set is how a sweep\n * reports a number nothing actually did. */\nfunction aggregate_row(combo: MatrixCombo, attempts: MatrixAttempt[]): MatrixRow {\n const converged = attempts.filter((attempt) => attempt.converged);\n const tool_calls = attempts.reduce((total, attempt) => total + attempt.tool_calls, 0);\n const salvaged = attempts.reduce((total, attempt) => total + attempt.salvaged_tool_calls, 0);\n const gate_edits = new Set(attempts.flatMap((attempt) => attempt.gate_edits));\n return {\n builder: combo.builder,\n critic: combo.critic,\n runs: attempts.length,\n converged: converged.length,\n mean_iterations: mean(defined_numbers(converged.map((a) => a.iterations_to_converge))),\n mean_wall_clock_ms: mean(defined_numbers(attempts.map((a) => a.wall_clock_ms))),\n mean_cost_usd: mean(defined_numbers(attempts.map((a) => a.total_cost_usd))),\n salvage_rate: tool_calls === 0 ? null : salvaged / tool_calls,\n critic_degraded: attempts.some((attempt) => attempt.critic_degraded),\n critic_degrade_causes: [\n ...new Set(attempts.flatMap((attempt) => attempt.critic_degrade_causes)),\n ],\n gate_edits: [...gate_edits].toSorted(),\n reason: attempts.findLast((attempt) => !attempt.converged)?.reason ?? null,\n attempts,\n };\n}\n\nfunction cross_product(builders: string[], critics: string[]): MatrixCombo[] {\n return builders.flatMap((builder) => critics.map((critic) => ({ builder, critic })));\n}\n\nfunction combo_dir(matrix_dir: string, combo: MatrixCombo): string {\n return join(matrix_dir, `${slug(combo.builder)}__${slug(combo.critic)}`);\n}\n\n/** Filesystem-safe slug for a model name in a `.volley-matrix/` path (model\n * ids carry `:` and `/`, e.g. `qwen3.6:latest`). */\nfunction slug(model: string): string {\n return model.replace(/[^a-zA-Z0-9._-]/g, '_');\n}\n\n/** One attempt's run summary, copied out of the run's own state into the\n * sweep, so the sweep keeps its evidence beside its table. Every attempt gets\n * its own `run-NN/` so a repeated seat keeps all of its evidence, not just the\n * last run's. */\nfunction persist_attempt(\n matrix_dir: string,\n combo: MatrixCombo,\n attempt: number,\n summary: RunSummary,\n): void {\n const dir = join(combo_dir(matrix_dir, combo), `run-${String(attempt).padStart(2, '0')}`);\n mkdirSync(dir, { recursive: true });\n writeFileSync(join(dir, 'summary.json'), `${JSON.stringify(summary, null, 2)}\\n`);\n}\n\n/** The whole sweep as one machine-readable document, written where the run state\n * is — a long ladder sweep is worth re-reading without re-running. */\nfunction persist_matrix(matrix_dir: string, rows: MatrixRow[]): string {\n mkdirSync(matrix_dir, { recursive: true });\n const path = join(matrix_dir, 'matrix.json');\n writeFileSync(path, `${JSON.stringify({ combos: rows }, null, 2)}\\n`);\n return path;\n}\n\n/** Run one seat `repeat` times, serially, keeping each attempt's run state. */\nasync function run_combo_attempts(\n options: Required<Pick<RunMatrixOptions, 'base' | 'matrix_dir' | 'renderer'>> & {\n combo: MatrixCombo;\n repeat: number;\n run_combo: ComboRunner;\n tag: string;\n },\n): Promise<{ attempts: MatrixAttempt[]; ok: boolean }> {\n const { combo, renderer, repeat, tag } = options;\n const attempts: MatrixAttempt[] = [];\n let ok = true;\n for (let attempt = 1; attempt <= repeat; attempt += 1) {\n const label = repeat === 1 ? tag : `${tag} run ${String(attempt)}/${String(repeat)}`;\n renderer.info(`${label}: builder=${combo.builder} critic=${combo.critic}`);\n try {\n const summary = await options.run_combo(options.base, combo, renderer, attempt);\n persist_attempt(options.matrix_dir, combo, attempt, summary);\n const result = attempt_from_summary(attempt, summary);\n attempts.push(result);\n renderer.info(`${label}: → ${result.status}${result.reason === null ? '' : ` (${result.reason})`}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n attempts.push(broke_attempt(attempt, message));\n ok = false;\n renderer.warn(`${label}: produced no summary: ${message}`);\n }\n }\n return { attempts, ok };\n}\n\n/** Run the builder×critic cross product serially — `repeat` attempts per seat —\n * persisting every attempt's summary and aggregating them into one table. */\nexport async function run_matrix(options: RunMatrixOptions): Promise<MatrixOutcome> {\n const { base, matrix_dir, renderer } = options;\n const run_combo = options.run_combo ?? default_run_combo;\n const repeat = options.repeat ?? DEFAULT_REPEAT;\n const combos = cross_product(options.builders, options.critics);\n renderer.info(\n `matrix: ${String(combos.length)} seat(s) × ${String(repeat)} run(s) = ` +\n `${String(combos.length * repeat)} run(s), serially`,\n );\n\n const rows: MatrixRow[] = [];\n let ok = true;\n let index = 0;\n for (const combo of combos) {\n index += 1;\n const outcome = await run_combo_attempts({\n base,\n matrix_dir,\n renderer,\n combo,\n repeat,\n run_combo,\n tag: `matrix [${String(index)}/${String(combos.length)}]`,\n });\n ok = ok && outcome.ok;\n rows.push(aggregate_row(combo, outcome.attempts));\n }\n\n renderer.info(render_matrix_table(rows));\n renderer.info(`matrix: wrote ${persist_matrix(matrix_dir, rows)}`);\n return { rows, ok };\n}\n\nconst MATRIX_COLUMNS = [\n 'builder',\n 'critic',\n 'pass',\n 'iters',\n 'wall',\n 'cost',\n 'salvage',\n 'flags',\n 'why',\n] as const;\n\nfunction format_wall(ms: number | null): string {\n return ms === null ? '—' : `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction format_rate(rate: number | null): string {\n return rate === null ? '—' : `${String(Math.round(rate * 100))}%`;\n}\n\nfunction format_cost(usd: number | null): string {\n return usd === null ? '—' : `$${usd.toFixed(2)}`;\n}\n\nfunction format_iterations(iterations: number | null): string {\n return iterations === null ? '—' : iterations.toFixed(1);\n}\n\n/** How the degraded flag names a cause in its cell. */\nconst DEGRADE_CAUSE_LABELS: Readonly<Record<DegradeCause, string>> = {\n stream_error: 'stream',\n step_exhaustion: 'steps',\n};\n\n/** The degraded flag with what caused it, `deg:stream`, `deg:steps`, or\n * `deg:stream+steps`, since a bare `deg` can't say whether the critic kept\n * dying or kept reading. */\nfunction degraded_flag(row: MatrixRow): string {\n const causes = row.critic_degrade_causes.map((cause) => DEGRADE_CAUSE_LABELS[cause]);\n return causes.length === 0 ? 'deg' : `deg:${causes.join('+')}`;\n}\n\n/** The two facts that qualify a pass rather than explain a failure, so they do\n * not have to compete with `why` for the same cell. */\nfunction format_flags(row: MatrixRow): string {\n const flags = [\n row.critic_degraded ? degraded_flag(row) : null,\n row.gate_edits.length > 0 ? 'gate' : null,\n ].filter((flag): flag is string => flag !== null);\n return flags.length === 0 ? '—' : flags.join(',');\n}\n\nfunction cell_values(row: MatrixRow): string[] {\n return [\n row.builder,\n row.critic,\n `${String(row.converged)}/${String(row.runs)}`,\n format_iterations(row.mean_iterations),\n format_wall(row.mean_wall_clock_ms),\n format_cost(row.mean_cost_usd),\n format_rate(row.salvage_rate),\n format_flags(row),\n row.reason ?? '—',\n ];\n}\n\n/** Render the aggregate table as a padded, self-aligning block (stderr).\n * Sourced entirely from the rows' `comparison`-derived fields. */\nexport function render_matrix_table(rows: MatrixRow[]): string {\n const header: string[] = [...MATRIX_COLUMNS];\n const body = rows.map(cell_values);\n const widths = header.map((title, col) =>\n Math.max(title.length, ...body.map((cells) => (cells[col] ?? '').length)),\n );\n const render_line = (cells: string[]): string =>\n cells.map((cell, col) => cell.padEnd(widths[col] ?? 0)).join(' ').trimEnd();\n const separator = widths.map((w) => '─'.repeat(w)).join(' ');\n return [render_line(header), separator, ...body.map(render_line)].join('\\n');\n}\n","/**\n * `--dry-run` preflight: prove a run can\n * proceed *before any model spend*. It always renders the resolved config and,\n * when checkride is the resolved check, runs `checkride doctor`. Under\n * `--worktree` it also predicts what a successful run will do with its effects\n * (`report_worktree_fate`) — integrate, salvage onto the run branch, or\n * discard — so no fate arrives as a surprise at teardown.\n *\n * For a containment-requiring tool-loop builder (local or `openrouter`) — run\n * from *inside* its container — it additionally checks the two things that\n * contained build needs: the toolchain is present and the worktree is\n * creatable. Any containment check failing exits 5 (`EXIT_CONFIG_ERROR`).\n *\n * Every seat on a URL-taking provider then gets its model endpoint probed: each\n * seat's own resolved base URL (`seat_base_url`, which crosses a loopback\n * authority to the gateway when `VOLLEY_MODEL_HOST` is set — engine.ts), one\n * probe when both seats share a server. An unreachable endpoint exits 5 too.\n *\n * The all-Claude path runs *none* of the containment checks or probes — it\n * never requires Docker or a model server — so they never contribute an exit 5\n * on that path.\n *\n * A *local critic* additionally gets the critic-seat canary: one tiny $0\n * generate through the real critic tool wiring, run\n * whatever the builder provider is. A degradable failure warns and predicts\n * `critic_degraded`; only a would-fail-even-degraded combo (endpoint down,\n * model missing) exits 5. The `claude_cli` and `openrouter` critic paths never\n * run it: a canary that costs nothing on a local model costs money there.\n *\n * The probes are injectable so the exit-code contract is unit-testable without\n * a daemon, a git repo, or a live model endpoint.\n */\nimport { spawnSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { capture_baseline } from './changes.js';\nimport { detect_containment } from './containment.js';\nimport { critic_canary } from './critic/run.js';\nimport { command_env, create_volley_engine, seat_base_url, takes_seat_url } from './engine.js';\nimport type { Engine } from './engine.js';\nimport { EXIT_CONFIG_ERROR, EXIT_SUCCESS } from './exit_codes.js';\nimport type { Renderer } from './render/renderer.js';\nimport type { BuilderProvider, CriticProvider, ResolvedConfig } from './types.js';\nimport { run_state_dir } from './workspace.js';\nimport { build_root, report_worktree_fate } from './worktree.js';\n\n/** Executables the in-container builder shells out to (checkride/pnpm invoke\n * node; git drives the worktree). Their presence proves the sandbox image\n * carries the toolchain (Dockerfile). */\nconst REQUIRED_TOOLCHAIN: ReadonlyArray<string> = ['node', 'pnpm', 'git'];\n\n/** A short cap on the endpoint probe so a wrong/unreachable host fails fast\n * rather than hanging the preflight before the loop even starts. */\nconst ENDPOINT_PROBE_TIMEOUT_MS = 3000;\n\n/** Builders that drive their model through volley's own tool loop, local or\n * hosted, so the containment preflight applies. `claude_cli` never does. */\nexport function is_tool_loop_builder(\n provider: BuilderProvider,\n): provider is 'ollama' | 'lmstudio' | 'openrouter' {\n return provider !== 'claude_cli';\n}\n\n/** Critics that run a local model through volley's own tool wiring, so the\n * critic-seat canary applies. `claude_cli` never does: that path is\n * proven and its calls cost real money. Nor does `openrouter`, whose calls cost\n * money too. */\nexport function is_local_critic(\n provider: CriticProvider,\n): provider is 'ollama' | 'lmstudio' {\n return provider === 'ollama' || provider === 'lmstudio';\n}\n\n/** One model server a seat (or both seats) will reach, and who reaches it. */\ntype SeatEndpoint = { seats: string; url: string };\n\n/** The model endpoint each seat on a URL-taking provider will hit, resolved by\n * the same `seat_base_url` the run uses, so the preflight probes exactly what\n * the run will hit. Two seats on one server are merged into one endpoint, so\n * a shared server is probed once. */\nfunction seat_endpoints(\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n): SeatEndpoint[] {\n const builder = takes_seat_url(config.builder_provider)\n ? seat_base_url(config.builder_provider, config.builder_url, env)\n : null;\n const critic = takes_seat_url(config.critic_provider)\n ? seat_base_url(config.critic_provider, config.critic_url, env)\n : null;\n if (builder !== null && builder === critic) {\n return [{ seats: 'builder and critic', url: builder }];\n }\n return [\n ...(builder === null ? [] : [{ seats: 'builder', url: builder }]),\n ...(critic === null ? [] : [{ seats: 'critic', url: critic }]),\n ];\n}\n\n/** Probe each seat's model endpoint before any spend. False, after naming the\n * seat and the URL, when one is unreachable. */\nasync function probe_seat_endpoints(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined>,\n reachable: (url: string) => Promise<boolean>,\n): Promise<boolean> {\n for (const { seats, url } of seat_endpoints(config, env)) {\n if (!(await reachable(url))) {\n renderer.error(`preflight: ${seats} model endpoint unreachable: ${url}`);\n return false;\n }\n renderer.info(`${seats} model endpoint: reachable (${url})`);\n }\n return true;\n}\n\n/** Which required executables are not runnable on the current PATH. */\nfunction toolchain_missing(tools: ReadonlyArray<string> = REQUIRED_TOOLCHAIN): string[] {\n return tools.filter((tool) => {\n const result = spawnSync(tool, ['--version'], { env: command_env(process.env), stdio: 'ignore' });\n return result.error !== undefined || result.status !== 0;\n });\n}\n\n/** Non-destructive check that a git worktree could be created here: git runs and\n * `workspace` is a git work tree. Does not create anything (create/rotate is the\n * run's job — worktree.ts). */\nfunction worktree_creatable(workspace: string): { ok: boolean; detail: string } {\n const repo = resolve(workspace);\n const version = spawnSync('git', ['--version'], { env: command_env(process.env), stdio: 'ignore' });\n if (version.error !== undefined || version.status !== 0) {\n return { ok: false, detail: 'git is not available' };\n }\n if (!existsSync(resolve(repo, '.git'))) {\n return { ok: false, detail: `${repo} is not a git repository` };\n }\n const inside = spawnSync('git', ['-C', repo, 'rev-parse', '--is-inside-work-tree'], {\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (inside.status !== 0 || (inside.stdout ?? '').trim() !== 'true') {\n return { ok: false, detail: `${repo} is not a git work tree` };\n }\n return { ok: true, detail: repo };\n}\n\n/** Reachability probe: any HTTP response (even a 404) proves the TCP connect\n * landed; a thrown error (connection refused, DNS failure, timeout) means the\n * endpoint is unreachable. */\nasync function endpoint_reachable(\n url: string,\n timeout_ms: number = ENDPOINT_PROBE_TIMEOUT_MS,\n): Promise<boolean> {\n try {\n await fetch(url, { method: 'GET', signal: AbortSignal.timeout(timeout_ms) });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Injectable probes so the exit-code contract is testable without a daemon,\n * git, or a live endpoint; each defaults to the real implementation above.\n * `canary_engine` fakes the *engine*, not the canary, so the tests exercise the\n * real two-rung classification in `critic_canary`. */\nexport type PreflightProbes = {\n toolchain_missing?: (tools?: ReadonlyArray<string>) => string[];\n worktree_creatable?: (workspace: string) => { ok: boolean; detail: string };\n endpoint_reachable?: (url: string) => Promise<boolean>;\n checkride_doctor?: (workspace: string) => boolean;\n canary_engine?: (\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n ) => Engine;\n};\n\n/** The canary drives the same engine construction the run itself uses, with the\n * critic role's provider wired in at the critic seat's URL; consulted only after\n * `is_local_critic` says the canary applies, so the claude_cli critic path never\n * builds an engine. */\nfunction default_canary_engine(\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n): Engine {\n return create_volley_engine({\n workspace: config.workspace,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n env,\n });\n}\n\n/** A seat's info line: its model and provider, and the endpoint a seat on a\n * URL-taking provider will reach. */\nfunction seat_line(\n seat: 'builder' | 'critic',\n model: string,\n provider: BuilderProvider | CriticProvider,\n url: string | null,\n env: Record<string, string | undefined>,\n): string {\n const endpoint = takes_seat_url(provider)\n ? `, endpoint: ${seat_base_url(provider, url, env)}`\n : '';\n return `${seat} model: ${model} (provider: ${provider}${endpoint})`;\n}\n\n/**\n * What this run will do about a builder that edits its own gate, said before any\n * spend — the same predict-then-warn shape as the worktree fate and the\n * critic-seat canary.\n *\n * The warning that earns its place here: `--fail-on-gate-edit` outside a git\n * repository is a refusal that cannot fire. Change detection needs a baseline to\n * diff against, so a non-git workspace silently reports nothing — and an\n * operator who asked for the refusal should learn that now, not from a summary\n * whose `gate_edits` is empty for the wrong reason.\n */\nfunction report_gate_posture(config: ResolvedConfig, renderer: Renderer): void {\n const root = build_root(config.workspace, config.worktree);\n const detectable = capture_baseline(root) !== null || existsSync(join(root, '.git'));\n if (config.fail_on_gate_edit && !detectable) {\n renderer.warn(\n '--fail-on-gate-edit is set, but the build root is not a git repository, so there is no ' +\n 'baseline to diff against and gate edits cannot be detected. The flag will not fire: ' +\n 'run against a git workspace to get the refusal you asked for.',\n );\n return;\n }\n if (config.gate_paths.length === 0) {\n const edits = config.mode === 'critique' ? 'changes' : 'builder edits';\n renderer.info(`gate: no gate paths configured; ${edits} to tests and check config are not flagged.`);\n return;\n }\n renderer.info(\n `gate: watching ${String(config.gate_paths.length)} path pattern(s)` +\n (config.fail_on_gate_edit\n ? ' — a builder edit to any of them halts the run (--fail-on-gate-edit, exit 8).'\n : ' — edits are reported to the critic and recorded in the summary, not refused.'),\n );\n}\n\nfunction run_checkride_doctor(workspace: string): boolean {\n const doctor = spawnSync('pnpm', ['exec', 'checkride', 'doctor'], {\n cwd: workspace,\n env: command_env(process.env),\n stdio: ['ignore', 'ignore', 'inherit'],\n });\n return doctor.error === undefined && doctor.status === 0;\n}\n\n/**\n * Run the preflight and return its exit code (`EXIT_SUCCESS` or, on any failure,\n * `EXIT_CONFIG_ERROR` = 5). `env` supplies the endpoint crossing (`VOLLEY_MODEL_HOST`)\n * and matches what the run itself will read.\n */\nexport async function preflight(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined>,\n probes: PreflightProbes = {},\n): Promise<number> {\n const tool_loop_builder = is_tool_loop_builder(config.builder_provider);\n\n renderer.info(`dry run: config valid (run ${config.run_id})`);\n renderer.info(`workspace: ${config.workspace}`);\n // Each run gets its own directory under the root; a dry run creates none.\n renderer.info(\n config.state_dir === null ? `state: ${run_state_dir(config)}` : `state root: ${config.state_dir}`,\n );\n renderer.info(`check: ${config.check} (resolved: ${config.check_resolved})`);\n if (config.mode === 'critique') {\n renderer.info('builder: none (a critique checks and critiques the change once)');\n } else {\n renderer.info(\n seat_line('builder', config.builder_model, config.builder_provider, config.builder_url, env),\n );\n renderer.info(`builder max steps: ${config.builder_max_steps}`);\n renderer.info(`builder tool calls per turn: ${config.builder_max_tool_calls}`);\n renderer.info(\n `builder output tokens per turn: ${config.builder_max_output_tokens ?? \"the provider's limit\"}`,\n );\n }\n if (tool_loop_builder) {\n const contained = detect_containment(env);\n renderer.info(\n contained\n ? 'containment: inside the sandbox container (VOLLEY_CONTAINED)'\n : 'containment: uncontained on the host (--allow-unsandboxed-builder)',\n );\n renderer.info(`sandbox image: ${config.sandbox_image}`);\n }\n renderer.info(\n `critic: ${config.critic_preset}${config.critic_prompt_path !== null ? ` (${config.critic_prompt_path})` : ''}`,\n );\n renderer.info(\n seat_line('critic', config.critic_model, config.critic_provider, config.critic_url, env),\n );\n // What a successful run does with its effects, predicted here for any\n // builder provider — the worktree's fate is not a containment concern, and\n // `--worktree` without `--git` must not quietly end in a discarded build.\n report_worktree_fate(config, renderer);\n report_gate_posture(config, renderer);\n\n if (config.check_resolved === 'checkride') {\n const doctor = probes.checkride_doctor ?? run_checkride_doctor;\n if (!doctor(config.workspace)) {\n renderer.error('checkride doctor failed; fix the workspace check pipeline before running');\n return EXIT_CONFIG_ERROR;\n }\n renderer.info('checkride doctor: ok');\n }\n\n // Containment preflight — tool-loop builder only, so the all-Claude path\n // never reaches an exit 5 from here.\n if (tool_loop_builder) {\n const missing = (probes.toolchain_missing ?? toolchain_missing)(REQUIRED_TOOLCHAIN);\n if (missing.length > 0) {\n renderer.error(`preflight: missing toolchain in the sandbox: ${missing.join(', ')}`);\n return EXIT_CONFIG_ERROR;\n }\n renderer.info(`toolchain: ${REQUIRED_TOOLCHAIN.join(', ')} present`);\n\n if (config.worktree) {\n const worktree = (probes.worktree_creatable ?? worktree_creatable)(config.workspace);\n if (!worktree.ok) {\n renderer.error(`preflight: worktree not creatable: ${worktree.detail}`);\n return EXIT_CONFIG_ERROR;\n }\n renderer.info(`worktree: creatable (${worktree.detail})`);\n }\n }\n\n // Each URL-taking seat's own model endpoint, whatever the other seat runs on,\n // so a critic on a second machine is checked as surely as the builder's\n // server. The all-Claude path has no endpoint to probe.\n const reachable = probes.endpoint_reachable ?? endpoint_reachable;\n if (!(await probe_seat_endpoints(config, renderer, env, reachable))) {\n return EXIT_CONFIG_ERROR;\n }\n\n // Critic-seat canary — local critic only, whatever the\n // builder provider is, so a claude_cli-builder + local-critic run still gets\n // its doomed-combo warning before any builder spend. A degradable death warns\n // and predicts `critic_degraded` (refusing it would contradict the fallback\n // ladder); only a would-fail-even-degraded combo exits 5, named model×seat.\n if (is_local_critic(config.critic_provider)) {\n const engine = (probes.canary_engine ?? default_canary_engine)(config, env);\n const seat = `model '${config.critic_model}' in the critic seat (provider: ${config.critic_provider})`;\n try {\n const canary = await critic_canary(engine, config, env);\n if (canary.outcome === 'failed') {\n renderer.error(`preflight: critic canary failed — ${seat}: ${canary.detail}`);\n return EXIT_CONFIG_ERROR;\n }\n if (canary.outcome === 'degraded') {\n renderer.warn(\n `critic canary: ${seat} died on the tool-bearing call (${canary.detail}) ` +\n 'but survived tool-less; a real run will likely degrade to the ' +\n 'tool-less fallback and be marked critic_degraded',\n );\n } else {\n renderer.info(`critic canary: ok (${seat} answered through the real tool wiring)`);\n }\n } finally {\n await engine.dispose();\n }\n }\n\n return EXIT_SUCCESS;\n}\n","#!/usr/bin/env node\n/**\n * CLI entry point: cac argv parsing, dispatch, exit-code mapping.\n * Human progress goes to stderr; stdout carries machine output only.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { cac } from 'cac';\nimport type { Command } from 'cac';\nimport { serve_acp } from 'fascicle/acp';\nimport { ACP_MAX_ITERATIONS, acp_base_config, acp_serve_config } from './acp.js';\nimport {\n DEFAULT_CHECK,\n DEFAULT_SANDBOX_IMAGE,\n load_config_file,\n resolve_config,\n} from './config.js';\nimport { resolve_baseline } from './changes.js';\nimport { exit_code_for_error, exit_code_for_status, EXIT_SUCCESS } from './exit_codes.js';\nimport { find_run_state, load_resume_state } from './iteration.js';\nimport { EXIT_MATRIX_INCOMPLETE, parse_model_list, parse_repeat, run_matrix } from './matrix.js';\nimport { run_critique, run_volley } from './orchestrator.js';\nimport { preflight } from './preflight.js';\nimport { colors_enabled, shown } from './render/format.js';\nimport { create_renderer } from './render/renderer.js';\nimport type { Renderer, RenderMode } from './render/renderer.js';\nimport { config_error, error_kind } from './types.js';\nimport type {\n BuilderPermissionMode,\n BuilderProvider,\n CriticProvider,\n ResolvedConfig,\n RunResult,\n VolleyConfig,\n} from './types.js';\nimport { default_state_root, state_path } from './workspace.js';\n\n/** One help string for every command that takes a state root. */\nconst STATE_DIR_HELP =\n \"Keep each run's state under <path>/<run id>/ (default: $XDG_STATE_HOME/volley, else ~/.local/state/volley)\";\n\ntype CliFlags = {\n prompt?: string;\n workspace?: string;\n criteria?: string;\n check?: string;\n builderModel?: string;\n builderProvider?: string;\n builderUrl?: string;\n builderMaxSteps?: number;\n builderMaxToolCalls?: number;\n builderMaxOutputTokens?: number;\n allowUnsandboxedBuilder?: boolean;\n criticModel?: string;\n criticProvider?: string;\n criticUrl?: string;\n builderPermissionMode?: string;\n critic?: string;\n maxIterations?: number;\n maxCostUsd?: number;\n git?: boolean;\n worktree?: boolean;\n discardWorktree?: boolean;\n gatePaths?: string;\n failOnGateEdit?: boolean;\n sandboxImage?: string;\n stateDir?: string;\n /** A number when cac coerced a numeric-looking value (`0042` arrives as 42). */\n runId?: string | number;\n dryRun?: boolean;\n trustConfig?: boolean;\n config?: string;\n /** A number when cac coerced an all-digit revision, as it does `runId`. */\n baseline?: string | number;\n json?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n thinking?: boolean;\n};\n\ntype MatrixFlags = {\n config?: string;\n builders?: string;\n critics?: string;\n workspace?: string;\n repeat?: number;\n json?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n};\n\n/**\n * volley's own version for `--version`, read from the manifest rather than\n * repeated here — a literal drifts silently, since `pnpm version` bumps only\n * `package.json` (this one sat at `0.2.0` through three releases).\n *\n * Walks up from this module to the nearest `package.json`, the same shape\n * `presets_dir()` uses to find its files: the manifest sits directly above both\n * `src/` (under tsx) and `dist/` (the built bin, and the published package), so\n * one walk serves every entry path. Never throws — an unreadable manifest\n * reports `unknown` rather than failing every command over a version string.\n */\nexport function package_version(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const manifest = join(dir, 'package.json');\n if (existsSync(manifest)) {\n try {\n const version = (JSON.parse(readFileSync(manifest, 'utf8')) as { version?: unknown })\n .version;\n if (typeof version === 'string') return version;\n } catch {\n // A torn or unreadable manifest is not worth failing a run over.\n }\n }\n dir = dirname(dir);\n }\n return 'unknown';\n}\n\n/** Split a comma-separated `--gate-paths` value into globs. An all-empty value\n * yields an empty list — \"nothing is the gate\", which turns the report off. */\nfunction parse_glob_list(value: string): string[] {\n return value\n .split(',')\n .map((glob) => glob.trim())\n .filter((glob) => glob.length > 0);\n}\n\nfunction render_mode(config: ResolvedConfig): RenderMode {\n if (config.json) return 'json';\n if (config.quiet) return 'quiet';\n if (config.verbose) return 'verbose';\n return 'default';\n}\n\n/** `run_id` names the run whose trajectory the verbose hint points at; a\n * sweep passes a placeholder, since each seat has an id of its own. */\nfunction make_renderer(config: ResolvedConfig, run_id: string = config.run_id): Renderer {\n return create_renderer({\n mode: render_mode(config),\n show_thinking: config.show_thinking,\n color: colors_enabled(),\n max_cost_usd: config.max_cost_usd,\n trajectory_path: state_path({ ...config, run_id }, 'trajectory.jsonl'),\n });\n}\n\nfunction warn_api_key_meter(renderer: Renderer): void {\n if (process.env['ANTHROPIC_API_KEY'] !== undefined) {\n renderer.warn(\n 'ANTHROPIC_API_KEY is set: the claude CLI will bill this run against the API key, not a subscription. Know which meter you are on.',\n );\n }\n}\n\n/** One loud warning when a tool-loop builder is about to run *uncontained* on\n * the host via the opt-out. Config resolution has already refused this\n * unless volley is contained or the opt-out is set, so reaching here with the\n * opt-out active means the operator accepted the uncontained risk. */\nexport function warn_unsandboxed_builder(config: ResolvedConfig, renderer: Renderer): void {\n if (config.builder_provider !== 'claude_cli' && config.allow_unsandboxed_builder) {\n renderer.warn(\n `UNSANDBOXED BUILDER: '${config.builder_provider}' runs volley's tool loop with a real bash ` +\n `(write + exec) directly on this machine in ${config.workspace} — no container isolation. ` +\n `Proceeding because --allow-unsandboxed-builder / VOLLEY_ALLOW_UNSANDBOXED_BUILDER is set; ` +\n `run volley inside its sandbox container for blast-radius containment instead.`,\n );\n }\n}\n\n/** The critic seat's options: its model, provider, and URL. `required` marks\n * the model and provider as having no default, as under `acp`. */\nfunction with_critic_options(command: Command, required = false): Command {\n const model_note = required ? ' (required)' : '';\n const provider_note = required ? 'required' : 'default: claude_cli';\n return command\n .option('--critic-model <model>', `Critic model${model_note}`)\n .option('--critic-provider <name>', `claude_cli | ollama | lmstudio | openrouter (${provider_note})`)\n .option('--critic-url <url>', \"Critic's model server base URL, ollama, lmstudio, or openrouter only (default: VOLLEY_OLLAMA_URL / VOLLEY_LMSTUDIO_URL / VOLLEY_OPENROUTER_URL)\");\n}\n\n/** The seat options, declared once for every command that runs seats: each\n * seat's model, provider, and URL, the tool-loop builder's step cap, and the\n * unsandboxed opt-out. `required` marks each seat's model and provider as\n * having no default, as under `acp`. */\nfunction with_seat_options(command: Command, required = false): Command {\n const model_note = required ? ' (required)' : '';\n const provider_note = required ? 'required' : 'default: claude_cli';\n return with_critic_options(\n command\n .option('--builder-model <model>', `Builder model${model_note}`)\n .option('--builder-provider <name>', `claude_cli | ollama | lmstudio | openrouter (${provider_note})`)\n .option('--builder-url <url>', \"Builder's model server base URL, ollama, lmstudio, or openrouter only (default: VOLLEY_OLLAMA_URL / VOLLEY_LMSTUDIO_URL / VOLLEY_OPENROUTER_URL)\")\n .option('--builder-max-steps <n>', 'Tool-loop builder step cap per iteration, any provider but claude_cli (default: 50)')\n .option('--builder-max-tool-calls <n>', 'Tool calls a tool-loop builder may make per turn, reads aside, any provider but claude_cli (default: 1)')\n .option('--builder-max-output-tokens <n>', \"Output tokens a tool-loop builder may generate per turn, reasoning included, any provider but claude_cli (default: 16384 on ollama and lmstudio, the provider's on openrouter)\")\n .option('--allow-unsandboxed-builder', 'Permit a builder other than claude_cli to run without a sandbox (real host bash + write)'),\n required,\n );\n}\n\n/** What a critique declares only so that it can refuse each by name, with\n * exit 5: cac would answer an undeclared one with a bare \"Unknown option\".\n * `resolve_config` refuses all but `--config`, which the command does. */\nconst CRITIQUE_REFUSED_OPTIONS = [\n '--builder-model <model>',\n '--builder-provider <name>',\n '--builder-url <url>',\n '--builder-max-steps <n>',\n '--builder-max-tool-calls <n>',\n '--builder-max-output-tokens <n>',\n '--builder-permission-mode <mode>',\n '--allow-unsandboxed-builder',\n '--sandbox-image <tag>',\n '--max-iterations <n>',\n '--max-cost-usd <usd>',\n '--git',\n '--worktree',\n '--discard-worktree',\n '--fail-on-gate-edit',\n '--config <path>',\n];\n\nfunction merge_flags(base: VolleyConfig, flags: CliFlags): VolleyConfig {\n return {\n ...base,\n ...(flags.prompt !== undefined ? { prompt: flags.prompt } : {}),\n ...(flags.workspace !== undefined ? { workspace: flags.workspace } : {}),\n ...(flags.criteria !== undefined ? { criteria: flags.criteria } : {}),\n ...(flags.check !== undefined ? { check: flags.check } : {}),\n ...(flags.builderModel !== undefined ? { builder_model: flags.builderModel } : {}),\n ...(flags.builderProvider !== undefined\n ? { builder_provider: flags.builderProvider as BuilderProvider }\n : {}),\n ...(flags.builderUrl !== undefined ? { builder_url: flags.builderUrl } : {}),\n ...(flags.builderMaxSteps !== undefined\n ? { builder_max_steps: Number(flags.builderMaxSteps) }\n : {}),\n ...(flags.builderMaxToolCalls !== undefined\n ? { builder_max_tool_calls: Number(flags.builderMaxToolCalls) }\n : {}),\n ...(flags.builderMaxOutputTokens !== undefined\n ? { builder_max_output_tokens: Number(flags.builderMaxOutputTokens) }\n : {}),\n ...(flags.allowUnsandboxedBuilder === true ? { allow_unsandboxed_builder: true } : {}),\n ...(flags.criticModel !== undefined ? { critic_model: flags.criticModel } : {}),\n ...(flags.criticProvider !== undefined\n ? { critic_provider: flags.criticProvider as CriticProvider }\n : {}),\n ...(flags.criticUrl !== undefined ? { critic_url: flags.criticUrl } : {}),\n ...(flags.builderPermissionMode !== undefined\n ? { builder_permission_mode: flags.builderPermissionMode as BuilderPermissionMode }\n : {}),\n ...(flags.critic !== undefined ? { critic: flags.critic } : {}),\n ...(flags.maxIterations !== undefined ? { max_iterations: Number(flags.maxIterations) } : {}),\n ...(flags.maxCostUsd !== undefined ? { max_cost_usd: Number(flags.maxCostUsd) } : {}),\n ...(flags.git === true ? { git_checkpoints: true } : {}),\n ...(flags.worktree === true ? { worktree: true } : {}),\n ...(flags.discardWorktree === true ? { discard_worktree: true } : {}),\n ...(flags.gatePaths !== undefined ? { gate_paths: parse_glob_list(flags.gatePaths) } : {}),\n ...(flags.failOnGateEdit === true ? { fail_on_gate_edit: true } : {}),\n ...(flags.sandboxImage !== undefined ? { sandbox_image: flags.sandboxImage } : {}),\n ...(flags.stateDir !== undefined ? { state_dir: flags.stateDir } : {}),\n ...(flags.dryRun === true ? { dry_run: true } : {}),\n ...(flags.json === true ? { json: true } : {}),\n ...(flags.verbose === true ? { verbose: true } : {}),\n ...(flags.quiet === true ? { quiet: true } : {}),\n ...(flags.thinking === false ? { show_thinking: false } : {}),\n };\n}\n\n/** What a resume is about to run on a config this machine didn't sign, said\n * once before it runs, so `--trust-config` is never a blind yes. Every value\n * came from that config, so each is quoted with its control characters\n * escaped, and can't redraw the line it's warned on. */\nfunction warn_trusted_config(config: ResolvedConfig, renderer: Renderer): void {\n renderer.warn(\n `resuming on a config volley on this machine didn't sign (--trust-config): check ` +\n `${shown(config.check)} (resolved: ${config.check_resolved}), builder ` +\n `${config.builder_provider} ${shown(config.builder_model)} (${config.builder_permission_mode}), ` +\n `critic ${config.critic_provider} ${shown(config.critic_model)}, workspace ${shown(config.workspace)}`,\n );\n}\n\n/** A flag's value as typed. cac reads an all-digit value as a number, which\n * drops leading zeros, so a coerced id or revision would silently name another\n * run or commit: refused rather than guessed at. */\nfunction not_a_bare_number(name: string, value: string | number | undefined): string | undefined {\n if (typeof value === 'number') {\n throw config_error(`${name} must not be a bare number (read as ${String(value)})`);\n }\n return value;\n}\n\nfunction emit_result(config: ResolvedConfig, result: RunResult, renderer: Renderer): number {\n renderer.final_summary(result);\n if (config.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n }\n return exit_code_for_status(result.status);\n}\n\nfunction report_error(err: unknown): number {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`volley: ${message}\\n`);\n if (error_kind(err) === 'phase_error') {\n const cause = (err as { cause?: unknown }).cause;\n if (cause instanceof Error && cause.message !== message) {\n process.stderr.write(` cause: ${cause.message}\\n`);\n }\n }\n return exit_code_for_error(err);\n}\n\nasync function main(argv: string[]): Promise<number> {\n const cli = cac('volley');\n\n let exit_code = EXIT_SUCCESS;\n\n const run_command = cli\n .command('', 'Run the builder/critic loop')\n .option('--prompt <prompt>', 'Task prompt (string or @file)')\n .option('--workspace <path>', 'Workspace directory (must exist and be writable)')\n .option('--criteria <criteria>', 'Acceptance criteria (string or @file)')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`);\n with_seat_options(run_command)\n .option('--builder-permission-mode <mode>', 'acceptEdits | bypassPermissions')\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--max-iterations <n>', 'Iteration cap')\n .option('--max-cost-usd <usd>', 'Hard USD ceiling, enforced in the loop guard')\n .option('--git', 'Auto-commit after each phase (workspace must be a git repo)')\n .option('--worktree', 'Isolate the builder run in a per-run git worktree (workspace must be a git repo)')\n .option('--discard-worktree', \"Throw a --worktree run's effects away at teardown instead of keeping them on the run branch\")\n .option('--gate-paths <globs>', 'Comma-separated globs naming the gate (tests, fixtures, check config); replaces the defaults')\n .option('--fail-on-gate-edit', 'Halt the run if the builder edits a gate path (exit 8) instead of reporting it')\n .option('--sandbox-image <tag>', `Container image for the local-builder sandbox (default: ${DEFAULT_SANDBOX_IMAGE})`)\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--run-id <id>', \"The run's id, naming its volley/<id> branch (default: a fresh UUID)\")\n .option('--dry-run', 'Validate config (and checkride doctor) without running')\n .option('--config <path>', 'TypeScript config file exporting a VolleyConfig')\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs (truncated at 4000 chars)')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks (still recorded in the trajectory)')\n .action(async (flags: CliFlags) => {\n const base = flags.config !== undefined ? await load_config_file(flags.config) : ({} as VolleyConfig);\n const merged = merge_flags(base, flags);\n const run_id = not_a_bare_number('--run-id', flags.runId);\n const config = resolve_config(merged, run_id !== undefined ? { run_id } : {});\n const renderer = make_renderer(config);\n warn_api_key_meter(renderer);\n warn_unsandboxed_builder(config, renderer);\n if (merged.dry_run === true) {\n exit_code = await preflight(config, renderer, process.env);\n return;\n }\n const result = await run_volley(config, { renderer });\n exit_code = emit_result(config, result, renderer);\n });\n\n cli\n .command('resume <run_id>', 'Resume a run from its last completed iteration')\n .option('--workspace <path>', \"Where a run an older volley started keeps its .volley/ state\", {\n default: '.',\n })\n .option('--state-dir <path>', 'State root the run was started under (default: $XDG_STATE_HOME/volley, else ~/.local/state/volley)')\n .option('--trust-config', \"Resume a config volley on this machine didn't sign: another machine's, an older volley's, or one you edited. Read it first\")\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks')\n .action(async (run_id: string, flags: CliFlags) => {\n // cac refuses any option this command doesn't declare, so what's left\n // once the lookup flags are taken out is the output flags alone.\n const { workspace = '.', stateDir, trustConfig, ...output } = flags;\n // The run is looked for under the root named here, else the default, and\n // where it's found wins over the recorded root, so a moved root resumes\n // where it now is. A run an older volley kept in .volley/ resumes there.\n const root = stateDir === undefined ? default_state_root(process.env) : resolve(stateDir);\n const state_dir = find_run_state(workspace, run_id, root);\n const resume = load_resume_state(workspace, run_id, state_dir, {\n trust_config: trustConfig === true,\n });\n const merged = merge_flags(resume.raw_config, output);\n const config = resolve_config(merged, {\n run_id: resume.run_id,\n started_at: resume.started_at,\n state_dir,\n });\n if (resume.iterations_completed >= config.max_iterations) {\n throw config_error(\n `run already completed ${String(resume.iterations_completed)} of ${String(config.max_iterations)} iterations`,\n );\n }\n const renderer = make_renderer(config);\n warn_api_key_meter(renderer);\n warn_unsandboxed_builder(config, renderer);\n if (resume.config_signed === false) warn_trusted_config(config, renderer);\n renderer.info(\n `resuming run ${run_id} at iteration ${String(resume.iterations_completed + 1)}`,\n );\n const result = await run_volley(config, { renderer }, resume.state);\n exit_code = emit_result(config, result, renderer);\n });\n\n const critique_command = cli\n .command('critique', 'Check and critique a change already made, once, with no builder')\n .option('--workspace <path>', 'The repository whose change is reviewed', { default: '.' })\n .option('--baseline <rev>', 'Review everything that differs from this revision, committed or not (default: HEAD)')\n .option('--criteria <criteria>', 'Acceptance criteria (string or @file)')\n .option('--prompt <prompt>', 'The task the change answers, recorded with the run; the critic judges against --criteria')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`);\n with_critic_options(critique_command)\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--gate-paths <globs>', 'Comma-separated globs naming the gate (tests, fixtures, check config); replaces the defaults')\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--run-id <id>', \"The run's id, naming its state directory (default: a fresh UUID)\")\n .option('--dry-run', 'Validate config and the baseline, run checkride doctor, and probe the critic seat, then exit')\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs (truncated at 4000 chars)')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks (still recorded in the trajectory)');\n for (const refused of CRITIQUE_REFUSED_OPTIONS) {\n critique_command.option(refused, 'Refused: a critique runs no builder and no loop');\n }\n critique_command.action(async (flags: CliFlags) => {\n if (flags.config !== undefined) {\n throw config_error(\n \"volley critique refuses --config: a run's config file sets a builder; pass the critique's settings as flags\",\n );\n }\n const run_id = not_a_bare_number('--run-id', flags.runId);\n const baseline = not_a_bare_number('--baseline', flags.baseline);\n const merged = merge_flags({} as VolleyConfig, flags);\n const config = resolve_config(merged, {\n mode: 'critique',\n ...(run_id !== undefined ? { run_id } : {}),\n });\n const renderer = make_renderer(config);\n warn_api_key_meter(renderer);\n if (merged.dry_run === true) {\n // A revision that isn't a commit fails the dry run as it would the critique.\n const sha = resolve_baseline(config.workspace, baseline);\n renderer.info(`baseline: ${sha ?? 'none (not a git repository, or no commit yet)'}`);\n exit_code = await preflight(config, renderer, process.env);\n return;\n }\n const result = await run_critique(config, {\n renderer,\n ...(baseline !== undefined ? { baseline } : {}),\n });\n exit_code = emit_result(config, result, renderer);\n });\n\n cli\n .command('matrix', 'Sweep builder×critic model combos serially over one config')\n .option('--config <path>', 'Base VolleyConfig (TS/JS): the task, workspace, providers, and caps held fixed')\n .option('--builders <models>', 'Comma-separated builder models to sweep')\n .option('--critics <models>', 'Comma-separated critic models to sweep')\n .option('--workspace <path>', 'Override the base config workspace')\n .option('--repeat <n>', 'Attempts per seat (default: 1); a pass rate needs more than one')\n .option('--json', 'Machine mode: aggregate JSON on stdout, no table')\n .option('--verbose', 'Show full builder/critic streams per combo')\n .option('--quiet', 'Per-combo phase transitions and the final table only')\n .action(async (flags: MatrixFlags) => {\n if (flags.config === undefined) {\n throw config_error('volley matrix requires --config <path> (the base task to sweep)');\n }\n const builders = parse_model_list(flags.builders, '--builders');\n const critics = parse_model_list(flags.critics, '--critics');\n const repeat = parse_repeat(flags.repeat);\n const base = await load_config_file(flags.config);\n const merged = merge_flags(base, {\n ...(flags.workspace !== undefined ? { workspace: flags.workspace } : {}),\n ...(flags.json === true ? { json: true } : {}),\n ...(flags.verbose === true ? { verbose: true } : {}),\n ...(flags.quiet === true ? { quiet: true } : {}),\n });\n // Resolve once with the forced throw-away worktree to validate the\n // git repo, providers, and task up front — before any combo spends — and to\n // build the renderer and locate the workspace-level `.volley-matrix/`\n // output. Matches what `default_run_combo` resolves per seat.\n const base_config = resolve_config({ ...merged, worktree: true, discard_worktree: true });\n const renderer = make_renderer(base_config, '<run id>');\n warn_api_key_meter(renderer);\n warn_unsandboxed_builder(base_config, renderer);\n const outcome = await run_matrix({\n base: merged,\n builders,\n critics,\n matrix_dir: join(base_config.workspace, '.volley-matrix'),\n renderer,\n repeat,\n });\n if (base_config.json) {\n process.stdout.write(`${JSON.stringify({ combos: outcome.rows }, null, 2)}\\n`);\n }\n exit_code = outcome.ok ? EXIT_SUCCESS : EXIT_MATRIX_INCOMPLETE;\n });\n\n // `--worktree`, `--git`, and `--json` are declared only so they can be\n // refused with a reason; cac would answer an undeclared one with a bare\n // \"Unknown option\".\n const acp_command = cli.command('acp', 'Serve volley to an editor as an ACP agent over stdio');\n with_seat_options(acp_command, true)\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`)\n .option('--max-iterations <n>', `Iteration cap per prompt (default: ${String(ACP_MAX_ITERATIONS)})`)\n .option('--max-cost-usd <usd>', 'Hard USD ceiling per prompt, enforced in the loop guard')\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--worktree', 'Refused: a sibling worktree sits outside the project the editor has open')\n .option('--git', 'Refused: phase commits would bypass the permission prompts')\n .option('--json', 'Refused: stdout carries the protocol')\n .action(async (flags: CliFlags) => {\n const base = acp_base_config(merge_flags({} as VolleyConfig, flags));\n await serve_acp(acp_serve_config(base, { version: package_version() }));\n });\n\n cli.help();\n cli.version(package_version());\n\n try {\n cli.parse(argv, { run: false });\n await cli.runMatchedCommand();\n } catch (err) {\n return report_error(err);\n }\n return exit_code;\n}\n\n// Guard the entry so importing this module (e.g. from tests, to exercise the\n// exported warn helpers) does not run the CLI. `import.meta.main` is true only\n// when this file is the process entry point (symlink-safe; Node ≥ 24).\nif (import.meta.main) {\n const code = await main(process.argv);\n process.exitCode = code;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":["git"],"sources":["../src/builder/context_check.ts","../src/builder/countdown.ts","../src/builder/prepare_step.ts","../src/builder/trim.ts","../src/types.ts","../src/engine.ts","../src/workspace_tools.ts","../src/builder/tools.ts","../src/check/checkride.ts","../src/check/command.ts","../src/claude_cli_permissions.ts","../src/cost.ts","../src/prewarm.ts","../src/containment.ts","../src/trust.ts","../src/workspace.ts","../src/worktree.ts","../src/builder.ts","../src/changes.ts","../src/critic/prompt.ts","../src/critic/run.ts","../src/render/format.ts","../src/iteration.ts","../src/summary.ts","../src/phases.ts","../src/acp_progress.ts","../src/acp_tools.ts","../src/check/detect.ts","../src/config.ts","../src/loop_state.ts","../src/flow.ts","../src/orchestrator.ts","../src/render/renderer.ts","../src/acp.ts","../src/exit_codes.ts","../src/matrix.ts","../src/preflight.ts","../src/cli.ts"],"sourcesContent":["/**\n * Best-effort local-context guard. A too-small context window\n * silently truncates the tool schemas volley sends — the #1 reported local\n * tool-calling failure (Ollama's 4k default). We warn at builder start *where\n * the value is detectable* and never block or fail on it: detection is a\n * courtesy, the setup requirement is the user's (README `## Local builder`).\n *\n * On the ai_sdk transport this probe reads the server-side `num_ctx` (a\n * Modelfile or server default). Under fascicle's native transport (the\n * deferred future bridge) `num_ctx`/`keep_alive` become per-call\n * `provider_options.ollama` options set at request time, so the value would be\n * volley's to pass rather than a server default to probe — the warning stays\n * useful either way.\n */\nimport type { BuilderProvider } from '../types.js';\n\n/** Below this, tool schemas start getting truncated for volley's tool set. */\nexport const MIN_RECOMMENDED_NUM_CTX = 16384;\n\n/** Probe timeout — a local `/api/show` answers in single-digit ms when up; a\n * hung server must not stall builder start. */\nconst PROBE_TIMEOUT_MS = 2000;\n\n/** The warning when a detected context window is too small, or null when the\n * window is adequate or unknown (`num_ctx === null` = not detectable). Pure so\n * the threshold decision is unit-testable without a server. */\nexport function context_warning(model: string, num_ctx: number | null): string | null {\n if (num_ctx === null || num_ctx >= MIN_RECOMMENDED_NUM_CTX) return null;\n return (\n `local builder model '${model}' is configured with num_ctx ${String(num_ctx)}, below the ` +\n `~${String(MIN_RECOMMENDED_NUM_CTX)} volley recommends: a small context window silently ` +\n 'truncates the tool schemas (the #1 local tool-calling failure). Raise it (e.g. a Modelfile ' +\n '`PARAMETER num_ctx 16384`) or expect the model to ignore its tools.'\n );\n}\n\n/** Pull `num_ctx` out of Ollama's newline-delimited `parameters` blob\n * (e.g. `\"num_ctx 4096\\nstop \\\"<|im_end|>\\\"\"`). Null when\n * the parameter is absent or unparseable — which is the common case for a\n * server relying on its own default, and precisely the \"not detectable\" edge. */\nexport function parse_num_ctx(parameters: string | null): number | null {\n if (parameters === null) return null;\n const match = /^\\s*num_ctx\\s+(\\d+)\\s*$/m.exec(parameters);\n if (match === null) return null;\n const value = Number(match[1]);\n return Number.isFinite(value) ? value : null;\n}\n\n/** Best-effort probe of an Ollama server for a model's configured `num_ctx`\n * via `/api/show` (`base_url` is the server root). Returns null on any\n * failure (server down, non-OK, field absent, parse/JSON error) — the\n * warning never gates the builder. */\nexport async function probe_ollama_num_ctx(\n base_url: string,\n model: string,\n abort?: AbortSignal,\n): Promise<number | null> {\n const signals = [AbortSignal.timeout(PROBE_TIMEOUT_MS)];\n if (abort !== undefined) signals.push(abort);\n try {\n const res = await fetch(`${base_url.replace(/\\/$/, '')}/api/show`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ model }),\n signal: AbortSignal.any(signals),\n });\n if (!res.ok) return null;\n const body = (await res.json()) as { parameters?: unknown };\n return parse_num_ctx(typeof body.parameters === 'string' ? body.parameters : null);\n } catch {\n return null;\n }\n}\n\n/** Emit a small-context warning via `warn` when an Ollama builder model's\n * `num_ctx` is detectably below the recommended floor. Ollama-only — LM Studio\n * exposes no reliable pre-flight context field, so it is documented, not\n * probed. Never throws (setup friction is data, not an error). */\nexport async function warn_small_local_context(\n provider: BuilderProvider,\n model: string,\n base_url: string,\n warn: (message: string) => void,\n abort?: AbortSignal,\n): Promise<void> {\n if (provider !== 'ollama') return;\n const warning = context_warning(model, await probe_ollama_num_ctx(base_url, model, abort));\n if (warning !== null) warn(warning);\n}\n","/**\n * The tool-loop builder's step countdown. A model that explores first can\n * spend its whole budget before it verifies: in volley-41806476 the builder's\n * 50th step was a `bash` call fascicle refused, and the half-fixed tree went to\n * the check and critic. So for the last few steps of a session, each turn's\n * request ends with a note of how many are left and what to do with them.\n *\n * The note goes in through fascicle's `prepare_step`, which reshapes only what\n * one turn sends, so the transcript stays as the model wrote it, and the note\n * sits after everything a local runtime has cached, so its cached prefix holds.\n */\nimport type { PrepareStepHook } from 'fascicle';\n\n/** How many of a session's last steps carry the countdown: five, or a tenth\n * of a long budget, but never more than half of it, so a short session still\n * starts without one. */\nexport function countdown_window(max_steps: number): number {\n return Math.min(Math.max(5, Math.ceil(max_steps / 10)), Math.floor(max_steps / 2));\n}\n\n/** The note for a turn with `steps_left` steps left, this one included.\n * `check` names how to run the check. On the last step fascicle runs only a\n * call that ends the session, which for the builder is `finish`. */\nexport function countdown_note(steps_left: number, check: string): string {\n if (steps_left <= 1) {\n return (\n '[volley] This is the last step of this session, and only finish runs on it. ' +\n \"Call finish now, with a summary that says what's done and what isn't verified.\"\n );\n }\n return (\n `[volley] ${String(steps_left)} steps left in this session, this one included, ` +\n 'and on the last one only finish runs. ' +\n `If you haven't run ${check} since your last edit, run it now, ` +\n 'then fix what it reports or call finish.'\n );\n}\n\n/** The `prepare_step` hook that adds the countdown to a session of\n * `max_steps` steps. */\nexport function step_countdown(max_steps: number, check: string): PrepareStepHook {\n const window = countdown_window(max_steps);\n return ({ step_index, messages }) => {\n const steps_left = max_steps - step_index;\n if (steps_left > window) return undefined;\n return {\n messages: [...messages, { role: 'user', content: countdown_note(steps_left, check) }],\n };\n };\n}\n","/**\n * The tool-loop builder's one `prepare_step` slot, shared by the hooks that\n * reshape a turn's request: the history trim, then the step countdown, whose\n * note goes last so it sits after everything a local runtime has cached.\n */\nimport type { PrepareStepHook } from 'fascicle';\n\n/** One hook that runs `hooks` in order, each on the request the one before it\n * made, and reports no change when none of them made one. */\nexport function compose_prepare_steps(hooks: ReadonlyArray<PrepareStepHook>): PrepareStepHook {\n return async ({ step_index, messages }) => {\n let request = messages;\n let changed = false;\n for (const hook of hooks) {\n const prepared = await hook({ step_index, messages: request });\n if (prepared?.messages !== undefined) {\n request = prepared.messages;\n changed = true;\n }\n }\n return changed ? { messages: request } : undefined;\n };\n}\n","/**\n * Trimming a long tool-loop session's history (#7). Every turn resends the\n * whole session, every earlier `read_file` result included, even for files the\n * builder has rewritten since, so a long local session's requests grow\n * linearly and each turn's latency grows with them: volley-41806476's input\n * went from 2.6k to 57k tokens over 50 steps, and its turns from 3 s to as\n * much as 120 s.\n *\n * Above a size the operator sets (`--builder-trim-history`), each turn's\n * request replaces the older tool results with one-line stubs: a read of a\n * file a later call wrote, edited, or read whole says so, and any other result\n * names its call and size. The last `TRIM_KEEP_TURNS` turns, every assistant\n * and user message, every failed call's result, and anything short stay as\n * they are. It goes in through fascicle's `prepare_step`, which reshapes only\n * what one turn sends, so the transcript stays as the model wrote it.\n *\n * A local runtime reuses the KV cache for the prefix a request shares with\n * the last one, and rewriting an earlier message breaks that prefix, so the\n * window is prefilled again. So the trim moves in coarse steps: it stubs\n * everything before a turn boundary, boundaries fall every\n * `TRIM_STRIDE_TURNS` turns, and the boundary moves on only when the trimmed\n * request has grown past the size again. Between moves each request starts\n * with the same bytes as the last, since a stub depends only on what came\n * before its boundary and never on the step. The trim keeps no state:\n * `trim_cutoff` works the boundary out again from the transcript each turn.\n */\nimport { posix } from 'node:path';\nimport type { Message, PrepareStepHook } from 'fascicle';\n\n/** A rough token count per character: the hook sees no token counts, so a\n * request's size is estimated from its text. */\nconst CHARS_PER_TOKEN = 4;\n\n/** Turns at the end of a session whose tool results are never stubbed. */\nexport const TRIM_KEEP_TURNS = 6;\n\n/** How many turns apart the boundaries the trim may cut at fall. */\nexport const TRIM_STRIDE_TURNS = 8;\n\n/** Results this short are kept, since a stub would save next to nothing. */\nexport const STUB_MIN_CHARS = 200;\n\n/** What a message costs beyond its text: its role and framing. */\nconst MESSAGE_OVERHEAD_TOKENS = 8;\n\n/** The calls that change a file, whose success makes an earlier read of it\n * stale. Both volley's tools and fascicle's ACP tools use these names and a\n * `path` input. */\nconst FILE_WRITERS: ReadonlySet<string> = new Set(['write_file', 'edit_file']);\n\nconst COMMAND_TOOLS: ReadonlySet<string> = new Set(['bash', 'run_command']);\n\nfunction message_chars(message: Message): number {\n if (typeof message.content === 'string') return message.content.length;\n let chars = 0;\n for (const part of message.content) {\n if (part.type === 'text' || part.type === 'reasoning') chars += part.text.length;\n else if (part.type === 'tool_call') chars += part.name.length + (JSON.stringify(part.input) ?? '').length;\n }\n return chars;\n}\n\n/** A request's size in tokens, estimated from its characters. */\nexport function estimate_tokens(messages: ReadonlyArray<Message>): number {\n let tokens = 0;\n for (const message of messages) {\n tokens += Math.ceil(message_chars(message) / CHARS_PER_TOKEN) + MESSAGE_OVERHEAD_TOKENS;\n }\n return tokens;\n}\n\n/** What a tool call asked for, as far as the trim reads it. */\ntype CallInput = { path: string | null; whole: boolean };\n\nfunction call_input(input: unknown): CallInput {\n if (typeof input !== 'object' || input === null) return { path: null, whole: true };\n const fields = input as Record<string, unknown>;\n const path = typeof fields['path'] === 'string' ? posix.normalize(fields['path']) : null;\n // An ACP read names a range with `offset` or `limit`; volley's never does.\n return { path, whole: fields['offset'] === undefined && fields['limit'] === undefined };\n}\n\n/** Each tool call's input, by call id, from the assistant messages in\n * `messages`. */\nfunction call_inputs(messages: ReadonlyArray<Message>): Map<string, CallInput> {\n const inputs = new Map<string, CallInput>();\n for (const message of messages) {\n if (message.role !== 'assistant' || typeof message.content === 'string') continue;\n for (const part of message.content) {\n if (part.type === 'tool_call') inputs.set(part.id, call_input(part.input));\n }\n }\n return inputs;\n}\n\ntype ToolMessage = Extract<Message, { role: 'tool' }>;\n\n/** A later call on a path that makes an earlier read of it stale. */\ntype Supersession = { tool: string; changed: boolean };\n\n/** Whether this result is one whose call changed its file or read it whole. */\nfunction supersession_of(message: ToolMessage, input: CallInput | undefined): Supersession | null {\n if (input === undefined || input.path === null || message.is_error === true) return null;\n if (FILE_WRITERS.has(message.name)) {\n return message.content.startsWith('error:') ? null : { tool: message.name, changed: true };\n }\n if (message.name === 'read_file' && input.whole) return { tool: 'read_file', changed: false };\n return null;\n}\n\nfunction exit_code_of(content: string): number | null {\n try {\n const parsed: unknown = JSON.parse(content);\n if (typeof parsed === 'object' && parsed !== null) {\n const code = (parsed as Record<string, unknown>)['exit_code'];\n if (typeof code === 'number') return code;\n }\n } catch {\n // Not JSON: a command result without an exit code to keep.\n }\n return null;\n}\n\nfunction stub(message: ToolMessage, input: CallInput | undefined, later: Supersession | undefined): string {\n const size = `${String(message.content.length)} chars`;\n if (later !== undefined && input !== undefined && input.path !== null) {\n return later.changed\n ? `[volley] read_file ${input.path} (${size}) elided: a later ${later.tool} changed this file. Read it again for its current content.`\n : `[volley] read_file ${input.path} (${size}) elided: it was read again later in this session.`;\n }\n const exit_code = COMMAND_TOOLS.has(message.name) ? exit_code_of(message.content) : null;\n const detail = exit_code === null ? size : `${size}, exit ${String(exit_code)}`;\n return `[volley] ${message.name} output (${detail}) elided from an earlier turn. Run it again if you need it.`;\n}\n\n/**\n * The request with every tool result before `cutoff` that is long enough to\n * matter and didn't fail replaced by a stub. Every message keeps its place,\n * role, id, and name. A stub reads only what comes before `cutoff`, so the\n * same transcript prefix always gives the same bytes.\n */\nexport function trim_view(messages: ReadonlyArray<Message>, cutoff: number): Message[] {\n const window = messages.slice(0, cutoff);\n const inputs = call_inputs(window);\n // Walk back from the boundary so each read meets the nearest later call on\n // its path.\n const next_on_path = new Map<string, Supersession>();\n const later_for = new Map<number, Supersession>();\n for (let i = window.length - 1; i >= 0; i -= 1) {\n const message = window[i];\n if (message?.role !== 'tool') continue;\n const input = inputs.get(message.tool_call_id);\n const path = input?.path ?? null;\n if (path === null) continue;\n if (message.name === 'read_file') {\n const later = next_on_path.get(path);\n if (later !== undefined) later_for.set(i, later);\n }\n const supersedes = supersession_of(message, input);\n if (supersedes !== null) next_on_path.set(path, supersedes);\n }\n return messages.map((message, i) => {\n if (i >= cutoff || message.role !== 'tool' || message.is_error === true) return message;\n if (message.content.length <= STUB_MIN_CHARS) return message;\n return { ...message, content: stub(message, inputs.get(message.tool_call_id), later_for.get(i)) };\n });\n}\n\n/**\n * Where to cut this turn's request, as a message index, or null to send it\n * whole. Boundaries are the starts of turns `TRIM_STRIDE_TURNS`,\n * `2 * TRIM_STRIDE_TURNS`, and so on, short of the last `TRIM_KEEP_TURNS`.\n * The cut moves to the next boundary only while the request, trimmed at the\n * last one, is still over `threshold`. A trimmed request only grows as the\n * session goes on, so a boundary once taken is kept.\n */\nexport function trim_cutoff(messages: ReadonlyArray<Message>, threshold: number): number | null {\n const turn_starts = messages.flatMap((message, i) => (message.role === 'assistant' ? [i] : []));\n let cutoff: number | null = null;\n for (let turn = TRIM_STRIDE_TURNS; turn <= turn_starts.length - TRIM_KEEP_TURNS; turn += TRIM_STRIDE_TURNS) {\n const view = cutoff === null ? messages : trim_view(messages, cutoff);\n if (estimate_tokens(view) <= threshold) break;\n cutoff = turn_starts[turn] ?? null;\n }\n return cutoff;\n}\n\n/** The `prepare_step` hook that trims a request estimated above `threshold`\n * tokens. */\nexport function step_trim(threshold: number): PrepareStepHook {\n return ({ messages }) => {\n const cutoff = trim_cutoff(messages, threshold);\n return cutoff === null ? undefined : { messages: trim_view(messages, cutoff) };\n };\n}\n","/**\n * Shared value and type contracts for volley.\n *\n * Type aliases are PascalCase; value-level identifiers are snake_case.\n * Fascicle's usage/cost types are used verbatim so summaries carry the\n * substrate's shapes, not a re-derivation.\n */\nimport type { FinishReason, Throughput, UsageTotals } from 'fascicle';\n\nexport type Verdict = 'approved' | 'changes_requested';\n\nexport type CriticPreset = 'reviewer' | 'optimizer' | 'researcher';\n\n/** Transport for the critic role. The critic is read-only + schema-constrained,\n * so it has always been able to run on a local model. `openrouter` reaches a\n * hosted model over one API key and takes the local critic's tools and\n * degradation ladder. */\nexport type CriticProvider = 'claude_cli' | 'ollama' | 'lmstudio' | 'openrouter';\n\n/** Transport for the builder role. `claude_cli` is a full agentic Claude Code\n * session; every other provider runs the builder as a volley-driven tool loop\n * (write/exec tools supplied by the harness), whether its model is local\n * (`ollama`, `lmstudio`) or hosted (`openrouter`). */\nexport type BuilderProvider = 'claude_cli' | 'ollama' | 'lmstudio' | 'openrouter';\n\nexport type BuilderPermissionMode = 'acceptEdits' | 'bypassPermissions';\n\n/** `auto`, `none`, or any shell command (the `string & {}` keeps the literal\n * hints in editor completions without collapsing the union). */\nexport type CheckMode = 'auto' | 'none' | (string & {});\n\nexport type CheckRunnerKind = 'checkride' | 'command' | 'none';\n\nexport type CostSource = 'provider_reported' | 'engine_derived' | 'unknown';\n\n/** Fascicle's `provider_error.cause_kind` discriminant — why a provider call\n * died. Recorded alongside a critic retry so a degraded run says\n * *what* failed, not just that it retried. */\nexport type CauseKind = 'provider_5xx' | 'network' | 'unknown';\n\n/** Why a local critic's verdict came from the tool-less fallback:\n * `stream_error`, the tool-bearing call kept dying on the provider's stream\n * after the bounded retry; `step_exhaustion`, it spent its step budget (or\n * stopped on a tool call) without producing a verdict. */\nexport type DegradeCause = 'stream_error' | 'step_exhaustion';\n\nexport type RunStatus =\n | 'running'\n | 'success'\n | 'budget_exhausted'\n | 'cost_cap_reached'\n /** The builder edited the gate that judges it, under `--fail-on-gate-edit`:\n * the run halts on the spot rather than iterating, because a check the builder\n * can rewrite is not evidence the work is done. */\n | 'gate_edit_blocked'\n /** A critique's other outcome: the critic requested changes, or the check\n * failed, on the one change it reviewed. A run never ends this way. */\n | 'rejected'\n | 'interrupted'\n | 'error';\n\n/** What a run does: the builder/critic loop (`run`), or one check and one\n * critique of a change already made, with no builder at all (`critique`). */\nexport type RunMode = 'run' | 'critique';\n\n/** User-facing configuration, before resolution (config file / flags). */\nexport type VolleyConfig = {\n prompt: string;\n workspace: string;\n criteria: string;\n check?: CheckMode;\n builder_model?: string;\n builder_provider?: BuilderProvider;\n builder_url?: string;\n builder_max_steps?: number;\n builder_max_tool_calls?: number;\n builder_max_output_tokens?: number;\n builder_trim_history?: number;\n allow_unsandboxed_builder?: boolean;\n critic_model?: string;\n critic_provider?: CriticProvider;\n critic_url?: string;\n builder_permission_mode?: BuilderPermissionMode;\n critic?: CriticPreset | (string & {});\n max_iterations?: number;\n max_cost_usd?: number | null;\n git_checkpoints?: boolean;\n worktree?: boolean;\n discard_worktree?: boolean;\n gate_paths?: string[];\n fail_on_gate_edit?: boolean;\n sandbox_image?: string;\n state_dir?: string;\n verbose?: boolean;\n quiet?: boolean;\n json?: boolean;\n show_thinking?: boolean;\n dry_run?: boolean;\n};\n\n/** Fully resolved run configuration; the run's `config.json` mirrors this. */\nexport type ResolvedConfig = {\n version: 2;\n run_id: string;\n started_at: string;\n /** A run, or a critique (`volley critique`). A critique's builder fields\n * hold the defaults, untouched by flags and the environment, since no\n * builder is ever constructed, and its loop settings are one round with\n * nothing isolated or committed. */\n mode: RunMode;\n /** The task. A critique needs none, since a critic judges against the\n * criteria alone, so it's empty unless one was given to record. */\n prompt: string;\n criteria: string;\n check: CheckMode;\n check_resolved: CheckRunnerKind;\n builder_model: string;\n builder_provider: BuilderProvider;\n /** The builder seat's own model server base URL (`--builder-url`), as given.\n * It is normalized, and crossed to the host LLM endpoint when contained, only\n * where it is used, because the crossing depends on where the run executes.\n * Null falls back to the provider's env var (`VOLLEY_OLLAMA_URL` /\n * `VOLLEY_LMSTUDIO_URL` / `VOLLEY_OPENROUTER_URL`), then its default, never to\n * the critic's URL. Only a provider volley reaches at a base URL (ollama,\n * lmstudio, openrouter) takes one. */\n builder_url: string | null;\n builder_max_steps: number;\n /** How many tool calls a tool-loop builder may make in one turn, reads\n * aside (`read_file`, `search_files`, `list_files` are `read_only` and\n * don't count); fascicle runs a turn's calls in order up to the first one\n * past the cap, drops the rest, and tells the model which it dropped. 1 by\n * default, since some model and runtime pairs return parallel calls badly;\n * raise it for a pair that handles them. Ignored by the `claude_cli`\n * builder. */\n builder_max_tool_calls: number;\n /** The most output tokens a tool-loop builder may generate in one turn,\n * reasoning included, or null to leave each turn to the provider's own\n * limit. 16384 by default on a local builder (ollama, lmstudio), null on\n * openrouter. A turn cut off at it before it made a tool call costs that\n * one step, not the session: fascicle feeds back that it hit the limit and\n * the loop goes on. Ignored by the `claude_cli` builder. */\n builder_max_output_tokens: number | null;\n /** The estimated request size, in tokens, above which a tool-loop builder's\n * turns send older tool results as one-line stubs (#7), or null to send\n * every turn whole. Null by default, until a long local session is shown\n * to run faster with it on. Ignored by the `claude_cli` builder. */\n builder_trim_history: number | null;\n /** Operator opt-out permitting a non-`claude_cli` builder to run without a\n * sandbox — it gets a real host bash. Refused by default. */\n allow_unsandboxed_builder: boolean;\n critic_model: string;\n critic_provider: CriticProvider;\n /** The critic seat's own model server base URL (`--critic-url`), as given;\n * resolved like `builder_url`, and null never falls back to the builder's. */\n critic_url: string | null;\n builder_permission_mode: BuilderPermissionMode;\n critic_preset: CriticPreset | 'custom';\n critic_prompt_path: string | null;\n max_iterations: number;\n max_cost_usd: number | null;\n git_checkpoints: boolean;\n /** Isolate the builder run's effects in a per-run git worktree: the\n * builder/critic file tools' containment root moves to the worktree, while\n * the run's state stays where `state_dir` puts it (the control plane). Off by\n * default; requires the workspace to be a git repository. */\n worktree: boolean;\n /** Throw a `--worktree` run's effects away at teardown even when it converged:\n * the run branch is force-deleted rather than kept, because only the\n * verdicts are wanted. This is what `volley matrix` sweeps with — one config,\n * many builder×critic seats, no per-seat commits or branches left anywhere.\n * Refused without `--worktree`; `--git` still wins, so a `--worktree --git`\n * run integrates exactly as it always has. */\n discard_worktree: boolean;\n /** Glob patterns naming the *gate*: the tests, fixtures, and check\n * configuration that decide whether the builder's work passes. An edit to one\n * is reported to the critic and recorded in the summary — and refused outright\n * under `fail_on_gate_edit`. Defaults to `DEFAULT_GATE_PATTERNS`; a config's\n * own list replaces it, because what counts as the gate is the task's call\n * (a test-writing task edits tests by design). */\n gate_paths: string[];\n /** Halt the run when the builder edits a `gate_paths` match, instead of\n * reporting it and continuing. Off by default: a gate edit is legitimate often\n * enough that refusing it by default would break honest tasks, and the mark on\n * the summary already makes it impossible to miss. */\n fail_on_gate_edit: boolean;\n /** Container image the local-builder Docker sandbox runs. Defaults to\n * volley's own `Dockerfile`-built image; `--sandbox-image <tag>` /\n * `VOLLEY_SANDBOX_IMAGE` override it. Meaningful only for a local builder —\n * the `claude_cli` path never uses Docker. */\n sandbox_image: string;\n /** The root that holds each run's state at `<state_dir>/<run_id>/`, as an\n * absolute path: `--state-dir`, else the default root,\n * `$XDG_STATE_HOME/volley` or `~/.local/state/volley`. `resolve_config`\n * always sets one. Null is the layout older runs used, `<workspace>/.volley/`,\n * rotated aside by the next fresh run: a run an older volley started\n * resumes in it, and a hand-built config can still ask for it. */\n state_dir: string | null;\n workspace: string;\n verbose: boolean;\n quiet: boolean;\n json: boolean;\n show_thinking: boolean;\n};\n\n/** One failing check slot's raw artifact, for the critic prompt. */\nexport type CheckArtifact = {\n slot: string;\n path: string | null;\n content: string;\n truncated: boolean;\n};\n\nexport type CheckResult = {\n ran: boolean;\n runner: CheckRunnerKind;\n ok: boolean;\n exit_code: number | null;\n duration_ms: number;\n failing_slots: string[];\n detail: CheckArtifact[];\n /** Raw checkride summary JSON (when the runner is checkride). */\n summary?: unknown;\n /** checkride's capped excerpt of the failing slots (`.check/digest.md`),\n * when the check failed and checkride wrote one. */\n digest?: string;\n /** Captured combined output (when the runner is a shell command). */\n log?: string;\n};\n\n/** How one path changed between the run's baseline and the builder's output.\n * `renamed` covers git's rename/copy detection (the destination path is the one\n * recorded); `unknown` is any status git reports that none of these name. */\nexport type ChangeStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'unknown';\n\n/** One path the builder changed, and whether that path is part of the *gate* —\n * the tests, fixtures, and check configuration that decide whether the work\n * passes. A gate edit is not misconduct by itself (some tasks are *about* the\n * tests); it is the fact that makes a green check prove less. */\nexport type ChangedFile = {\n path: string;\n status: ChangeStatus;\n gate: boolean;\n};\n\n/** What the builder changed since the run's baseline, as the harness sees it\n * (`src/changes.ts`). Null in `LoopState` when the build root is not a git\n * repository — change detection is evidence, never a precondition. */\nexport type ChangeSet = {\n /** The commit the changes are measured against — the build root's HEAD before\n * the first iteration. Null in a repository with no commits yet, where only\n * untracked files can be reported. */\n baseline: string | null;\n /** The changed paths, sorted, capped at the collection limit. */\n files: ChangedFile[];\n /** Every gate-matching path — computed over the *full* list before the cap,\n * so truncation can never hide a gate edit. */\n gate_edits: string[];\n /** How many paths changed in total, before the cap. */\n total: number;\n truncated: boolean;\n};\n\n/** Per-phase record for iteration summaries. */\nexport type PhaseRecord = {\n provider: string;\n model: string;\n session_id: string | null;\n /** Wall-clock of the phase's model work, the same measure for every provider\n * so an all-local run and an all-Claude run compare directly. The builder's is\n * fascicle's `GenerateResult.timing`: the whole call, every turn and the tools\n * between them. The critic's spans its whole degradation ladder, failed\n * attempts included, since no one result's timing covers the attempts before\n * it. Neither counts the Ollama prewarm. */\n duration_ms: number;\n usage: UsageTotals;\n cost_usd: number | null;\n cost_source: CostSource;\n /** How the phase's generate call ended. For a local builder,\n * `'max_steps'` is a budget cutoff surfaced as a warning, not an error. */\n finish_reason: FinishReason;\n /** Tool calls fascicle executed in this phase, and how many were recovered\n * from assistant text rather than returned structurally — the raw\n * counts behind the salvage-rate health metric. */\n tool_calls: number;\n salvaged_tool_calls: number;\n /** Turns the provider cut off at the output cap before they made a tool\n * call (`--builder-max-output-tokens`), each of which cost a step and went\n * on. Set on a builder record when any was; absent otherwise. Additive. */\n truncated_turns?: number;\n /** Provider-error retries that preceded this phase's successful call\n * — the local-critic degradation ladder's first rung: a stochastic\n * Ollama stream death is retried once before falling back. Set on the critic\n * record (0 when the first call succeeded); absent on the builder, which is\n * not retried this build. Additive — old summary consumers ignore it. */\n retries?: number;\n /** The `cause_kind` of the retried provider error, recorded with `retries`.\n * Absent when no retry happened. */\n retry_cause_kind?: CauseKind;\n /** This local-critic verdict was rendered by the tool-less fallback rung:\n * the tool-bearing critique kept dying on the provider's stream\n * even after the bounded retry, or ran out of steps before its verdict, so the\n * critic judged with no read access — grounded only by the criteria, the raw\n * check artifacts, and a workspace file inventory. Set (true) on a degraded\n * critic record; absent on a full critique and on the builder. Additive, and a\n * degraded verdict is *always* marked so it never passes silently as a full\n * one. */\n critic_degraded?: boolean;\n /** Why the verdict degraded, set with `critic_degraded`. Additive. */\n degrade_cause?: DegradeCause;\n /** Output tokens per second over the model's own turns (tool execution and\n * retry backoff excluded), from fascicle's per-step timing. `basis` is\n * `decode` when every turn streamed, `blended` when any round trip counted\n * prefill and network too — always the case for `claude_cli`, whose rate\n * fascicle derives from the CLI's reported API time. Absent when no turn\n * carried timing. Additive.\n *\n * On Ollama, `decode` holds only while a turn's first chunk arrives as its\n * first token is generated. Ollama sends a tool call whole, so a turn whose\n * only output is a tool call dispatches nothing until generation ends, and\n * its tokens are divided by the last few milliseconds: a non-thinking seat's\n * rate reads far too high until robmclarty/fascicle#12 times those turns\n * another way. A thinking seat needs ai-sdk-ollama 4.3.0 or later, which\n * streams the reasoning even though volley never sets `think`. */\n throughput?: Throughput;\n /** Each turn of a builder session, in order, so a long session's growth\n * and where its time went can be read off the archive (#7). Set on a builder\n * record whose provider reported steps (every tool-loop builder); absent on\n * the critic and on a session with none. Additive. */\n steps?: BuilderStepRecord[];\n};\n\n/** Where a builder turn's prefill and decode times came from.\n * `ollama_reported`: Ollama's own `prompt_eval_duration` and `eval_duration`\n * (native transport). `ollama_derived`: prefill as `total_duration` less\n * `load_duration` and `eval_duration`, the ai_sdk transport's metadata, which\n * leaves `prompt_eval_duration` out; slightly high, since the total includes\n * Ollama's own overhead. `first_chunk`: prefill as the time to the first\n * streamed chunk, decode as the rest of the round trip. `none`: no split. */\nexport type StepTimingBasis = 'ollama_reported' | 'ollama_derived' | 'first_chunk' | 'none';\n\n/** One turn of a builder session. */\nexport type BuilderStepRecord = {\n index: number;\n /** The whole request this turn sent, so the session's growth reads as the\n * sequence of these. */\n input_tokens: number;\n output_tokens: number;\n /** The turn's provider round trip, tool execution excluded. */\n duration_ms: number;\n prefill_ms?: number;\n decode_ms?: number;\n timing_basis: StepTimingBasis;\n finish_reason: FinishReason;\n truncated?: true;\n /** Each tool call the turn made, and how many characters its result put\n * into the transcript every later turn resends. */\n tool_calls: Array<{ name: string; output_chars: number }>;\n};\n\nexport type HaltReason = 'cost_cap' | 'gate_edit' | null;\n\n/** Carry-state threaded through the fascicle loop. */\nexport type LoopState = {\n iteration: number;\n iteration_started_at: string;\n feedback: string | null;\n verdict: Verdict | null;\n unmet_criteria: string[];\n check: CheckResult | null;\n /** What the builder changed this iteration, measured against the run's\n * baseline (`src/changes.ts`). Null when the build root is not a git\n * repository, and before the first `build` step of a run. */\n changes: ChangeSet | null;\n builder: PhaseRecord | null;\n critic: PhaseRecord | null;\n total_usage: UsageTotals;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n check_duration_ms: number;\n /** How many of the run's builder sessions ended on the step limit\n * (`max_steps`) rather than calling finish. */\n builder_max_steps_hits: number;\n iteration_cost_usd: number;\n halt: HaltReason;\n cost_warned: boolean;\n};\n\nexport type RunInput = {\n resume_from: LoopState | null;\n};\n\n/** Projection of final loop state; the run's `summary.json` mirrors this. */\nexport type RunResult = {\n run_id: string;\n status: RunStatus;\n started_at: string;\n completed_at: string | null;\n iterations_completed: number;\n total_usage: UsageTotals;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n check_duration_ms: number;\n /** How many of the run's builder sessions hit the step limit before they\n * called finish: work handed to the check and critic unverified. The\n * warning a run prints for each goes to stderr, which `--json` silences, so\n * a harness reads it here. Always 0 for a `claude_cli` builder, which has\n * no step limit, and for a critique. */\n builder_max_steps_hits: number;\n final_verdict: Verdict | null;\n /** The run branch teardown left behind because this run's work was never\n * integrated: under `--worktree` without `--git` a converged run has no\n * other copy of its effects, so teardown commits them onto `volley/<run id>`\n * and keeps the branch instead of force-deleting it. Null whenever nothing\n * survived — every non-worktree run, every integrated run, every discarded\n * one. `--json` consumers read it here; the run's `summary.json` mirrors it. */\n salvaged_branch: string | null;\n /** A run, or a critique, which runs no builder. */\n mode: RunMode;\n /** Where this run keeps its config, summary, trajectory, feedback, verdict,\n * and iterations: `<state_dir>/<run_id>/` under a state root, else the\n * workspace's `.volley/`. Inside the sandbox container it is the container's\n * path, which a harness maps back to the directory it mounted. */\n run_state_dir: string;\n};\n\nexport type VolleyPhase = 'builder' | 'critic' | 'check';\n\n/** Recoverable domain failures surface as `kind`-tagged Error values (the\n * same discrimination style as fascicle's error taxonomy) so the top-level\n * handler maps them to exit codes without string matching or instanceof. */\nexport type ConfigError = Error & { kind: 'config_error' };\n\nexport type CheckError = Error & { kind: 'check_error' };\n\nexport type PhaseError = Error & {\n kind: 'phase_error';\n phase: VolleyPhase;\n iteration: number;\n cause: unknown;\n};\n\nexport function config_error(message: string): ConfigError {\n return Object.assign(new Error(message), { kind: 'config_error' as const });\n}\n\nexport function check_error(message: string): CheckError {\n return Object.assign(new Error(message), { kind: 'check_error' as const });\n}\n\n/** Wraps a provider/schema failure with the phase and iteration it hit. */\nexport function phase_error(\n phase: VolleyPhase,\n iteration: number,\n cause: unknown,\n): PhaseError {\n const detail = cause instanceof Error ? cause.message : String(cause);\n return Object.assign(\n new Error(`${phase} failed on iteration ${iteration}: ${detail}`),\n { kind: 'phase_error' as const, phase, iteration, cause },\n );\n}\n\nexport function error_kind(err: unknown): string | null {\n if (typeof err === 'object' && err !== null && 'kind' in err) {\n const kind = (err as { kind: unknown }).kind;\n return typeof kind === 'string' ? kind : null;\n }\n return null;\n}\n","/**\n * The ONLY module that calls fascicle's `create_engine`. Every\n * other module receives an `Engine`-shaped value, which keeps the engine\n * mockable in tests and confines provider knowledge to one seam.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { create_engine } from 'fascicle';\nimport type { Engine, ProviderConfigMap, PricingTable } from 'fascicle';\nimport { config_error } from './types.js';\nimport type { BuilderProvider, CriticProvider } from './types.js';\n\nexport type { Engine } from 'fascicle';\n\n/** LM Studio's OpenAI-compatible server and Ollama's server-root defaults.\n * The Ollama URL is the server root, NOT `…/api`: `ai-sdk-ollama` appends\n * `/api/...` itself, so a base URL ending in `/api` requests `/api/api/chat`\n * and 404s. */\nexport const DEFAULT_OLLAMA_URL = 'http://localhost:11434';\nexport const DEFAULT_LMSTUDIO_URL = 'http://localhost:1234/v1';\n/** OpenRouter's API root, the one fascicle's openrouter adapter defaults to. */\nexport const DEFAULT_OPENROUTER_URL = 'https://openrouter.ai/api/v1';\n\n/** The variable an `openrouter` seat's API key is read from. */\nconst OPENROUTER_KEY_VAR = 'OPENROUTER_API_KEY';\n\n/** The variable a `claude_cli` seat's API key is read from, which the Claude\n * CLI also reads on its own. */\nconst ANTHROPIC_KEY_VAR = 'ANTHROPIC_API_KEY';\n\n/** Every variable a seat reads a credential from. Every process volley starts\n * runs without them (the check, the builder's commands, and volley's own git\n * and checkride calls, which run hooks and filters the builder can write), so\n * nothing the builder writes can read the keys its seats spend. */\nexport const SEAT_CREDENTIAL_VARS: ReadonlyArray<string> = [OPENROUTER_KEY_VAR, ANTHROPIC_KEY_VAR];\n\n/** The environment every process volley starts runs with: `env`, `PATH`\n * included, less every variable a seat reads a credential from. */\nexport function command_env(env: Readonly<Record<string, string | undefined>>): Record<string, string> {\n const stripped: ReadonlySet<string> = new Set(SEAT_CREDENTIAL_VARS);\n return Object.fromEntries(\n Object.entries(env).filter(\n (entry): entry is [string, string] => entry[1] !== undefined && !stripped.has(entry[0]),\n ),\n );\n}\n\n/** Loopback authorities the container→host crossing rewrites. A base URL\n * pointing at one of these is local to wherever volley runs; contained, that is\n * *inside* the sandbox container, where the host LLM daemon is unreachable\n * except across the boundary at `VOLLEY_MODEL_HOST`. `URL.hostname` keeps an\n * IPv6 literal's brackets, so the IPv6 loopback is spelled `[::1]`. */\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]', '0.0.0.0']);\n\n/** Cross a loopback base URL to the host LLM endpoint. When volley\n * runs inside its sandbox container the local model daemon is on the *host*, so\n * the example's `docker run` injects `VOLLEY_MODEL_HOST=host.docker.internal`\n * (the host-gateway allowlist target; see `sandbox_invocation` in\n * `src/sandbox.ts`). This normalizer *consumes that override* and swaps a\n * loopback host for the gateway, so an unchanged `http://localhost:11434` still\n * reaches the host from in-container. A non-loopback URL (a real remote daemon)\n * is left untouched, and an unset `VOLLEY_MODEL_HOST` (the host / unsandboxed\n * path) is a no-op — so the default and all-Claude paths are unaffected. */\nexport function cross_to_host_gateway(\n base_url: string,\n env: Record<string, string | undefined>,\n): string {\n const host = env['VOLLEY_MODEL_HOST'];\n if (host === undefined || host === '') return base_url;\n let parsed: URL;\n try {\n parsed = new URL(base_url);\n } catch {\n return base_url;\n }\n if (!LOOPBACK_HOSTS.has(parsed.hostname.toLowerCase())) return base_url;\n parsed.hostname = host;\n // `URL` re-serializes `http://host:port` with a trailing `/`; drop it so the\n // Ollama server-root shape (no path) is preserved, while a real path (LM\n // Studio's `/v1`) is left intact.\n return parsed.toString().replace(/\\/$/, '');\n}\n\n/** The providers a seat reaches at a base URL volley configures. `claude_cli`\n * picks its own endpoint, so it never appears here. */\ntype UrlProvider = 'ollama' | 'lmstudio' | 'openrouter';\n\n/** Where a URL-taking provider's base URL comes from when a seat names none of\n * its own: the provider's env var, then its default. `normalize` canonicalizes\n * a URL from any source, so two spellings of one server compare equal. */\ntype SeatUrlSource = {\n env: string;\n default_url: string;\n normalize: (url: string) => string;\n};\n\nfunction strip_trailing_slashes(url: string): string {\n return url.replace(/\\/+$/, '');\n}\n\nconst SEAT_URL_SOURCES: Readonly<Record<UrlProvider, SeatUrlSource>> = {\n // A trailing `/api` (the pre-v0.3.1 documented default, and a natural mistake\n // since Ollama's REST paths all start with it) is stripped rather than left\n // to 404 every request.\n ollama: {\n env: 'VOLLEY_OLLAMA_URL',\n default_url: DEFAULT_OLLAMA_URL,\n normalize: (url) => strip_trailing_slashes(url).replace(/\\/api$/, ''),\n },\n // LM Studio's base URL keeps its `/v1`: the OpenAI-compatible client appends\n // `/chat/completions` to it.\n lmstudio: {\n env: 'VOLLEY_LMSTUDIO_URL',\n default_url: DEFAULT_LMSTUDIO_URL,\n normalize: strip_trailing_slashes,\n },\n // OpenRouter's base URL keeps its `/api/v1` the same way, so a seat URL can\n // name a proxy or another OpenAI-compatible gateway.\n openrouter: {\n env: 'VOLLEY_OPENROUTER_URL',\n default_url: DEFAULT_OPENROUTER_URL,\n normalize: strip_trailing_slashes,\n },\n};\n\n/** The providers that take a seat URL (`--builder-url` / `--critic-url`), and\n * so get their endpoint probed by `--dry-run`. */\nexport const SEAT_URL_PROVIDERS = Object.keys(SEAT_URL_SOURCES) as ReadonlyArray<UrlProvider>;\n\n/** Whether a seat on `provider` reaches its model at a base URL volley\n * configures, and so takes a URL of its own. */\nexport function takes_seat_url(\n provider: BuilderProvider | CriticProvider | undefined,\n): provider is UrlProvider {\n return (SEAT_URL_PROVIDERS as ReadonlyArray<string | undefined>).includes(provider);\n}\n\n/** An absent, empty, or all-whitespace value counts as unset. */\nfunction present(value: string | null | undefined): string | null {\n const trimmed = value?.trim() ?? '';\n return trimmed === '' ? null : trimmed;\n}\n\n/** The base URL a seat's model calls go to: the seat's own URL, else the\n * provider's env var (`VOLLEY_OLLAMA_URL` / `VOLLEY_LMSTUDIO_URL` /\n * `VOLLEY_OPENROUTER_URL`), else its default. A seat never falls back to the\n * other seat's URL. The result is normalized, then a loopback authority is\n * crossed to the host LLM endpoint when volley runs contained. Both seats can\n * be loopback URLs on different ports, and each crosses on its own port. */\nexport function seat_base_url(\n provider: UrlProvider,\n seat_url: string | null,\n env: Record<string, string | undefined>,\n): string {\n const source = SEAT_URL_SOURCES[provider];\n const raw = present(seat_url) ?? present(env[source.env]) ?? source.default_url;\n return cross_to_host_gateway(source.normalize(raw), env);\n}\n\n/** The API key an `openrouter` seat sends, from `OPENROUTER_API_KEY`. An unset\n * or blank key is a config error naming the variable, which `resolve_config`\n * raises before any work, because fascicle's own \"requires a non-empty\n * api_key\" doesn't say where the key comes from. */\nexport function openrouter_api_key(env: Record<string, string | undefined>): string {\n const key = present(env[OPENROUTER_KEY_VAR]);\n if (key === null) {\n throw config_error(\n `${OPENROUTER_KEY_VAR} is not set: an openrouter seat sends it as its API key`,\n );\n }\n return key;\n}\n\nfunction load_pricing_overrides(path: string): PricingTable {\n if (!existsSync(path)) {\n throw config_error(`VOLLEY_PRICING_PATH not found: ${path}`);\n }\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as PricingTable;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw config_error(`VOLLEY_PRICING_PATH is not valid JSON: ${detail}`);\n }\n}\n\nexport type EngineOptions = {\n /** The Claude session's working directory. A run passes its build root, which\n * is the worktree under `--worktree`, so the builder writes where the check\n * and the critic look. */\n workspace: string;\n /** When the builder runs on a URL-taking provider, that provider is\n * configured alongside claude_cli so one engine drives both roles. */\n builder_provider?: BuilderProvider;\n /** The builder seat's own base URL (`--builder-url`); null or absent falls\n * back to the provider's env var, then its default. */\n builder_url?: string | null;\n /** When the critic runs on a URL-taking provider, that provider is\n * configured alongside claude_cli so one engine drives both roles. */\n critic_provider?: CriticProvider;\n /** The critic seat's own base URL (`--critic-url`), resolved the same way. */\n critic_url?: string | null;\n env?: Record<string, string | undefined>;\n};\n\n/** A seat's provider entry, with the base URL resolved for that seat. The ai-sdk\n * peer (`ai-sdk-ollama` / `@ai-sdk/openai-compatible`) is loaded lazily by\n * fascicle only when the provider actually runs. The entry is complete, because\n * `Engine.with_providers` replaces a provider's whole entry: whatever this\n * returns is all a seat's derived engine knows about the provider, so an\n * `openrouter` entry carries its key and its transport along with its URL.\n *\n * `openrouter` runs on fascicle's native transport, its OpenAI-compatible core,\n * so no ai-sdk peer gets installed for it, and its `X-Title` attributes the\n * traffic to volley.\n *\n * For the local providers, native transport is the deferred future bridge, not\n * adopted here: they stay on the ai_sdk transport, which fascicle 0.14.0 already\n * selects by default (`transport?: 'ai_sdk' | 'native'` defaults to `'ai_sdk'`),\n * so no field is needed today. Flipping later is a one-line change — add\n * `transport: 'native'` to the ollama/lmstudio entry returned below, which both\n * seats' engines then share. No URL re-pointing is required: `seat_base_url`\n * already yields the daemon-root URL the native `/api/chat` transport wants\n * (its adapter appends `/api/chat` itself), which is exactly what the v0.3.1\n * base-URL fix produces.\n * Kept as a proven-once-then-reverted option so the transport stays a clean\n * second variable in the model-vs-transport comparison. Flipping it today would\n * also lose the reasoning: fascicle's native Ollama adapter drops\n * `message.thinking`, with `think` unset or true (robmclarty/fascicle#12), so a\n * thinking seat's reasoning would vanish from the terminal and the trajectory.\n *\n * Every provider's base URL crosses a loopback authority to `VOLLEY_MODEL_HOST`\n * when volley runs contained, so an in-container model client reaches the\n * host LLM endpoint at `host.docker.internal`; on the host / unsandboxed path the\n * override is unset and this is a no-op. */\nfunction seat_provider_config(\n provider: UrlProvider,\n seat_url: string | null,\n env: Record<string, string | undefined>,\n): ProviderConfigMap {\n const base_url = seat_base_url(provider, seat_url, env);\n switch (provider) {\n case 'ollama':\n return { ollama: { base_url } };\n case 'lmstudio':\n return { lmstudio: { base_url } };\n case 'openrouter':\n return {\n openrouter: {\n api_key: openrouter_api_key(env),\n base_url,\n transport: 'native',\n x_title: 'volley',\n },\n };\n }\n}\n\n/** Per-run engine. `claude_cli` is always configured with `options.workspace`\n * (the run's build root) as its session cwd; any URL-taking provider selected\n * by the builder or critic role is wired in alongside it, at that seat's URL,\n * so one engine drives both roles. An engine holds one URL per provider, so on\n * a provider both seats share it carries the builder's; `create_seat_engines`\n * gives the critic its own engine when its URL differs. Binary, auth mode,\n * fallback provider URLs, and pricing come from the environment. */\nexport function create_volley_engine(options: EngineOptions): Engine {\n const env = options.env ?? process.env;\n\n const auth_mode = env['VOLLEY_AUTH_MODE'] ?? 'auto';\n if (auth_mode !== 'auto' && auth_mode !== 'oauth' && auth_mode !== 'api_key') {\n throw config_error(\n `VOLLEY_AUTH_MODE must be auto, oauth, or api_key; got: ${auth_mode}`,\n );\n }\n\n const binary = env['VOLLEY_CLAUDE_BIN'];\n const pricing_path = env['VOLLEY_PRICING_PATH'];\n\n const providers: ProviderConfigMap = {\n claude_cli: {\n default_cwd: options.workspace,\n setting_sources: ['project', 'local'],\n auth_mode,\n // Under `oauth` the CLI inherits the whole environment to reach its\n // login, and hands it on to every command it runs; this keeps the other\n // seat's key out. fascicle drops these before it applies the auth mode,\n // so a configured `api_key` still reaches the CLI.\n omit_env: SEAT_CREDENTIAL_VARS,\n ...(binary !== undefined && binary.length > 0 ? { binary } : {}),\n ...(auth_mode === 'api_key' && env[ANTHROPIC_KEY_VAR] !== undefined\n ? { api_key: env[ANTHROPIC_KEY_VAR] }\n : {}),\n },\n };\n // A run may select a URL-taking provider for the builder, the critic, or both\n // (even two different ones). The critic's goes in first, so a critic-only\n // engine (the dry-run canary's) gets the critic's URL, and on a provider both\n // seats share, the builder's URL wins.\n if (takes_seat_url(options.critic_provider)) {\n Object.assign(\n providers,\n seat_provider_config(options.critic_provider, options.critic_url ?? null, env),\n );\n }\n if (takes_seat_url(options.builder_provider)) {\n Object.assign(\n providers,\n seat_provider_config(options.builder_provider, options.builder_url ?? null, env),\n );\n }\n\n return create_engine({\n providers,\n ...(pricing_path !== undefined && pricing_path.length > 0\n ? { pricing: load_pricing_overrides(pricing_path) }\n : {}),\n });\n}\n\n/** The engine each seat's model calls go through. */\nexport type SeatEngines = { builder: Engine; critic: Engine };\n\n/** One engine per seat, shared unless it can't be. fascicle fixes one base URL\n * per provider when it builds an engine, so two seats on the same provider at\n * different URLs need two engines: the critic's is derived from the builder's\n * with `with_providers`, which keeps claude_cli, auth, and pricing and\n * overrides only the shared provider's entry. Every other pairing, including a\n * run that sets no seat URL at all, gets the one engine a run has always had. */\nexport async function create_seat_engines(options: EngineOptions): Promise<SeatEngines> {\n const env = options.env ?? process.env;\n const builder = create_volley_engine(options);\n const provider = options.critic_provider;\n if (\n provider !== options.builder_provider ||\n !takes_seat_url(provider) ||\n seat_base_url(provider, options.builder_url ?? null, env) ===\n seat_base_url(provider, options.critic_url ?? null, env)\n ) {\n return { builder, critic: builder };\n }\n try {\n const critic = builder.with_providers(\n seat_provider_config(provider, options.critic_url ?? null, env),\n );\n return { builder, critic };\n } catch (err) {\n // Nothing has run on the builder's engine yet; release it, not leak it.\n await builder.dispose();\n throw err;\n }\n}\n\n/** Dispose each distinct seat engine once. Both disposals start together, so\n * one that fails doesn't keep the other from running. */\nexport async function dispose_seat_engines(engines: SeatEngines): Promise<void> {\n const distinct =\n engines.critic === engines.builder ? [engines.builder] : [engines.builder, engines.critic];\n await Promise.all(distinct.map((engine) => engine.dispose()));\n}\n","/**\n * Shared workspace tools: `contain()` path confinement plus the read-only\n * tool set (`read_file`, `search_files`, `list_files`).\n *\n * The claude_cli builder/critic get file access from the CLI's own built-in\n * tools. API-style providers (ollama, lmstudio, …) have no built-ins, so\n * volley supplies its own. The critic uses the read-only set as-is via\n * `src/critic/tools.ts`; the builder set in\n * `src/builder/tools.ts` reuses `contain()` and the read tools and adds its\n * write/exec surface. Every path is resolved and confined to the\n * workspace root.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { z } from 'zod';\nimport type { Tool } from 'fascicle';\n\nexport const READ_FILE_MAX_BYTES = 200_000;\nexport const SEARCH_MAX_MATCHES = 200;\nconst LIST_MAX_ENTRIES = 2000;\n\n/** Directories never worth handing a seat; they bury signal and blow the\n * traversal budget. The acp seats' `list_files` and `search` skip the same\n * names (`./acp_tools.ts`), so a seat sees one tree under acp and on the CLI. */\nexport const IGNORED_DIRS: ReadonlySet<string> = new Set([\n 'node_modules',\n '.git',\n '.volley',\n '.check',\n 'dist',\n '.cache',\n]);\n\n/** Which tool set a seat holds, so its prompt names the tools it has: volley's\n * own (`'volley'`), or fascicle's workspace tools under `volley acp`\n * (`'acp'`). */\nexport type ToolSet = 'volley' | 'acp';\n\n/** Resolve `rel` inside `workspace`, rejecting absolute paths and any `..`\n * escape. Returns the absolute path; throws on containment violation. The\n * `workspace` root passed here is the build root, which is the per-run git\n * worktree under `--worktree` (`build_root`), not necessarily the\n * workspace the run was started on. */\nexport function contain(workspace: string, rel: string): string {\n const root = resolve(workspace);\n const candidate = isAbsolute(rel) ? resolve(rel) : resolve(root, rel);\n const within = candidate === root || candidate.startsWith(`${root}${sep}`);\n if (!within) {\n throw new Error(`path escapes the workspace: ${rel}`);\n }\n return candidate;\n}\n\ntype WalkEntry = { rel: string; abs: string };\n\nfunction walk(root: string, start: string, limit: number): WalkEntry[] {\n const out: WalkEntry[] = [];\n const stack = [start];\n while (stack.length > 0 && out.length < limit) {\n const dir = stack.pop() as string;\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n continue;\n }\n for (const name of entries) {\n const abs = join(dir, name);\n let is_dir: boolean;\n try {\n is_dir = statSync(abs).isDirectory();\n } catch {\n continue;\n }\n if (is_dir) {\n if (!IGNORED_DIRS.has(name)) stack.push(abs);\n continue;\n }\n out.push({ rel: relative(root, abs), abs });\n if (out.length >= limit) break;\n }\n }\n return out;\n}\n\n/** The files a read tool's optional `path` covers: the whole tree, the tree\n * under a directory, or the one file it names. A path that doesn't exist\n * throws, so the seat reads why rather than an empty result that looks like\n * \"nothing matched\". */\nfunction scoped_files(workspace: string, path: string | undefined, limit: number): WalkEntry[] {\n const root = resolve(workspace);\n if (path === undefined) return walk(root, root, limit);\n const start = contain(workspace, path);\n let is_dir: boolean;\n try {\n is_dir = statSync(start).isDirectory();\n } catch (err) {\n throw new Error(`no such file or directory: ${path}`, { cause: err });\n }\n return is_dir ? walk(root, start, limit) : [{ rel: relative(root, start), abs: start }];\n}\n\nfunction build_regex(pattern: string, flags: string): RegExp {\n try {\n return new RegExp(pattern, flags);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`invalid regular expression: ${detail}`);\n }\n}\n\nconst read_file_input = z.object({\n path: z.string().describe('Workspace-relative path to the file to read.'),\n});\n\nconst search_files_input = z.object({\n pattern: z.string().describe('JavaScript regular expression to match against each line.'),\n path: z\n .string()\n .optional()\n .describe('Optional workspace-relative directory or file to limit the search to.'),\n ignore_case: z.boolean().optional().describe('Case-insensitive match. Default false.'),\n});\n\nconst list_files_input = z.object({\n path: z\n .string()\n .optional()\n .describe('Optional workspace-relative directory or file. Default: the workspace root.'),\n contains: z\n .string()\n .optional()\n .describe('Optional substring filter applied to each relative path.'),\n});\n\n// Each is `read_only`, so a builder's per-turn call cap doesn't count it: a\n// read changes nothing a later call in the turn could depend on.\n//\n// Each tool is typed as fascicle's `Tool` (input `unknown`) and re-parses the\n// model's raw arguments with its own schema. fascicle's `Tool` is invariant\n// on the input type, so typed-per-tool values will not widen into `Tool[]`;\n// parsing inside `execute` keeps the wiring cast-free and validates arguments\n// at the boundary. The declared `input_schema` still drives the JSON schema\n// the model sees.\nexport function read_only_tools(workspace: string): Tool[] {\n const read_file: Tool = {\n name: 'read_file',\n read_only: true,\n description:\n 'Read a UTF-8 text file from the workspace. Returns the file content ' +\n `(truncated at ${String(READ_FILE_MAX_BYTES)} bytes).`,\n input_schema: read_file_input,\n execute: (raw) => {\n const input = read_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const content = readFileSync(abs, 'utf8');\n return content.length > READ_FILE_MAX_BYTES\n ? `${content.slice(0, READ_FILE_MAX_BYTES)}\\n… [truncated at ${String(READ_FILE_MAX_BYTES)} bytes]`\n : content;\n },\n };\n\n const search_files: Tool = {\n name: 'search_files',\n read_only: true,\n description:\n 'Search workspace files for lines matching a regular expression. Returns ' +\n `up to ${String(SEARCH_MAX_MATCHES)} \"relative/path:line: text\" hits.`,\n input_schema: search_files_input,\n execute: (raw) => {\n const input = search_files_input.parse(raw);\n const regex = build_regex(input.pattern, input.ignore_case === true ? 'i' : '');\n const files = scoped_files(workspace, input.path, LIST_MAX_ENTRIES);\n const hits: string[] = [];\n for (const file of files) {\n if (hits.length >= SEARCH_MAX_MATCHES) break;\n let content: string;\n try {\n content = readFileSync(file.abs, 'utf8');\n } catch {\n continue;\n }\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i += 1) {\n if (hits.length >= SEARCH_MAX_MATCHES) break;\n const line = lines[i] as string;\n if (regex.test(line)) hits.push(`${file.rel}:${String(i + 1)}: ${line.trim()}`);\n }\n }\n if (hits.length === 0) return 'no matches';\n const capped =\n hits.length >= SEARCH_MAX_MATCHES ? `\\n… [capped at ${String(SEARCH_MAX_MATCHES)} matches]` : '';\n return `${hits.join('\\n')}${capped}`;\n },\n };\n\n const list_files: Tool = {\n name: 'list_files',\n read_only: true,\n description:\n 'List files under a workspace directory (recursively; skips node_modules, ' +\n '.git, and other build/output directories).',\n input_schema: list_files_input,\n execute: (raw) => {\n const input = list_files_input.parse(raw);\n let files = scoped_files(workspace, input.path, LIST_MAX_ENTRIES).map((f) => f.rel);\n if (input.contains !== undefined) {\n const needle = input.contains;\n files = files.filter((f) => f.includes(needle));\n }\n if (files.length === 0) return 'no files';\n const capped =\n files.length >= LIST_MAX_ENTRIES ? `\\n… [capped at ${String(LIST_MAX_ENTRIES)} entries]` : '';\n return `${files.join('\\n')}${capped}`;\n },\n };\n\n return [read_file, search_files, list_files];\n}\n\n/** A `paths + sizes` listing of the workspace tree, no file contents — the\n * grounding a tool-less critic gets when its provider's tool parser died and the\n * degradation ladder traded read access for survival. Reuses the same\n * `walk` + `IGNORED_DIRS` traversal as the read tools, so the inventory matches\n * what a working `list_files` would have surfaced; caps at `limit` entries. */\nexport function workspace_inventory(root: string, limit: number = LIST_MAX_ENTRIES): string {\n const base = resolve(root);\n const files = walk(base, base, limit);\n if (files.length === 0) return 'no files';\n const lines = files.map((file) => {\n let size: number;\n try {\n size = statSync(file.abs).size;\n } catch {\n size = 0;\n }\n return `${file.rel} (${String(size)} bytes)`;\n });\n const capped =\n files.length >= limit ? `\\n… [capped at ${String(limit)} entries]` : '';\n return `${lines.join('\\n')}${capped}`;\n}\n","/**\n * Builder tool set for local (non-CLI) builders.\n *\n * A local model brings no built-in tools, so volley supplies the whole\n * agentic surface: the shared read-only trio (reused from\n * `src/workspace_tools.ts`) plus `write_file`, `edit_file`, `bash`,\n * `fetch`, and the terminal `finish`. File paths are confined to the\n * workspace via `contain()`.\n *\n * Error semantics: a wrong-but-recoverable input — `edit_file`\n * matching 0 or N places, a `bash` command exiting non-zero or timing out, a\n * `fetch` that is SSRF-blocked or fails — is *returned* as a tool result the\n * model reads and acts on. Tools throw only on a genuine harness fault\n * (containment violation, unreadable input, over-cap write).\n *\n * `fetch` is a native readability pipeline (`linkedom` + `@mozilla/\n * readability` + `turndown`) with SSRF protection at the undici connector, not\n * as a pre-flight URL check: a validating DNS `lookup` rejects hostnames that\n * resolve to a non-unicast address before the TCP connect, and the resolved\n * socket's peer address is re-checked after connect — which also catches\n * literal-IP URLs (Node skips `lookup` for those) and every redirect hop\n * (each re-dispatches through the same guarded connector). The byte cap is\n * enforced while reading the HTTP stream, so raw HTML is never returned and a\n * huge page cannot OOM the tool.\n *\n * Egress is defended in two independent layers: this tool's SSRF\n * deny-list (above) and the sandbox's container network posture (`--network none`\n * by default, or a host-collapsed allowlist bridge — see `SandboxNetwork` in\n * `src/sandbox.ts`). Under whole-process containment the whole volley\n * process — `fetch` included — runs inside the container, so both layers apply to\n * `fetch`'s egress: `--network none` leaves it no route and it returns a \"could\n * not fetch\" error result, and the loop continues.\n */\nimport { spawnSync } from 'node:child_process';\nimport { lookup as dns_lookup } from 'node:dns';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport type { LookupFunction } from 'node:net';\nimport { dirname } from 'node:path';\nimport { Readability } from '@mozilla/readability';\nimport ipaddr from 'ipaddr.js';\nimport { parseHTML } from 'linkedom';\nimport TurndownService from 'turndown';\nimport { Agent, buildConnector, interceptors, request } from 'undici';\nimport { z } from 'zod';\nimport type { Tool, ToolExecContext } from 'fascicle';\nimport { command_env } from '../engine.js';\nimport { contain, read_only_tools } from '../workspace_tools.js';\n\nexport const WRITE_FILE_MAX_BYTES = 1_000_000;\n\n// Sized to fit a workspace `pnpm check`: volley's own checkride timeout is\n// 600s, so a shorter budget would kill the builder's self-verify\n// mid-run. Overridable per call site via `BuilderToolOptions` (tests use a\n// short value so the timeout path is exercised without a 10-minute wait).\nexport const BASH_TIMEOUT_MS = 600_000;\n\n// Model-facing cap on each of stdout/stderr; oversize output is truncated\n// with a marker. Not a memory guard — `BASH_CAPTURE_MAX_BYTES`\n// below bounds what `spawnSync` buffers before we ever truncate.\nconst BASH_MAX_OUTPUT_BYTES = 100_000;\n\n// OOM backstop on `spawnSync`'s captured output, well above the display cap:\n// a command that floods gigabytes is bounded here, then truncated to the\n// display cap for the model.\nconst BASH_CAPTURE_MAX_BYTES = 10_000_000;\n\n// Hard cap on bytes read from the HTTP stream before conversion: a page\n// larger than this is truncated at the socket, so raw HTML never reaches the\n// model and a huge page cannot OOM the tool.\nconst FETCH_MAX_BYTES = 200_000;\n\n// Default page-size for the model-facing markdown slice; `start_index`\n// paginates through the rest (MCP fetch-server contract).\nconst FETCH_MAX_CHARS = 5000;\n\n// How many redirect hops to follow. Each hop re-dispatches through the same\n// SSRF-guarded connector, so a redirect into a private range is still refused.\nconst FETCH_MAX_REDIRECTS = 5;\n\n// Per-request timeout (headers and body idle), in ms.\nconst FETCH_TIMEOUT_MS = 30_000;\n\n// Below this, readability's extraction is treated as a miss (empty article /\n// JS-rendered SPA) and we fall back to converting the whole document body.\nconst FETCH_MIN_EXTRACT_CHARS = 200;\n\nconst FETCH_USER_AGENT = 'volley-local-builder';\n\n/** The raw outcome of running one bash command, before the model-facing\n * truncation + timeout marker the `bash` tool applies. `status` is the exit code\n * (null when the process was killed by a signal — e.g. the timeout SIGKILL);\n * `timed_out` marks the timeout path. */\nexport type BashOutcome = {\n status: number | null;\n stdout: string;\n stderr: string;\n timed_out: boolean;\n};\n\n/** How the `bash` tool runs a command: the local `host_bash_executor`\n * (`spawnSync`) — which under whole-process containment runs *inside*\n * volley's own hardened container, no `docker exec` hop. The executor runs one\n * command to completion and returns its raw outcome; the `bash` tool owns the\n * truncation + timeout marker. Kept as an injectable seam so tests can supply a\n * fake and a future shape could re-point it (the `docker exec` executor was\n * retired). */\nexport type BashExecutor = (\n command: string,\n options: { timeout_ms: number; max_capture_bytes: number },\n) => BashOutcome;\n\nexport type BuilderToolOptions = {\n /** Override `BASH_TIMEOUT_MS` (ms). */\n bash_timeout_ms?: number;\n /** Override `BASH_MAX_OUTPUT_BYTES` (bytes, per stream). */\n bash_max_output_bytes?: number;\n /**\n * Where `bash` runs a command. Defaults to `host_bash_executor` — the local\n * `spawnSync`, which under containment runs inside volley's own container against the\n * bind-mounted worktree. Injectable so tests can supply a fake (the\n * `docker exec` executor was retired).\n */\n bash_executor?: BashExecutor;\n /** Override `FETCH_MAX_BYTES` (bytes read from the HTTP stream before the cap). */\n fetch_max_bytes?: number;\n /**\n * Test seam: override the connection-time SSRF classifier. Production leaves\n * this unset and uses `is_forbidden_address`, which rejects every non-unicast\n * (private / loopback / link-local / CGNAT / …) address. Tests set it to reach\n * a loopback fixture server while still exercising the real rejection path.\n */\n fetch_is_address_forbidden?: (address: string) => boolean;\n /**\n * Test seam: override the DNS resolver the SSRF connector validates through.\n * Defaults to `node:dns` `lookup`. Lets a test point a hostname at a private\n * address to exercise the redirect-into-private-range rejection.\n */\n fetch_lookup?: LookupFunction;\n};\n\nconst write_file_input = z.object({\n path: z.string().describe('Workspace-relative path to write. Parent directories are created.'),\n content: z.string().describe('Full UTF-8 content of the file. Overwrites any existing content.'),\n});\n\nconst edit_file_input = z.object({\n path: z.string().describe('Workspace-relative path of the file to edit.'),\n old_str: z\n .string()\n .min(1)\n .describe('Exact text to replace. Must occur exactly once in the file.'),\n new_str: z.string().describe('Replacement text.'),\n});\n\nconst bash_input = z.object({\n command: z.string().describe('Shell command to run in the workspace directory.'),\n});\n\nconst finish_input = z.object({\n summary: z.string().describe('Short summary of what was accomplished.'),\n});\n\nconst fetch_input = z.object({\n url: z.string().describe('Absolute http(s) URL to fetch.'),\n max_chars: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`Maximum characters of extracted markdown to return (default ${String(FETCH_MAX_CHARS)}).`),\n start_index: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe('Character offset into the extracted markdown to start from, for paging a long page. Default 0.'),\n});\n\nfunction count_occurrences(haystack: string, needle: string): number {\n return haystack.split(needle).length - 1;\n}\n\n/** Truncate `text` to at most `max` bytes, appending a marker when clipped.\n * Byte-based to honor the byte cap; a split multibyte char at the boundary\n * renders as the replacement char, which is acceptable for tool output. */\nfunction truncate_bytes(text: string, max: number): string {\n if (Buffer.byteLength(text, 'utf8') <= max) return text;\n const clipped = Buffer.from(text, 'utf8').subarray(0, max).toString('utf8');\n return `${clipped}\\n… [truncated at ${String(max)} bytes]`;\n}\n\n/**\n * Non-unicast → forbidden. Rejects loopback, private, link-local,\n * unspecified, broadcast, multicast, CGNAT, and the IPv6 equivalents; an\n * IPv4-mapped IPv6 address is folded to its v4 form first so `::ffff:127.0.0.1`\n * is caught as loopback (and `::ffff:<public>` is still allowed). An\n * unparseable address fails closed.\n */\nexport function is_forbidden_address(address: string): boolean {\n let parsed;\n try {\n parsed = ipaddr.parse(address);\n } catch {\n return true;\n }\n const canonical =\n 'isIPv4MappedAddress' in parsed && parsed.isIPv4MappedAddress() ? parsed.toIPv4Address() : parsed;\n return canonical.range() !== 'unicast';\n}\n\n// Default DNS resolver the SSRF connector validates through; the `fetch_lookup`\n// option swaps it in tests.\nconst default_resolver: LookupFunction = (hostname, options, callback) => {\n dns_lookup(hostname, options, callback);\n};\n\n// A `lookup` that resolves normally, then rejects the connection if any\n// resolved address is forbidden — closing the DNS-rebinding / redirect-hop gap\n// a pre-flight URL check leaves open. Runs before the TCP connect, so a\n// hostname pointing at a private range never opens a socket.\nfunction guarded_lookup(is_forbidden: (address: string) => boolean, resolve: LookupFunction): LookupFunction {\n return (hostname, options, callback) => {\n resolve(hostname, options, (err, address, family) => {\n if (err !== null) {\n callback(err, '', 0);\n return;\n }\n const resolved = Array.isArray(address) ? address.map((entry) => entry.address) : [address];\n const blocked = resolved.find((entry) => is_forbidden(entry));\n if (blocked !== undefined) {\n callback(ssrf_error(blocked, hostname), '', 0);\n return;\n }\n callback(null, address, family);\n });\n };\n}\n\nfunction ssrf_error(address: string, hostname: string): NodeJS.ErrnoException {\n const err: NodeJS.ErrnoException = new Error(\n `blocked non-unicast address ${address} for host \"${hostname}\"`,\n );\n err.code = 'ERR_SSRF_BLOCKED';\n return err;\n}\n\n// An undici Agent whose connector validates SSRF at two points: the `lookup`\n// above (hostnames, before connect) and the peer address of the established\n// socket (which also catches literal-IP URLs — Node skips `lookup` for those —\n// and every redirect hop, since each re-dispatches through this connector).\nfunction create_ssrf_agent(is_forbidden: (address: string) => boolean, resolve: LookupFunction): Agent {\n const base = buildConnector({ lookup: guarded_lookup(is_forbidden, resolve), timeout: FETCH_TIMEOUT_MS });\n const connector: typeof base = (options, callback) => {\n base(options, (err, socket) => {\n if (err !== null) {\n callback(err, null);\n return;\n }\n if (socket === null) {\n callback(new Error('connection produced no socket'), null);\n return;\n }\n const remote = socket.remoteAddress;\n if (remote !== undefined && is_forbidden(remote)) {\n socket.destroy();\n callback(ssrf_error(remote, options.hostname), null);\n return;\n }\n callback(null, socket);\n });\n };\n return new Agent({ connect: connector, headersTimeout: FETCH_TIMEOUT_MS, bodyTimeout: FETCH_TIMEOUT_MS });\n}\n\n// Read the response body, stopping at `max_bytes` so raw HTML never fully\n// buffers. Breaking the `for await` destroys the stream, ending the\n// download.\nasync function read_body_capped(body: AsyncIterable<Buffer>, max_bytes: number): Promise<Buffer> {\n const chunks: Buffer[] = [];\n let total = 0;\n for await (const chunk of body) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n const remaining = max_bytes - total;\n if (buf.length >= remaining) {\n chunks.push(buf.subarray(0, remaining));\n break;\n }\n chunks.push(buf);\n total += buf.length;\n }\n return Buffer.concat(chunks);\n}\n\nfunction header_value(value: string | string[] | undefined): string {\n if (Array.isArray(value)) return value[0] ?? '';\n return value ?? '';\n}\n\nfunction content_kind(content_type: string, body: string): 'html' | 'text' | 'binary' {\n const ct = content_type.toLowerCase();\n if (ct.includes('html') || ct.includes('xml')) return 'html';\n if (\n ct.startsWith('text/') ||\n ct.includes('json') ||\n ct.includes('javascript') ||\n ct.includes('csv')\n ) {\n return 'text';\n }\n if (ct === '') return body.trimStart().startsWith('<') ? 'html' : 'text';\n return 'binary';\n}\n\n// Extract the main content as markdown: readability over a linkedom DOM, then\n// turndown. Falls back to converting the whole document when readability finds\n// little (empty article / JS-rendered SPA). Never returns raw HTML.\nfunction extract_markdown(html: string): string {\n const turndown = new TurndownService({ headingStyle: 'atx', codeBlockStyle: 'fenced' });\n turndown.remove(['script', 'style', 'noscript']);\n let body_markdown = '';\n let title = '';\n try {\n const { document } = parseHTML(html);\n const article = new Readability(document).parse();\n if (article !== null) {\n title = (article.title ?? '').trim();\n if (article.content) {\n body_markdown = turndown.turndown(article.content).trim();\n }\n }\n } catch {\n body_markdown = '';\n }\n if (body_markdown.length < FETCH_MIN_EXTRACT_CHARS) {\n let fallback = '';\n try {\n fallback = turndown.turndown(html).trim();\n } catch {\n fallback = '';\n }\n if (fallback.length > body_markdown.length) body_markdown = fallback;\n }\n const prefix = title.length > 0 && !body_markdown.startsWith(`# ${title}`) ? `# ${title}\\n\\n` : '';\n return `${prefix}${body_markdown}`.trim();\n}\n\n// MCP fetch-server pagination: return the `max_chars` slice at `start_index`,\n// and when more remains, a self-describing trailer naming the next start_index.\nfunction paginate(full: string, max_chars: number, start_index: number): string {\n if (start_index >= full.length) {\n return `(no more content: start_index ${String(start_index)} is at or past the end of the ${String(full.length)}-character document)`;\n }\n const slice = full.slice(start_index, start_index + max_chars);\n const next = start_index + slice.length;\n if (next >= full.length) return slice;\n const remaining = full.length - next;\n return `${slice}\\n\\n<truncated: ${String(remaining)} more characters. Call fetch again with start_index=${String(next)} to continue.>`;\n}\n\n// Flatten an error (and its `cause` chain) into a single line for the model.\nfunction error_detail(err: unknown): string {\n const parts: string[] = [];\n const seen = new Set<unknown>();\n let current: unknown = err;\n while (current !== undefined && current !== null && !seen.has(current)) {\n seen.add(current);\n if (current instanceof Error) {\n const code = (current as NodeJS.ErrnoException).code;\n parts.push(code !== undefined ? `${current.message} [${code}]` : current.message);\n current = (current as { cause?: unknown }).cause;\n } else {\n // Thrown values are Errors in practice; a non-Error is defensive only, so\n // keep a string as-is and never risk an \"[object Object]\" stringification.\n parts.push(typeof current === 'string' ? current : `non-error value (${typeof current})`);\n break;\n }\n }\n return parts.length > 0 ? parts.join(' <- ') : 'unknown error';\n}\n\ntype FetchConfig = {\n is_forbidden: (address: string) => boolean;\n resolve: LookupFunction;\n max_bytes: number;\n};\n\nasync function run_fetch(raw: unknown, ctx: ToolExecContext, config: FetchConfig): Promise<string> {\n const input = fetch_input.parse(raw);\n const max_chars = input.max_chars ?? FETCH_MAX_CHARS;\n const start_index = input.start_index ?? 0;\n\n let target: URL;\n try {\n target = new URL(input.url);\n } catch {\n return `error: not a valid absolute URL: ${input.url}`;\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') {\n return `error: unsupported URL scheme \"${target.protocol}\" — only http and https are fetched`;\n }\n\n const agent = create_ssrf_agent(config.is_forbidden, config.resolve);\n const dispatcher = agent.compose(interceptors.redirect({ maxRedirections: FETCH_MAX_REDIRECTS }));\n try {\n const res = await request(target.href, {\n dispatcher,\n signal: ctx.abort,\n headersTimeout: FETCH_TIMEOUT_MS,\n bodyTimeout: FETCH_TIMEOUT_MS,\n headers: {\n 'user-agent': FETCH_USER_AGENT,\n accept: 'text/html,application/xhtml+xml,text/plain;q=0.9,*/*;q=0.8',\n // No compression: keep the pipeline simple and the byte cap honest.\n 'accept-encoding': 'identity',\n },\n });\n if (res.statusCode >= 400) {\n await res.body.dump();\n return `error: HTTP ${String(res.statusCode)} fetching ${target.href}`;\n }\n const bytes = await read_body_capped(res.body, config.max_bytes);\n const content_type = header_value(res.headers['content-type']);\n const text = bytes.toString('utf8');\n if (text.trim().length === 0) {\n return `error: empty response body from ${target.href}`;\n }\n const kind = content_kind(content_type, text);\n if (kind === 'binary') {\n return `error: cannot extract non-text content (content-type: ${content_type}) from ${target.href}`;\n }\n const markdown = kind === 'html' ? extract_markdown(text) : text.trim();\n if (markdown.length === 0) {\n return `error: no readable content extracted from ${target.href}`;\n }\n return paginate(markdown, max_chars, start_index);\n } catch (err) {\n return `error: could not fetch ${target.href}: ${error_detail(err)}`;\n } finally {\n await agent.close().catch(() => undefined);\n }\n}\n\n/**\n * The `bash` executor: run the command via `spawnSync` with a shell, bounded by\n * the timeout (SIGKILL on expiry) and the OOM capture cap. Under whole-process\n * containment this runs *inside* volley's hardened container against the\n * bind-mounted worktree — the container is the isolation boundary, no\n * `docker exec` hop — and it is likewise the executor on the\n * `--allow-unsandboxed-builder` host escape hatch. A command runs with\n * volley's environment less the seats' keys, so nothing the builder runs can\n * read the key its seat spends. `status` is null when a signal (the timeout\n * SIGKILL) killed the process.\n */\nfunction host_bash_executor(cwd: string): BashExecutor {\n return (command, options) => {\n const result = spawnSync(command, {\n shell: true,\n cwd,\n env: command_env(process.env),\n encoding: 'utf8',\n timeout: options.timeout_ms,\n killSignal: 'SIGKILL',\n maxBuffer: options.max_capture_bytes,\n });\n return {\n status: result.status,\n stdout: result.stdout ?? '',\n stderr: result.stderr ?? '',\n timed_out: (result.error as NodeJS.ErrnoException | undefined)?.code === 'ETIMEDOUT',\n };\n };\n}\n\n// Same wiring convention as the shared read tools: each tool is typed as\n// fascicle's `Tool` (input `unknown`) and re-parses the model's raw\n// arguments with its own schema inside `execute`.\nexport function builder_tools(workspace: string, options: BuilderToolOptions = {}): Tool[] {\n const bash_timeout_ms = options.bash_timeout_ms ?? BASH_TIMEOUT_MS;\n const bash_max_output_bytes = options.bash_max_output_bytes ?? BASH_MAX_OUTPUT_BYTES;\n const bash_executor = options.bash_executor ?? host_bash_executor(workspace);\n\n const write_file: Tool = {\n name: 'write_file',\n description:\n 'Write a UTF-8 text file in the workspace, creating parent directories ' +\n 'and overwriting any existing content. Rejects content over ' +\n `${String(WRITE_FILE_MAX_BYTES)} bytes.`,\n input_schema: write_file_input,\n execute: (raw) => {\n const input = write_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const bytes = Buffer.byteLength(input.content, 'utf8');\n if (bytes > WRITE_FILE_MAX_BYTES) {\n throw new Error(\n `content is ${String(bytes)} bytes, over the ${String(WRITE_FILE_MAX_BYTES)}-byte write cap`,\n );\n }\n mkdirSync(dirname(abs), { recursive: true });\n writeFileSync(abs, input.content, 'utf8');\n return `wrote ${String(bytes)} bytes to ${input.path}`;\n },\n };\n\n const edit_file: Tool = {\n name: 'edit_file',\n description:\n 'Replace one exact occurrence of old_str with new_str in a workspace ' +\n 'file. old_str must match the file content exactly once — on 0 or ' +\n 'multiple matches nothing is changed and an error is returned; read ' +\n 'the file and retry with a longer, unique old_str.',\n input_schema: edit_file_input,\n execute: (raw) => {\n const input = edit_file_input.parse(raw);\n const abs = contain(workspace, input.path);\n const content = readFileSync(abs, 'utf8');\n const matches = count_occurrences(content, input.old_str);\n if (matches === 0) {\n return (\n `error: old_str not found in ${input.path} (0 matches). ` +\n 'No change made. Read the file and retry with an exact excerpt of its current content.'\n );\n }\n if (matches > 1) {\n return (\n `error: old_str matches ${String(matches)} times in ${input.path}. ` +\n 'No change made. Include more surrounding context to make old_str unique.'\n );\n }\n writeFileSync(abs, content.replace(input.old_str, input.new_str), 'utf8');\n return `edit applied to ${input.path}`;\n },\n };\n\n const bash: Tool = {\n name: 'bash',\n description:\n 'Run a shell command in the workspace and return its exit code, stdout, ' +\n 'and stderr. Each call is independent — no shell state (working ' +\n 'directory, environment, variables) carries over between commands. A ' +\n 'non-zero exit is a normal result, not an error: read it and adjust. ' +\n `Each stream is truncated past ${String(bash_max_output_bytes)} bytes, ` +\n `and the command is killed if it runs longer than ${String(bash_timeout_ms)}ms.`,\n input_schema: bash_input,\n // Stateless per command (the executor is injectable without touching\n // this contract — under containment it is the local `spawnSync` running in-container),\n // and never throws on the command's own failure — a non-zero exit or a\n // timeout is *returned* as `{ exit_code, stdout, stderr }` for the model to\n // read. The executor buffers up to `BASH_CAPTURE_MAX_BYTES` (OOM guard)\n // before we truncate to the model-facing cap.\n execute: (raw) => {\n const input = bash_input.parse(raw);\n const outcome = bash_executor(input.command, {\n timeout_ms: bash_timeout_ms,\n max_capture_bytes: BASH_CAPTURE_MAX_BYTES,\n });\n let stderr = truncate_bytes(outcome.stderr, bash_max_output_bytes);\n if (outcome.timed_out) {\n const note = `[command timed out after ${String(bash_timeout_ms)}ms and was killed]`;\n stderr = stderr.length > 0 ? `${stderr}\\n${note}` : note;\n }\n // `status` is the numeric exit code, or null when the process was killed\n // by a signal (e.g. the timeout SIGKILL).\n return {\n exit_code: outcome.status,\n stdout: truncate_bytes(outcome.stdout, bash_max_output_bytes),\n stderr,\n };\n },\n };\n\n const fetch: Tool = {\n name: 'fetch',\n description:\n 'Fetch an http(s) URL and return its main content converted to Markdown. ' +\n `Returns at most max_chars characters (default ${String(FETCH_MAX_CHARS)}); ` +\n 'when the page is longer, a trailer names the start_index to pass to read ' +\n 'the next slice. Private, loopback, and link-local addresses are refused. ' +\n 'A blocked, non-HTML, or failed request returns an error string you can read and act on.',\n input_schema: fetch_input,\n // Native readability pipeline with connection-time SSRF protection; a\n // blocked / non-HTML / HTTP error is returned as a tool result, not\n // thrown. The classifier and resolver are overridable for tests only.\n execute: (raw, ctx) =>\n run_fetch(raw, ctx, {\n is_forbidden: options.fetch_is_address_forbidden ?? is_forbidden_address,\n resolve: options.fetch_lookup ?? default_resolver,\n max_bytes: options.fetch_max_bytes ?? FETCH_MAX_BYTES,\n }),\n };\n\n return [...read_only_tools(workspace), write_file, edit_file, bash, fetch, finish_tool()];\n}\n\n/** The terminal `finish` tool, on its own for a builder set that brings its\n * own file and command tools (`../acp_tools.ts`). */\nexport function finish_tool(): Tool {\n return {\n name: 'finish',\n description:\n 'Declare the task complete. Calling this tool ends your turn — do not ' +\n 'call it until the work is done and verified.',\n input_schema: finish_input,\n // A successful `finish` ends the loop deterministically. The summary\n // is recorded in the trajectory like any tool call and otherwise ignored\n // — the workspace, not the self-report, is truth.\n ends_turn: true,\n execute: (raw) => {\n const input = finish_input.parse(raw);\n return `finished: ${input.summary}`;\n },\n };\n}\n","/**\n * checkride runner: spawn `pnpm exec checkride --json --digest`, gate on the\n * `.check/summary.json` contract (`schema_version: 1`), and collect raw\n * failing-slot artifacts for the critic — the critic reads what the tool\n * actually said, not a normalized digest. The digest checkride writes on a red\n * run is kept beside them for the next builder, which needs a short list of\n * what to fix more than the whole of every slot's output.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { isAbsolute, join, relative, sep } from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { ChildProcess } from 'node:child_process';\nimport { aborted_error } from 'fascicle';\nimport { command_env } from '../engine.js';\nimport { check_error } from '../types.js';\nimport type { CheckArtifact, CheckResult } from '../types.js';\n\nexport const CHECK_ARTIFACT_MAX_CHARS = 8000;\n\nconst CHECKRIDE_SCHEMA_VERSION = 1;\n\nexport type CheckrideSummaryCheck = {\n name: string;\n adapter: string | null;\n ok: boolean;\n skipped?: boolean;\n exit_code: number | null;\n duration_ms: number;\n output_file: string | null;\n};\n\nexport type CheckrideSummary = {\n schema_version: number;\n ok: boolean;\n total_duration_ms: number;\n checks: CheckrideSummaryCheck[];\n};\n\nexport type SpawnCaptureResult = {\n exit_code: number | null;\n stdout: string;\n stderr: string;\n};\n\n/** How long a check's output may stay open after its shell exits, while\n * something that escaped its process group still holds it, before the reads\n * stop so the check can finish. */\nconst OUTPUT_GRACE_MS = 2000;\n\n/** Kill a check's whole process group with SIGKILL. A test runner's workers,\n * and anything the check started in the background, sit in the shell's group,\n * so killing the shell alone would leave them running. Windows has no process\n * groups to signal, so there only the shell goes. */\nfunction kill_group(proc: ChildProcess): void {\n if (proc.pid === undefined) return;\n try {\n if (process.platform === 'win32') proc.kill('SIGKILL');\n else process.kill(-proc.pid, 'SIGKILL');\n } catch {\n // The group is gone: every process in it has exited.\n }\n}\n\n/** What a check runs with beside its command. */\nexport type CheckSpawnOptions = {\n abort?: AbortSignal;\n /** The whole environment the check runs with, in place of volley's own;\n * nothing is merged in, so it carries the `PATH` the check needs. Absent,\n * the check gets volley's less the seats' keys. */\n env?: Readonly<Record<string, string>>;\n};\n\n/** Run a check to its end in a process group of its own, capturing its\n * output. The abort kills the whole group and rejects with `aborted_error`,\n * and the shell's exit kills whatever it left behind, so a stopped run leaves\n * no test workers or servers running. */\nexport function spawn_capture(\n cmd: string,\n args: string[],\n options: CheckSpawnOptions & { cwd: string },\n): Promise<SpawnCaptureResult> {\n const { abort } = options;\n if (abort?.aborted === true) return Promise.reject(new aborted_error('check aborted'));\n return new Promise((resolve_promise, reject) => {\n const proc = spawn(cmd, args, {\n cwd: options.cwd,\n env: options.env ?? command_env(process.env),\n detached: process.platform !== 'win32',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let stdout = '';\n let stderr = '';\n let grace: NodeJS.Timeout | undefined;\n const on_abort = (): void => {\n kill_group(proc);\n reject(new aborted_error('check aborted'));\n };\n const finish = (): void => {\n clearTimeout(grace);\n abort?.removeEventListener('abort', on_abort);\n };\n proc.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n proc.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString();\n });\n proc.on('error', (err) => {\n finish();\n reject(check_error(`check command failed to start: ${err.message}`));\n });\n proc.on('exit', () => {\n kill_group(proc);\n grace = setTimeout(() => {\n proc.stdout.destroy();\n proc.stderr.destroy();\n }, OUTPUT_GRACE_MS);\n });\n proc.on('close', (code) => {\n finish();\n resolve_promise({ exit_code: code, stdout, stderr });\n });\n abort?.addEventListener('abort', on_abort, { once: true });\n });\n}\n\nexport type ParsedSummary = {\n summary: CheckrideSummary;\n warning: string | null;\n};\n\n/** Best-effort parse of the summary contract. `pnpm exec` talks over the\n * command's stdout (pnpm 11's dep-verify prints an \"Already up to date\"\n * install line ahead of the JSON), so the object is extracted between the\n * first `{` and the last `}` rather than parsed from byte 0. An unexpected\n * schema_version warns and still parses; no JSON object at all is a harness\n * error (exit 4). */\nexport function parse_checkride_summary(stdout: string): ParsedSummary {\n const start = stdout.indexOf('{');\n const end = stdout.lastIndexOf('}');\n let raw: unknown;\n try {\n if (start === -1 || end < start) throw new Error('no JSON object in stdout');\n raw = JSON.parse(stdout.slice(start, end + 1));\n } catch {\n throw check_error('checkride --json produced unparseable stdout');\n }\n if (typeof raw !== 'object' || raw === null || !Array.isArray((raw as CheckrideSummary).checks)) {\n throw check_error('checkride summary missing checks array');\n }\n const summary = raw as CheckrideSummary;\n const warning =\n summary.schema_version === CHECKRIDE_SCHEMA_VERSION\n ? null\n : `checkride summary schema_version ${String(summary.schema_version)} != ${String(CHECKRIDE_SCHEMA_VERSION)}; parsing best-effort`;\n return { summary, warning };\n}\n\n/** Parse the summary from stdout, falling back to the on-disk contract:\n * `.check/summary.json` is what checkride documents; stdout is its mirror and\n * wrappers may talk over it beyond what the tolerant slice can recover. */\nexport function parse_summary_with_fallback(stdout: string, workspace: string): ParsedSummary {\n try {\n return parse_checkride_summary(stdout);\n } catch (err) {\n const file = join(workspace, '.check', 'summary.json');\n if (!existsSync(file)) throw err;\n return parse_checkride_summary(readFileSync(file, 'utf8'));\n }\n}\n\nexport function failing_checks(summary: CheckrideSummary): CheckrideSummaryCheck[] {\n return summary.checks.filter((c) => !c.ok && c.skipped !== true);\n}\n\n/** Whether `path` sits under `dir`. */\nfunction within(dir: string, path: string): boolean {\n const from_dir = relative(dir, path);\n return from_dir !== '..' && !from_dir.startsWith(`..${sep}`) && !isAbsolute(from_dir);\n}\n\n/** Per failing slot: the raw artifact (`<output_file>` when present, else\n * `<slot>.stdout.txt`) in `check_dir`, a workspace's `.check/` or an archived\n * iteration's copy of it, truncated with a pointer to the file. The names come\n * from a summary the builder could have written, so a path that leaves\n * `check_dir` has no artifact, rather than putting a file from elsewhere in\n * front of a model. */\nexport function read_failing_artifacts(\n check_dir: string,\n failing: CheckrideSummaryCheck[],\n): CheckArtifact[] {\n return failing.map((check) => {\n const file = check.output_file ?? `${check.name}.stdout.txt`;\n const path = join(check_dir, file);\n if (!within(check_dir, path) || !existsSync(path) || !statSync(path).isFile()) {\n return { slot: check.name, path: null, content: '(no artifact found)', truncated: false };\n }\n const raw = readFileSync(path, 'utf8');\n const truncated = raw.length > CHECK_ARTIFACT_MAX_CHARS;\n return {\n slot: check.name,\n path,\n content: truncated ? raw.slice(0, CHECK_ARTIFACT_MAX_CHARS) : raw,\n truncated,\n };\n });\n}\n\n/** checkride's digest of a red run (`.check/digest.md`, written under\n * `--digest` and removed on a green one), or undefined when there is none. It\n * is capped by checkride itself, at 8 kB. */\nfunction read_digest(workspace: string): string | undefined {\n const path = join(workspace, '.check', 'digest.md');\n return existsSync(path) ? readFileSync(path, 'utf8') : undefined;\n}\n\nexport type CheckrideOpts = CheckSpawnOptions & {\n workspace: string;\n};\n\nexport async function run_checkride(opts: CheckrideOpts): Promise<CheckResult> {\n const { workspace, ...spawn_options } = opts;\n const proc = await spawn_capture('pnpm', ['exec', 'checkride', '--json', '--digest'], {\n ...spawn_options,\n cwd: workspace,\n });\n // checkride exit 2 is a harness/usage error — an operator problem, not\n // something to iterate on.\n if (proc.exit_code === 2) {\n throw check_error(`checkride harness error: ${proc.stderr.trim()}`);\n }\n const { summary } = parse_summary_with_fallback(proc.stdout, opts.workspace);\n const failing = failing_checks(summary);\n // Only a red run writes a digest; on a green one checkride removes any\n // stale one, and volley doesn't look.\n const digest = summary.ok ? undefined : read_digest(opts.workspace);\n return {\n ran: true,\n runner: 'checkride',\n ok: summary.ok,\n exit_code: proc.exit_code,\n duration_ms: summary.total_duration_ms,\n failing_slots: failing.map((c) => c.name),\n detail: read_failing_artifacts(join(opts.workspace, '.check'), failing),\n summary,\n ...(digest !== undefined ? { digest } : {}),\n };\n}\n","/**\n * Generic command runner: `sh -c <command>`, combined\n * output captured, exit-0 semantics. Command-not-found is an operator error\n * (exit 4), not an iterable failure.\n */\nimport { check_error } from '../types.js';\nimport type { CheckResult, CheckRunnerKind } from '../types.js';\nimport { spawn_capture } from './checkride.js';\nimport type { CheckSpawnOptions } from './checkride.js';\n\nexport type CommandCheckOpts = CheckSpawnOptions & {\n command: string;\n workspace: string;\n};\n\nexport async function run_command_check(opts: CommandCheckOpts): Promise<CheckResult> {\n const { command, workspace, ...spawn_options } = opts;\n const started = Date.now();\n const proc = await spawn_capture('sh', ['-c', command], { ...spawn_options, cwd: workspace });\n // sh reports 127 for command-not-found and 126 for not-executable.\n if (proc.exit_code === 127 || proc.exit_code === 126) {\n throw check_error(\n `check command failed to start (exit ${String(proc.exit_code)}): ${command}`,\n );\n }\n const log = `${proc.stdout}${proc.stderr}`;\n return {\n ran: true,\n runner: 'command',\n ok: proc.exit_code === 0,\n exit_code: proc.exit_code,\n duration_ms: Date.now() - started,\n failing_slots: [],\n detail: [],\n log,\n };\n}\n\nexport function skipped_check(reason: 'none' | 'cost_cap'): CheckResult {\n return {\n ran: false,\n runner: 'none',\n // With no check configured the loop is critic-gated only, so the gate is\n // open (`ok: true`). A cost-cap skip must not look like a passing gate.\n ok: reason === 'none',\n exit_code: null,\n duration_ms: 0,\n failing_slots: [],\n detail: [],\n };\n}\n\n/** What a rejected check says in place of its output. */\nexport const CHECK_REJECTED = 'the check was rejected when it asked to run, so it never ran';\n\n/** A check the user rejected when it asked to run: recorded as a failed\n * check, with the refusal as its output, so a round can't converge on work\n * nothing checked, and the critic hears why there's no result. */\nexport function rejected_check(runner: CheckRunnerKind): CheckResult {\n return {\n ran: true,\n runner,\n ok: false,\n exit_code: null,\n duration_ms: 0,\n failing_slots: [],\n detail: [],\n log: CHECK_REJECTED,\n };\n}\n","/**\n * What a `claude_cli` seat may touch. The CLI runs in the build root (its\n * session cwd), and two layers keep its file tools there:\n *\n * - The allowlist names only path rules the CLI matches. It checks file\n * permissions against `Edit(path)` and `Read(path)` alone (an `Edit` rule\n * governs the Write tool too; a `Write(path)` or `MultiEdit(path)` rule is\n * accepted and never matched), and a bare `Write` or `Read` approves every\n * path on the machine. `/` anchors a rule at the session's working\n * directory. Reads, searches, and globs inside the working directory need no\n * rule at all, so `Grep` and `Glob` aren't listed: a bare entry for either\n * would only reach outside it.\n * - `--settings` turns on the CLI's own blocks, which refuse file tools outside\n * the working directories in every permission mode, `bypassPermissions`\n * included, where allow rules decide nothing. The write block needs Claude\n * Code 2.1.314, the read block 2.1.257; an older CLI ignores the key, which\n * the dry run warns about.\n *\n * `Bash` stays unconfined: the blocks cover file tools only.\n */\nimport type { ResolvedConfig } from './types.js';\n\n/** Whether a seat this run drives runs on the Claude CLI. A critique has no\n * builder, whatever its provider resolved to. */\nexport function uses_claude_cli(config: ResolvedConfig): boolean {\n return (\n (config.mode !== 'critique' && config.builder_provider === 'claude_cli') ||\n config.critic_provider === 'claude_cli'\n );\n}\n\nexport const BUILDER_ALLOWED_TOOLS = ['Read(/**)', 'Edit(/**)', 'Bash', 'WebFetch'] as const;\n\nexport const CRITIC_ALLOWED_TOOLS = ['Read(/**)'] as const;\n\nexport const CRITIC_DISALLOWED_TOOLS = 'Write,Edit,MultiEdit,NotebookEdit,Bash';\n\nconst PERMISSION_BLOCKS = {\n permissions: {\n blockWritesOutsideWorkingDirectories: true,\n blockReadsOutsideWorkingDirectories: true,\n },\n} as const;\n\n/** The CLI flags that turn on `PERMISSION_BLOCKS`. */\nexport function settings_args(): string[] {\n return ['--settings', JSON.stringify(PERMISSION_BLOCKS)];\n}\n\nexport type ClaudeVersion = readonly [number, number, number];\n\nexport const MIN_CLAUDE_WRITE_BLOCK: ClaudeVersion = [2, 1, 314];\n\nexport const MIN_CLAUDE_READ_BLOCK: ClaudeVersion = [2, 1, 257];\n\n/** The version `claude --version` printed (`2.1.316 (Claude Code)`), or null\n * when it printed something else. */\nexport function parse_claude_version(stdout: string): ClaudeVersion | null {\n const match = /^\\s*(\\d+)\\.(\\d+)\\.(\\d+)\\b/.exec(stdout);\n if (match === null) return null;\n return [Number(match[1]), Number(match[2]), Number(match[3])];\n}\n\nexport function version_below(version: ClaudeVersion, min: ClaudeVersion): boolean {\n const [major, minor, patch] = version;\n const [min_major, min_minor, min_patch] = min;\n if (major !== min_major) return major < min_major;\n if (minor !== min_minor) return minor < min_minor;\n return patch < min_patch;\n}\n\nexport function format_version(version: ClaudeVersion): string {\n return version.join('.');\n}\n","/**\n * Cost and usage accumulation. All pricing knowledge lives in\n * fascicle; volley only folds `GenerateResult.usage` / `.cost` into loop\n * state and enforces the cap predicate in the guard.\n */\nimport { claude_cli_reported, throughput } from 'fascicle';\nimport type { GenerateResult, StepRecord, ToolCallRecord, UsageTotals } from 'fascicle';\nimport type {\n BuilderStepRecord,\n CostSource,\n LoopState,\n PhaseRecord,\n ResolvedConfig,\n StepTimingBasis,\n} from './types.js';\n\nexport const EMPTY_USAGE: UsageTotals = { input_tokens: 0, output_tokens: 0 };\n\nexport function add_usage(a: UsageTotals, b: UsageTotals): UsageTotals {\n const sum: UsageTotals = {\n input_tokens: a.input_tokens + b.input_tokens,\n output_tokens: a.output_tokens + b.output_tokens,\n };\n const optional = ['cached_input_tokens', 'cache_write_tokens', 'reasoning_tokens'] as const;\n for (const key of optional) {\n const total = (a[key] ?? 0) + (b[key] ?? 0);\n if (a[key] !== undefined || b[key] !== undefined) sum[key] = total;\n }\n return sum;\n}\n\n/** The providers whose calls carry the charge they report, which fascicle\n * records as the call's cost in place of a pricing table's estimate: the\n * Claude CLI's own total, and OpenRouter's per-response charge. */\nconst REPORTING_PROVIDERS: ReadonlySet<string> = new Set(['claude_cli', 'openrouter']);\n\nexport function cost_source_of(result: GenerateResult<unknown>): CostSource {\n if (result.cost === undefined) return 'unknown';\n return REPORTING_PROVIDERS.has(result.model_resolved.provider)\n ? 'provider_reported'\n : 'engine_derived';\n}\n\n/** One phase's record from its generate result. The duration is fascicle's\n * call-level wall clock (`GenerateResult.timing`: every turn and the tools\n * between them) unless the caller measured a wider span, as the critic does for\n * its whole degradation ladder. */\nexport function phase_record(\n result: GenerateResult<unknown>,\n model: string,\n duration_ms: number = result.timing?.duration_ms ?? 0,\n): PhaseRecord {\n const rate = throughput(result);\n const truncated = result.steps.filter((step) => step.truncated === true).length;\n return {\n provider: result.model_resolved.provider,\n model,\n session_id: claude_cli_reported(result)?.session_id ?? null,\n duration_ms,\n usage: result.usage,\n cost_usd: result.cost?.total_usd ?? null,\n cost_source: cost_source_of(result),\n finish_reason: result.finish_reason,\n tool_calls: result.tool_calls.length,\n salvaged_tool_calls: result.tool_calls.filter((call) => call.salvaged === true).length,\n ...(truncated > 0 ? { truncated_turns: truncated } : {}),\n ...(rate !== undefined ? { throughput: rate } : {}),\n };\n}\n\ntype StepSplit = { prefill_ms?: number; decode_ms?: number; timing_basis: StepTimingBasis };\n\nconst NS_PER_MS = 1e6;\n\nfunction ns_field(payload: Record<string, unknown>, name: string): number | undefined {\n const value = payload[name];\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;\n}\n\n/** A turn's prefill and decode times: Ollama's own durations when it reported\n * them (in ns), else the time to the first streamed chunk, else none. */\nfunction step_split(step: StepRecord): StepSplit {\n const reported = step.provider_reported?.['ollama'];\n if (typeof reported === 'object' && reported !== null) {\n const ollama = reported as Record<string, unknown>;\n const evaluated = ns_field(ollama, 'eval_duration');\n const prompt = ns_field(ollama, 'prompt_eval_duration');\n if (evaluated !== undefined && prompt !== undefined) {\n return {\n prefill_ms: Math.round(prompt / NS_PER_MS),\n decode_ms: Math.round(evaluated / NS_PER_MS),\n timing_basis: 'ollama_reported',\n };\n }\n const total = ns_field(ollama, 'total_duration');\n const load = ns_field(ollama, 'load_duration');\n if (evaluated !== undefined && total !== undefined && load !== undefined && total >= load + evaluated) {\n return {\n prefill_ms: Math.round((total - load - evaluated) / NS_PER_MS),\n decode_ms: Math.round(evaluated / NS_PER_MS),\n timing_basis: 'ollama_derived',\n };\n }\n }\n const timing = step.timing;\n if (timing?.first_chunk_ms !== undefined && timing.whole_tool_call !== true) {\n return {\n prefill_ms: timing.first_chunk_ms,\n decode_ms: Math.max(0, timing.duration_ms - timing.first_chunk_ms),\n timing_basis: 'first_chunk',\n };\n }\n return { timing_basis: 'none' };\n}\n\n/** How much a tool call's result put into the transcript: its output as the\n * loop serializes it, or the error text it fed back. */\nfunction output_chars(call: ToolCallRecord): number {\n if (call.output === undefined) return call.error?.message.length ?? 0;\n return typeof call.output === 'string' ? call.output.length : (JSON.stringify(call.output) ?? '').length;\n}\n\n/** Each turn of a session as the archive records it, or undefined when the\n * result has none. */\nexport function step_records(result: GenerateResult<unknown>): BuilderStepRecord[] | undefined {\n if (result.steps.length === 0) return undefined;\n return result.steps.map((step) => ({\n index: step.index,\n input_tokens: step.usage.input_tokens,\n output_tokens: step.usage.output_tokens,\n duration_ms: step.timing?.duration_ms ?? 0,\n ...step_split(step),\n finish_reason: step.finish_reason,\n ...(step.truncated === true ? { truncated: true as const } : {}),\n tool_calls: step.tool_calls.map((call) => ({ name: call.name, output_chars: output_chars(call) })),\n }));\n}\n\n/** Fold one phase's result into the loop state. Unknown cost records `null`\n * for the phase and warns once per run — a run never fails over pricing. The\n * builder's record also carries its session's turns. */\nexport function accumulate(\n state: LoopState,\n role: 'builder' | 'critic',\n result: GenerateResult<unknown>,\n model: string,\n duration_ms?: number,\n): LoopState {\n const record = phase_record(result, model, duration_ms);\n const steps = role === 'builder' ? step_records(result) : undefined;\n const cost = record.cost_usd ?? 0;\n return {\n ...state,\n [role]: steps !== undefined ? { ...record, steps } : record,\n total_usage: add_usage(state.total_usage, result.usage),\n total_cost_usd: state.total_cost_usd + cost,\n iteration_cost_usd: state.iteration_cost_usd + cost,\n builder_cost_usd: state.builder_cost_usd + (role === 'builder' ? cost : 0),\n critic_cost_usd: state.critic_cost_usd + (role === 'critic' ? cost : 0),\n cost_warned: state.cost_warned || record.cost_usd === null,\n };\n}\n\nexport function cost_cap_hit(config: ResolvedConfig, state: LoopState): boolean {\n return config.max_cost_usd !== null && state.total_cost_usd >= config.max_cost_usd;\n}\n","/**\n * Best-effort Ollama model pre-load. A cold multi-GB model can spend minutes\n * in load + first prompt eval — longer than the provider path's in-request\n * header timeout — so the first real `generate` dies with an opaque\n * `stream interrupted: fetch failed`. Ollama's documented load call (a\n * `/api/generate` POST with a model and no prompt) returns as soon as the\n * model is resident, so absorbing the load here keeps the real call's\n * time-to-first-byte inside its budget.\n *\n * Best-effort like the context probe: any failure (server down, unknown\n * model, timeout) is swallowed — the real generate call surfaces the error\n * with retry and reporting behind it. Ollama-only; LM Studio has no\n * equivalent load-without-generating endpoint.\n */\n\n/** Generous ceiling on the load itself: a disk-cold 30B-class model takes\n * tens of seconds to minutes. Past this, give up and let the real call try. */\nconst PREWARM_TIMEOUT_MS = 300_000;\n\n/** Load `model` into the Ollama server's memory (`base_url` is the server\n * root). Resolves when the model is resident, on any failure, or at the\n * timeout — never throws, never gates the phase. An already-resident model\n * returns immediately, so warming the same model for both roles is free.\n *\n * Load-bearing only on the ai_sdk transport: the cold-load death this\n * absorbs is the ai-sdk/undici in-request header timeout, not an Ollama\n * limit. On fascicle's native transport — the deferred future bridge, see\n * `seat_provider_config` in engine.ts — the per-turn call is a bare\n * `fetch(..., { signal })` with no default body timeout, so a cold model can\n * take as long as it needs and this pre-warm's necessity drops away (keep it\n * regardless: a resident model makes it a no-op). Native would also move the\n * `num_ctx`/`keep_alive` levers to per-call `provider_options.ollama`, rather\n * than the server-side Modelfile defaults volley probes today. */\nexport async function prewarm_ollama_model(\n base_url: string,\n model: string,\n abort?: AbortSignal,\n): Promise<void> {\n const signals = [AbortSignal.timeout(PREWARM_TIMEOUT_MS)];\n if (abort !== undefined) signals.push(abort);\n try {\n await fetch(`${base_url.replace(/\\/$/, '')}/api/generate`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ model }),\n signal: AbortSignal.any(signals),\n });\n } catch {\n // Best-effort: the real generate call owns error surfacing.\n }\n}\n","/**\n * Whether volley is running inside its sandbox container. A leaf, so the\n * config resolution, the preflight, and the run-config signing can all ask\n * without importing one another.\n */\n\n/** volley *detects* it is running inside its sandbox container rather than\n * starting the container itself. The signal is the `VOLLEY_CONTAINED=1` marker\n * volley's own image bakes in (`Dockerfile` `ENV`), so a `docker run <hardened\n * flags> <image> volley run …` is recognized as contained out of the box. Kept\n * env-only — no ambient `/.dockerenv` probe — so the safety gate is deterministic\n * and testable, and so a CI job that itself runs in an unrelated container does\n * not silently satisfy the gate; a hand-rolled sandbox must set the marker (or\n * the operator uses `--allow-unsandboxed-builder`). */\nexport function detect_containment(env: Readonly<Record<string, string | undefined>>): boolean {\n const value = env['VOLLEY_CONTAINED'];\n return value === '1' || value === 'true';\n}\n","/**\n * Which run configs a host-side resume may trust. A resume runs what a run's\n * `config.json` says: its check, a shell command, and its seats, permission\n * mode and prompt included. Inside the sandbox the builder runs arbitrary\n * commands with write access to its own run's state, so a contained run's\n * config is the builder's to rewrite, and resuming it on the host would run\n * whatever the builder left there.\n *\n * So volley on the host signs each config it writes, an HMAC under a key of\n * this machine's that never enters the container, and a host-side resume\n * trusts only a config whose signature holds. Inside the sandbox nothing is\n * signed, since the key isn't there and one made there would be in the\n * builder's reach, so a contained run's config never carries a signature the\n * host accepts, and the builder can't forge one without the key.\n */\nimport { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { detect_containment } from './containment.js';\n\ntype Env = Readonly<Record<string, string | undefined>>;\n\n/** Prefixed to what is signed, so a signature over a run config can't pass for\n * one over anything else under the same key. */\nconst DOMAIN = 'volley run config v1\\n';\n\n/** Where this machine's key lives: `$XDG_CONFIG_HOME/volley/run-key`, else\n * `~/.config/volley/run-key`, outside every state root, so a container a run\n * root is mounted into still can't read it. A relative `XDG_CONFIG_HOME` is\n * ignored, as the XDG spec says. */\nexport function trust_key_path(env: Env, home: string = homedir()): string {\n const xdg = env['XDG_CONFIG_HOME'];\n const base = xdg !== undefined && isAbsolute(xdg) ? xdg : join(home, '.config');\n return join(base, 'volley', 'run-key');\n}\n\nfunction error_code(err: unknown): unknown {\n return (err as { code?: unknown }).code;\n}\n\n/** The key as stored, or null when there is none or it isn't one. */\nfunction read_key(path: string): Buffer | null {\n try {\n const hex = readFileSync(path, 'utf8').trim();\n return /^[0-9a-f]{64}$/.test(hex) ? Buffer.from(hex, 'hex') : null;\n } catch {\n return null;\n }\n}\n\n/** The key, created on first use: 32 random bytes in a file only its user can\n * read, in a directory only its user can enter. Two runs that start together\n * race to create it; the loser reads the winner's. */\nfunction machine_key(env: Env): Buffer | null {\n const path = trust_key_path(env);\n const existing = read_key(path);\n if (existing !== null) return existing;\n try {\n mkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n writeFileSync(path, `${randomBytes(32).toString('hex')}\\n`, { flag: 'wx', mode: 0o600 });\n } catch (err) {\n if (error_code(err) !== 'EEXIST') return null;\n }\n return read_key(path);\n}\n\nfunction hmac(key: Buffer, config_text: string): string {\n return createHmac('sha256', key).update(DOMAIN).update(config_text).digest('hex');\n}\n\n/** This machine's signature over a run's `config.json` text, or null where\n * there's none to give: inside the sandbox, or when the key can't be read or\n * created. */\nexport function sign_config(config_text: string, env: Env = process.env): string | null {\n if (detect_containment(env)) return null;\n const key = machine_key(env);\n return key === null ? null : hmac(key, config_text);\n}\n\n/** Does `signature` hold for `config_text` under this machine's key? Never\n * creates the key: with none there's nothing it could hold under. */\nexport function config_signed(\n config_text: string,\n signature: string | null,\n env: Env = process.env,\n): boolean {\n if (signature === null) return false;\n const key = read_key(trust_key_path(env));\n if (key === null) return false;\n const expected = Buffer.from(hmac(key, config_text), 'hex');\n const given = Buffer.from(signature.trim(), 'hex');\n return given.length === expected.length && timingSafeEqual(given, expected);\n}\n","/**\n * Workspace lifecycle: run-state initialization, stale-run\n * backup rotation, path helpers, and optional git checkpoints.\n */\nimport { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { isAbsolute, join, relative, resolve, sep } from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { sign_config } from './trust.js';\nimport { check_error, config_error } from './types.js';\nimport type { ResolvedConfig } from './types.js';\n\n/** A run id names the run's `volley/<run id>` branch and its state directory,\n * so it is held to what both take without quoting: letters, digits, `-`, and\n * `_`, starting with a letter or digit, so it never reads as an option and\n * never climbs out of the directory it names. */\nexport const RUN_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;\n\n/** The root each run's state sits under when `--state-dir` names none:\n * `$XDG_STATE_HOME/volley`, else `<home>/.local/state/volley`. A relative\n * `XDG_STATE_HOME` is ignored, as the XDG spec says. `home` is the host's by\n * default; the sandbox passes its container's to spell the same root inside. */\nexport function default_state_root(\n env: Readonly<Record<string, string | undefined>>,\n home: string = homedir(),\n): string {\n const xdg = env['XDG_STATE_HOME'];\n const base = xdg !== undefined && isAbsolute(xdg) ? xdg : join(home, '.local', 'state');\n return join(base, 'volley');\n}\n\n/** What locates a run's state, as a structural subset of `ResolvedConfig` so a\n * resume can find a run before it has a whole config. */\nexport type StateLocation = Pick<ResolvedConfig, 'workspace' | 'state_dir' | 'run_id'>;\n\n/** Where a run keeps its config, summary, trajectory, feedback, verdict, and\n * iterations: `<state_dir>/<run_id>/` under its state root, or, in the layout\n * older runs used (`state_dir` null), `<workspace>/.volley/`. */\nexport function run_state_dir(run: StateLocation): string {\n return run.state_dir === null ? join(run.workspace, '.volley') : join(run.state_dir, run.run_id);\n}\n\nexport function state_path(run: StateLocation, ...parts: string[]): string {\n return join(run_state_dir(run), ...parts);\n}\n\nexport function iteration_dir(run: StateLocation, iteration: number): string {\n return state_path(run, 'iterations', String(iteration).padStart(3, '0'));\n}\n\n/** A state root that sits inside `root` (the build root), as the path from\n * there in git's `/`-separated vocabulary, or null when it sits outside. A\n * root inside the tree would otherwise pass for the builder's work: listed in\n * the changes the critic reads, and committed by every `--git` checkpoint.\n * The legacy `.volley/` (`state_dir` null) is excluded by name already. */\nexport function state_root_within(root: string, state_dir: string | null): string | null {\n if (state_dir === null) return null;\n const path = relative(resolve(root), resolve(state_dir));\n if (path === '' || path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path)) return null;\n return path.split(sep).join('/');\n}\n\n/** Filesystem-safe timestamp for `.bak.<stamp>` rotation names. Shared by the\n * run-state rotation here and the worktree rotation so both preserve\n * prior state under the same never-destroy naming. */\nexport function backup_stamp(date: Date = new Date()): string {\n return date.toISOString().replace(/[:.]/g, '-');\n}\n\n/** Fresh-run initialization: rotate a stale state directory aside (a prior\n * `.volley/` becomes `.volley.bak.<stamp>`), then create the directory tree.\n * Under a state root each run has a directory of its own, so only a reused\n * `--run-id` ever finds one to rotate. An empty one is used as it is: that is\n * what a contained run is handed when its run directory is the mount, which\n * can't be renamed. Resume runs skip rotation (`preserve: true`). */\nexport function initialize_run_state(\n run: StateLocation,\n options: { preserve?: boolean } = {},\n): void {\n const dir = run_state_dir(run);\n if (existsSync(dir) && options.preserve !== true && readdirSync(dir).length > 0) {\n renameSync(dir, `${dir}.bak.${backup_stamp()}`);\n }\n if (run.state_dir !== null && !existsSync(run.state_dir)) {\n // Trajectories hold prompts and tool output, so a root volley creates is\n // its user's alone, as the XDG spec asks of a state directory.\n mkdirSync(run.state_dir, { recursive: true, mode: 0o700 });\n }\n mkdirSync(join(dir, 'iterations'), { recursive: true });\n}\n\n/** Beside a run's `config.json`: this machine's signature over it\n * (`./trust.ts`), which a host-side resume checks before it trusts the\n * config. */\nexport const CONFIG_SIGNATURE = 'config.sig';\n\n/** Record the run's config, signed when volley runs on the host. Returns\n * whether it was signed: inside the sandbox it never is, and on the host only\n * when the machine's key can't be read or created. A signature a reused run\n * directory held from before is removed rather than left to vouch for this\n * config. */\nexport function write_resolved_config(\n config: ResolvedConfig,\n env: Readonly<Record<string, string | undefined>> = process.env,\n): boolean {\n const record = {\n version: config.version,\n run_id: config.run_id,\n started_at: config.started_at,\n mode: config.mode,\n prompt: config.prompt,\n criteria: config.criteria,\n check: config.check,\n check_resolved: config.check_resolved,\n builder_model: config.builder_model,\n builder_provider: config.builder_provider,\n builder_url: config.builder_url,\n builder_max_steps: config.builder_max_steps,\n builder_max_tool_calls: config.builder_max_tool_calls,\n builder_max_output_tokens: config.builder_max_output_tokens,\n builder_trim_history: config.builder_trim_history,\n critic_model: config.critic_model,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n builder_permission_mode: config.builder_permission_mode,\n critic_preset: config.critic_preset,\n critic_prompt_path: config.critic_prompt_path,\n max_iterations: config.max_iterations,\n max_cost_usd: config.max_cost_usd,\n git_checkpoints: config.git_checkpoints,\n worktree: config.worktree,\n discard_worktree: config.discard_worktree,\n gate_paths: config.gate_paths,\n fail_on_gate_edit: config.fail_on_gate_edit,\n sandbox_image: config.sandbox_image,\n state_dir: config.state_dir,\n workspace: config.workspace,\n };\n const text = `${JSON.stringify(record, null, 2)}\\n`;\n writeFileSync(state_path(config, 'config.json'), text);\n const signature = sign_config(text, env);\n if (signature === null) {\n rmSync(state_path(config, CONFIG_SIGNATURE), { force: true });\n return false;\n }\n writeFileSync(state_path(config, CONFIG_SIGNATURE), `${signature}\\n`);\n return true;\n}\n\n/** The identity volley's own commits fall back to. git won't commit without a\n * name and an email, and the sandbox image carries no git config, so inside\n * it a checkpoint or a worktree's salvage commit failed outright; a machine\n * never set up for git can be the same. `.invalid` is reserved, so the email\n * can't reach anyone. */\nconst FALLBACK_IDENTITY: ReadonlyArray<readonly [string, string]> = [\n ['user.name', 'volley'],\n ['user.email', 'volley@volley.invalid'],\n];\n\n/** The `-c` flags that give a commit in `cwd` the fallback identity for each\n * part git has no value for. One the repo or the user configured wins, and so\n * does a `GIT_AUTHOR_*` or `GIT_COMMITTER_*` variable, which git ranks above\n * any config. Put them ahead of the subcommand. */\nexport function commit_identity(cwd: string): string[] {\n return FALLBACK_IDENTITY.flatMap(([key, value]) => {\n const set = spawnSync('git', ['config', '--get', key], {\n cwd,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n return set.status === 0 && set.stdout.trim() !== '' ? [] : ['-c', `${key}=${value}`];\n });\n}\n\n/**\n * `--git`: commit everything under `root` after a phase (`git -C <root>`, run\n * here via the spawn `cwd`). `root` is the build root (`build_root`): the\n * workspace on the default path, or the per-run worktree under `--worktree`, so\n * checkpoints land on the worktree branch rather than the workspace's.\n * A checkpoint with nothing to commit is fine; a missing git binary or repo is\n * not. `excluded_dir` (from `state_root_within`) keeps a state root inside the\n * tree out of the commit; `:/` keeps the rest of the staging repo-wide, as a\n * bare `git add -A` is, and `literal` reads the path as written, wildcards and\n * all.\n */\nexport function git_checkpoint(root: string, message: string, excluded_dir: string | null = null): void {\n if (!existsSync(join(root, '.git'))) {\n // `.git` is a directory in the workspace and a file in a linked worktree;\n // existsSync accepts both.\n throw config_error(`git checkpoints require a git repository: ${root}`);\n }\n const pathspec = excluded_dir === null ? [] : ['--', ':/', `:(exclude,literal)${excluded_dir}`];\n const add = spawnSync('git', ['add', '-A', ...pathspec], { cwd: root, env: command_env(process.env) });\n if (add.error !== undefined || add.status !== 0) {\n throw check_error(`git add failed: ${add.stderr?.toString() ?? String(add.error)}`);\n }\n const commit = spawnSync('git', [...commit_identity(root), 'commit', '-m', message, '--no-verify'], {\n cwd: root,\n env: command_env(process.env),\n });\n // Exit 1 with \"nothing to commit\" is a no-op iteration, not a failure. So is\n // \"nothing added to commit\", which git says instead when the only untracked\n // files left are the state root `excluded_dir` kept out.\n if (commit.error !== undefined) {\n throw check_error(`git commit failed to start: ${String(commit.error)}`);\n }\n const out = `${commit.stdout?.toString() ?? ''}${commit.stderr?.toString() ?? ''}`;\n if (commit.status !== 0 && !/nothing (?:added )?to commit/.test(out)) {\n throw check_error(`git commit failed: ${out.trim()}`);\n }\n}\n\n/**\n * Integration — bring a successful `--worktree --git` run's effects onto the\n * workspace branch. The per-phase checkpoints on `branch` are the raw\n * audit/replay trail; here they collapse into a single squash commit\n * (`git merge --squash` then `commit`) on the workspace's current branch. The\n * shared object store makes this a local, fetch-free merge, and — because the\n * workspace branch never moved during the run (checkpoints went to the phase\n * branch) — it is conflict-free by construction. A run whose phase branch has no\n * new commits integrates to a no-op. Only successful runs integrate; an\n * abandoned run's branch is discarded wholesale by the teardown trio instead.\n */\nexport function integrate_worktree(workspace: string, branch: string, message: string): void {\n if (!existsSync(join(workspace, '.git'))) {\n throw config_error(`--worktree integration requires a git repository: ${workspace}`);\n }\n const squash = spawnSync('git', ['merge', '--squash', branch], {\n cwd: workspace,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (squash.error !== undefined) {\n throw check_error(`git merge --squash failed to start: ${String(squash.error)}`);\n }\n if (squash.status !== 0) {\n throw check_error(\n `git merge --squash ${branch} failed: ${(squash.stderr || squash.stdout).trim()}`,\n );\n }\n const commit = spawnSync('git', [...commit_identity(workspace), 'commit', '-m', message, '--no-verify'], {\n cwd: workspace,\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (commit.error !== undefined) {\n throw check_error(`git commit failed to start: ${String(commit.error)}`);\n }\n // An empty phase branch stages nothing; \"nothing to commit\" is a no-op.\n const out = `${commit.stdout ?? ''}${commit.stderr ?? ''}`;\n if (commit.status !== 0 && !out.includes('nothing to commit')) {\n throw check_error(`git commit failed: ${out.trim()}`);\n }\n}\n","/**\n * Git-worktree orchestration: isolate a builder run's\n * *effects* on a per-run branch checked out into a sibling worktree, then tear\n * the whole thing down when the run ends. The worktree lifecycle wraps the\n * fascicle loop — it is not itself a loop — so these are straight-line git\n * subprocess calls and the flow's no-loops rule is unaffected.\n *\n * Teardown is not one behaviour but three, decided by `worktree_fate` and\n * predicted out loud by `report_worktree_fate` before any model spend: a\n * converged `--worktree --git` run *integrates* (the orchestrator squash-merges,\n * then the branch is discarded), a `--discard-worktree` run *discards*, and a\n * plain `--worktree` run *salvages* — its work was never integrated and lives\n * nowhere else, so teardown commits it onto the run branch and keeps the branch\n * instead of force-deleting the build. Everything that did not converge still\n * discards wholesale.\n */\nimport { existsSync, renameSync, rmSync, symlinkSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { check_error, config_error } from './types.js';\nimport { backup_stamp, commit_identity } from './workspace.js';\n\n/** A live worktree: the checked-out path and the branch it holds. */\nexport type WorktreeHandle = {\n path: string;\n branch: string;\n};\n\n/** The sibling directory a run's worktree is checked out into — one per\n * workspace, alongside it so it never nests inside the repo's own tree. */\nexport function worktree_path(workspace: string): string {\n return `${resolve(workspace)}.worktree`;\n}\n\n/** The per-run branch name (one named branch per phase). Derived from the\n * run id so it is stable across a resume. */\nexport function worktree_branch(run_id: string): string {\n return `volley/${run_id}`;\n}\n\n/**\n * The directory the builder's *effects* land in: the run's worktree\n * when `--worktree` is on, else the workspace itself. This is the containment\n * root the builder/critic file tools resolve through `contain()` and the\n * `bash` tool's cwd — re-pointing it moves writes into the worktree without\n * disturbing the workspace. The check, the change report, and the checkpoints\n * follow it there; the run's state stays wherever `state_dir` puts it.\n */\nexport function build_root(workspace: string, worktree: boolean): string {\n return worktree ? worktree_path(workspace) : workspace;\n}\n\n/** What becomes of a *successful* `--worktree` run's effects. Any other\n * outcome — cost cap, budget, interrupt, error — always discards: an abandoned\n * phase's branch is thrown away wholesale, as it always has been. */\nexport type WorktreeFate = 'none' | 'integrate' | 'salvage' | 'discard';\n\n/** The config fields the fate turns on, as a structural subset of\n * `ResolvedConfig` so the decision is testable without a whole config. */\nexport type WorktreeFateConfig = {\n worktree: boolean;\n git_checkpoints: boolean;\n discard_worktree: boolean;\n};\n\n/**\n * Which of the three outcomes a converged run gets:\n *\n * - `integrate` — `--worktree --git`: the phase branch's checkpoints squash-merge\n * onto the workspace branch (`integrate_worktree`), then teardown discards it.\n * - `discard` — `--discard-worktree`: the effects go away with the branch. What\n * `volley matrix` sweeps with: isolate the effects, keep only verdicts.\n * - `salvage` — `--worktree` alone: nothing integrates, and the worktree holds the\n * run's only copy of its work, so teardown commits that onto the run branch and\n * keeps it rather than force-deleting a green run's build.\n *\n * `--git` wins over `--discard-worktree`, so the documented `--worktree --git`\n * integrate path is untouched by asking for a throw-away run.\n */\nexport function worktree_fate(config: WorktreeFateConfig): WorktreeFate {\n if (!config.worktree) return 'none';\n if (config.git_checkpoints) return 'integrate';\n if (config.discard_worktree) return 'discard';\n return 'salvage';\n}\n\n/** The run branch as a *prediction* can name it: `--dry-run` resolves its own\n * run id, which is not the id the real run will get, so the notice names the\n * pattern and the post-run report names the branch. */\nconst RUN_BRANCH_PATTERN = 'volley/<run id>';\n\nexport type WorktreeNotice = { level: 'info' | 'warn'; message: string };\n\n/**\n * What this run will do with its effects, in one line, said before any model\n * spend — the same predict-at-dry-run/warn-at-run-start shape as the local-critic\n * seat canary and the `num_ctx` guard. `salvage` is a warning, not an\n * info line: `--worktree` without `--git` integrates nothing, and it is the one\n * fate an operator is likely to have configured by accident.\n */\nexport function worktree_notice(config: WorktreeFateConfig): WorktreeNotice | null {\n const fate = worktree_fate(config);\n if (fate === 'none') return null;\n if (fate === 'integrate') {\n return {\n level: 'info',\n message:\n 'worktree: --worktree --git — a successful run squash-merges its run branch onto the ' +\n 'workspace branch at teardown; any other outcome is discarded.',\n };\n }\n if (fate === 'discard') {\n return {\n level: 'info',\n message:\n 'worktree: --discard-worktree — the run builds in an isolated worktree whose effects are ' +\n 'thrown away at teardown, converged or not. Verdicts only; no branch is kept.',\n };\n }\n return {\n level: 'warn',\n message:\n 'worktree: --worktree without --git — a successful run will NOT be integrated into the ' +\n 'workspace branch, and the builder writes only inside the sibling worktree, so your working ' +\n `tree stays as it is. The run's work is committed onto its own branch (${RUN_BRANCH_PATTERN}) ` +\n 'at teardown and left there for `git switch` / `git cherry-pick`. Add --git to squash-merge ' +\n 'it onto the workspace branch instead, or --discard-worktree to throw it away deliberately.',\n };\n}\n\n/** The renderer channels a notice writes through — structurally satisfied by\n * `Renderer`, so this module stays independent of the render layer. */\nexport type NoticeSink = {\n info: (message: string) => void;\n warn: (message: string) => void;\n};\n\n/** Emit the run's worktree fate on the channel its severity deserves (nothing at\n * all when `--worktree` is off). Called from the `--dry-run` preflight and again\n * at run start, so the outcome is predicted whether or not the operator dry-ran. */\nexport function report_worktree_fate(config: WorktreeFateConfig, sink: NoticeSink): void {\n const notice = worktree_notice(config);\n if (notice === null) return;\n if (notice.level === 'warn') {\n sink.warn(notice.message);\n return;\n }\n sink.info(notice.message);\n}\n\ntype GitResult = { status: number; stdout: string; stderr: string };\n\n/** Run git in `cwd`. A missing git binary is a precondition failure (like the\n * missing-repo guard); a non-zero exit is left to the caller to interpret. */\nfunction git(cwd: string, args: string[]): GitResult {\n const result = spawnSync('git', args, { cwd, env: command_env(process.env), encoding: 'utf8' });\n if (result.error !== undefined) {\n throw config_error(`git is required for --worktree but could not run: ${String(result.error)}`);\n }\n return { status: result.status ?? -1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };\n}\n\n/** Run git and throw on a non-zero exit, surfacing git's own diagnostics. */\nfunction git_ok(cwd: string, args: string[]): GitResult {\n const result = git(cwd, args);\n if (result.status !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim();\n throw check_error(`git ${args.join(' ')} failed: ${detail}`);\n }\n return result;\n}\n\n/** Best-effort git for teardown: swallows both spawn and exit failures so the\n * idempotent trio never throws out of a run's `finally`. Still reports what it\n * can — a spawn failure reads as a non-zero exit with no output — so the salvage\n * path can interrogate the repo without reintroducing a throw. */\nfunction git_quiet(cwd: string, args: string[]): GitResult {\n try {\n const result = spawnSync('git', args, { cwd, env: command_env(process.env), encoding: 'utf8' });\n return { status: result.status ?? -1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };\n } catch {\n // Teardown is cleanup; never mask the run's real outcome.\n return { status: -1, stdout: '', stderr: '' };\n }\n}\n\nfunction branch_exists(repo: string, branch: string): boolean {\n return git(repo, ['show-ref', '--verify', '--quiet', `refs/heads/${branch}`]).status === 0;\n}\n\n/**\n * Check `branch` out into a fresh worktree at `worktree_path(workspace)`.\n *\n * Rotate-on-conflict: a leftover worktree directory or branch from a\n * crashed run is renamed aside under a `.bak.<stamp>` name — never destroyed —\n * before the fresh one is created, mirroring `.volley.bak.<stamp>`.\n */\nexport function create_worktree(options: {\n workspace: string;\n branch: string;\n base?: string;\n log?: (message: string) => void;\n}): WorktreeHandle {\n const repo = resolve(options.workspace);\n if (!existsSync(join(repo, '.git'))) {\n throw config_error(`--worktree requires the workspace to be a git repository: ${repo}`);\n }\n const path = worktree_path(repo);\n const base = options.base ?? 'HEAD';\n const log = options.log ?? (() => {});\n\n // Preserve a leftover directory (possibly dirty), then drop its now-dangling\n // registration so `worktree add` sees a clean slate.\n if (existsSync(path)) {\n const backup = `${path}.bak.${backup_stamp()}`;\n renameSync(path, backup);\n git(repo, ['worktree', 'prune']);\n log(`worktree: rotated existing ${path} aside to ${backup}`);\n }\n // Preserve a leftover branch's commits rather than clobbering with `-B`.\n if (branch_exists(repo, options.branch)) {\n const backup_branch = `${options.branch}.bak.${backup_stamp()}`;\n git_ok(repo, ['branch', '-m', options.branch, backup_branch]);\n log(`worktree: rotated existing branch ${options.branch} aside to ${backup_branch}`);\n }\n\n git_ok(repo, ['worktree', 'add', '-b', options.branch, path, base]);\n\n // The toolchain rides along: `node_modules` is untracked, so a fresh\n // checkout has none — link the workspace's install in so the deterministic\n // check (which runs at the build root) and the builder's `bash` can\n // run the project toolchain without a per-run re-install.\n const modules = join(repo, 'node_modules');\n if (existsSync(modules) && !existsSync(join(path, 'node_modules'))) {\n symlinkSync(modules, join(path, 'node_modules'), 'dir');\n log(`worktree: linked node_modules from ${repo}`);\n }\n\n return { path, branch: options.branch };\n}\n\n/** What a teardown left behind. Both fields are null on the discarding path —\n * branch and checkout are gone, which is the point. */\nexport type TeardownOutcome = {\n /** The run branch teardown kept, holding work that was never integrated, for a\n * `git switch` / `git cherry-pick`. Null when the branch was deleted (nothing\n * was salvaged, or the run committed nothing worth keeping). */\n salvaged_branch: string | null;\n /** The checkout teardown refused to delete because its work could not be\n * committed (a stale index lock, a broken repo): the files are\n * still on disk, and the next run rotates them aside rather than destroying\n * them. Null whenever the checkout was removed. */\n kept_path: string | null;\n};\n\n/**\n * Tear the worktree down with the idempotent trio: remove the worktree,\n * delete its branch, prune the registration. Each step tolerates the target\n * already being gone, so a second teardown — or teardown of a worktree that\n * was never created — is a safe no-op.\n *\n * `salvage` flips the trio from *discard* to *keep* for the one case that has no\n * other copy of its work: a converged run whose effects were never integrated\n * (`--worktree` without `--git` — there are no checkpoint commits and no squash\n * merge, so `branch -D` plus a `--force` removal would eat the build). Teardown\n * then commits the checkout's state onto the run branch, skips the `branch -D`,\n * and removes only the checkout. Failed and integrated runs keep discarding:\n * nothing is left to save.\n */\nexport function teardown_worktree(options: {\n workspace: string;\n branch: string;\n salvage?: boolean;\n}): TeardownOutcome {\n const repo = resolve(options.workspace);\n const path = worktree_path(repo);\n const outcome: TeardownOutcome =\n options.salvage === true\n ? salvage_worktree(repo, path, options.branch)\n : { salvaged_branch: null, kept_path: null };\n // Salvage that could not commit: the work exists only in this directory, so\n // leave the whole worktree standing rather than removing what holds it.\n if (outcome.kept_path !== null) return outcome;\n\n git_quiet(repo, ['worktree', 'remove', '--force', path]);\n if (outcome.salvaged_branch === null) {\n git_quiet(repo, ['branch', '-D', options.branch]);\n }\n git_quiet(repo, ['worktree', 'prune']);\n // If git left the directory behind (already detached from the repo), clear it.\n if (existsSync(path)) {\n try {\n rmSync(path, { recursive: true, force: true });\n } catch {\n // Best effort; a lingering directory does not fail the run.\n }\n }\n return outcome;\n}\n\n/**\n * Commit whatever the run left in the worktree onto the run's own branch, so an\n * unintegrated success survives its teardown. Reports the branch when it ends up\n * carrying commits the workspace branch does not — a run that changed nothing\n * leaves no branch behind — or the checkout path when the commit did not land,\n * which is teardown's signal to keep its hands off the directory.\n */\nfunction salvage_worktree(repo: string, path: string, branch: string): TeardownOutcome {\n if (existsSync(path)) {\n git_quiet(path, ['add', '-A']);\n git_quiet(path, [\n ...commit_identity(path),\n 'commit',\n '-m',\n `volley: salvage unintegrated worktree (${branch})`,\n '--no-verify',\n ]);\n if (worktree_dirty(path)) return { salvaged_branch: null, kept_path: path };\n }\n return { salvaged_branch: branch_ahead(repo, branch) ? branch : null, kept_path: null };\n}\n\n/** Uncommitted or untracked changes still in the checkout — i.e. the salvage\n * commit did not land. A git call that fails outright reads as clean: teardown's\n * existing guards already cope with a checkout git cannot speak for. */\nfunction worktree_dirty(path: string): boolean {\n const status = git_quiet(path, ['status', '--porcelain']);\n return status.status === 0 && status.stdout.trim().length > 0;\n}\n\n/** Does `branch` carry commits the workspace's HEAD does not? The run branch is\n * cut from HEAD, so this asks \"did the run commit anything?\" — and answers false\n * for a branch that does not exist, which keeps teardown idempotent. */\nfunction branch_ahead(repo: string, branch: string): boolean {\n const ahead = git_quiet(repo, ['rev-list', '--count', `HEAD..${branch}`]);\n return ahead.status === 0 && Number(ahead.stdout.trim()) > 0;\n}\n\nexport type WorktreeOptions<T> = {\n enabled: boolean;\n workspace: string;\n branch: string;\n log?: (message: string) => void;\n /** Consulted with the body's value on a clean exit: `true` means this run's\n * work was never integrated, so teardown must salvage it onto the run branch\n * instead of discarding it. Never consulted when the body throws — a\n * failed run's branch is thrown away wholesale. */\n salvage?: (value: T) => boolean;\n};\n\n/** The body's value plus what teardown left behind. */\nexport type WorktreeOutcome<T> = TeardownOutcome & { value: T };\n\n/**\n * Run `body` with the run's worktree lifecycle around it: when enabled, create\n * the worktree first and guarantee teardown on every exit path; when disabled,\n * this is a transparent pass-through so the default path is byte-for-byte\n * unchanged.\n *\n * The discarding teardown stays in the `finally` — it is what a throw, an abort,\n * or a non-salvaging exit gets. A *salvaging* teardown has to run inside the\n * `try` instead, because its outcome (the surviving branch) is part of this\n * call's return value; `discard_on_exit` hands the responsibility over so the\n * two never both fire and `branch -D` the branch salvage just kept.\n */\nexport async function with_worktree<T>(\n options: WorktreeOptions<T>,\n body: () => Promise<T>,\n): Promise<WorktreeOutcome<T>> {\n if (!options.enabled) {\n return { value: await body(), salvaged_branch: null, kept_path: null };\n }\n create_worktree({\n workspace: options.workspace,\n branch: options.branch,\n ...(options.log !== undefined ? { log: options.log } : {}),\n });\n let discard_on_exit = true;\n try {\n const value = await body();\n if (options.salvage?.(value) !== true) {\n return { value, salvaged_branch: null, kept_path: null };\n }\n discard_on_exit = false;\n return {\n value,\n ...teardown_worktree({\n workspace: options.workspace,\n branch: options.branch,\n salvage: true,\n }),\n };\n } finally {\n if (discard_on_exit) {\n teardown_worktree({ workspace: options.workspace, branch: options.branch });\n }\n }\n}\n","/**\n * Builder invocation: one call to the builder leaf per iteration is one\n * complete agentic session in the workspace — Claude Code under `claude_cli`,\n * or a model driving volley's tools on any other provider, local or hosted.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { basename, dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { model_call } from 'fascicle';\nimport type {\n Engine,\n GenerateOptions,\n GenerateResult,\n ModelCallInput,\n PrepareStepHook,\n RunContext,\n Step,\n StreamChunk,\n Tool,\n ToolApprovalHandler,\n} from 'fascicle';\nimport { warn_small_local_context } from './builder/context_check.js';\nimport { step_countdown } from './builder/countdown.js';\nimport { compose_prepare_steps } from './builder/prepare_step.js';\nimport { step_trim } from './builder/trim.js';\nimport { builder_tools, type BashExecutor } from './builder/tools.js';\nimport { CHECK_REJECTED } from './check/command.js';\nimport { BUILDER_ALLOWED_TOOLS, settings_args } from './claude_cli_permissions.js';\nimport { accumulate } from './cost.js';\nimport { seat_base_url } from './engine.js';\nimport { prewarm_ollama_model } from './prewarm.js';\nimport { config_error, phase_error } from './types.js';\nimport type { CheckResult, LoopState, ResolvedConfig } from './types.js';\nimport type { ToolSet } from './workspace_tools.js';\nimport { build_root } from './worktree.js';\n\nexport function compose_builder_system(): string {\n return [\n 'You are the builder inside the volley harness: an autonomous agent',\n 'iterating on a workspace until it satisfies a task and its acceptance',\n 'criteria. Work directly in the current working directory. Plan',\n 'internally, make the changes, and verify your own work before finishing.',\n ].join('\\n');\n}\n\n/** Walk up from this module to the package root (works from src/ under tsx\n * and from dist/ in the published package, which ships src/builder/presets). */\nexport function builder_presets_dir(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const candidate = join(dir, 'src', 'builder', 'presets');\n if (existsSync(candidate)) return candidate;\n dir = dirname(dir);\n }\n throw config_error('builder presets directory not found');\n}\n\n/** The harness append each tool set's builder reads: one naming volley's own\n * tools, or one naming fascicle's workspace tools under `volley acp` and\n * saying what a call the user refused means. */\nconst HARNESS_APPENDS: Record<ToolSet, string> = {\n volley: 'harness_append_local.md',\n acp: 'harness_append_acp.md',\n};\n\n/** Step 2 of \"Work this way\", as both harness appends word it for a builder\n * held to one tool call a turn. */\nconst ONE_CALL_A_TURN = '2. Call one tool at a time and read its result before deciding the next\\n call.';\n\n/** Step 2 for a builder that may make several calls a turn: fascicle runs a\n * turn's calls in order, so a read can't race an edit, but each change or\n * command is still worth reading before the next. Reads don't count toward\n * the cap, so the step names no number. */\nconst BATCHED_CALLS = [\n '2. Batch independent reads into one turn, but make one change or command per',\n ' turn, and read its result before deciding the next call.',\n].join('\\n');\n\n// The CLI system prompt assumes CLI semantics (built-in tools, implicit\n// cwd), so the local builder gets its own — its tool set, the\n// workspace-is-cwd convention, and the harness-enforced `finish` stop.\nexport function compose_builder_system_local(\n tool_set: ToolSet = 'volley',\n max_tool_calls = 1,\n): string {\n const identity = [\n 'You are the builder inside the volley harness: an autonomous agent',\n 'iterating on a workspace until it satisfies a task and its acceptance',\n 'criteria.',\n ].join('\\n');\n const append = readFileSync(join(builder_presets_dir(), HARNESS_APPENDS[tool_set]), 'utf8');\n const worded =\n max_tool_calls > 1 ? append.replace(ONE_CALL_A_TURN, BATCHED_CALLS) : append;\n return `${identity}\\n\\n${worded.trimEnd()}`;\n}\n\n/** The builder system prompt for the active provider: the `claude_cli`\n * prompt (implicit built-in tools, \"the current working directory\") for the\n * CLI builder, which never takes an injected set, or the local prompt naming\n * the seat's tool set for every provider that runs volley's tool loop,\n * `openrouter` included. Mirrors the critic's `resolve_critic_prompt`. */\nfunction resolve_builder_system(config: ResolvedConfig, tool_set?: ToolSet): string {\n return config.builder_provider === 'claude_cli'\n ? compose_builder_system()\n : compose_builder_system_local(tool_set, config.builder_max_tool_calls);\n}\n\n// Salvage budget for a tool call a local model emits as assistant text instead\n// of a structured tool_call (Hermes / json-fenced / Qwen3-Coder XML). Must be\n// > 0 to turn salvage on; the budget is shared across the whole\n// generate call and each salvage is observable on the result for the\n// salvage-rate health metric.\nconst BUILDER_TOOL_CALL_REPAIR_ATTEMPTS = 3;\n\n/** How the step countdown tells the builder to run the check: the command\n * volley gates on, with the digest and without `--json`, the configured\n * command, or the project's own tests when no check gates the run. A\n * workspace can hold checkride with no `check` script, so not `pnpm check`. */\nfunction check_hint(config: ResolvedConfig): string {\n if (config.check_resolved === 'checkride') return 'the check (`pnpm exec checkride --digest`)';\n if (config.check_resolved === 'command') return `the check (\\`${config.check}\\`)`;\n return \"the project's tests\";\n}\n\n/** The builder's `prepare_step`: the countdown, after the history trim when\n * `--builder-trim-history` turns it on, so the countdown's note still goes\n * last. */\nfunction builder_prepare_step(config: ResolvedConfig): PrepareStepHook {\n const countdown = step_countdown(config.builder_max_steps, check_hint(config));\n if (config.builder_trim_history === null) return countdown;\n return compose_prepare_steps([step_trim(config.builder_trim_history), countdown]);\n}\n\n/** Per-provider tool wiring for the builder, mirroring `critic_tool_options`.\n * The `claude_cli` builder is confined at the CLI permission layer (allowlist +\n * permission mode) and brings its own built-in tools — this arm is unchanged\n * from v2, and takes no injected tools or approval handler. Every other\n * builder, local or `openrouter`, brings none, so volley supplies its whole\n * workspace tool surface (or the set the caller injected in its place, with\n * the handler that answers its approvals), the per-call loop knobs, the step\n * countdown (`./builder/countdown.ts`) and the history trim when it's on\n * (`./builder/trim.ts`), the output cap when one is set, and\n * **no** schema (it produces a workspace, not a verdict); per-call values win\n * over engine defaults. */\nfunction builder_tool_options(\n deps: BuilderDeps,\n): Pick<\n GenerateOptions,\n | 'tools'\n | 'on_tool_approval'\n | 'provider_options'\n | 'max_steps'\n | 'tool_error_policy'\n | 'tool_call_repair_attempts'\n | 'max_tool_calls_per_step'\n | 'prepare_step'\n | 'max_tokens'\n | 'truncated_turn_policy'\n> {\n const { config } = deps;\n const bash_executor = deps.bash_executor ?? null;\n if (config.builder_provider === 'claude_cli') {\n // The file tools stay in the build root, the session's cwd: the allowlist\n // scopes them under `acceptEdits`, and the settings blocks hold under\n // `bypassPermissions` too, where allow rules decide nothing.\n return {\n provider_options: {\n claude_cli: {\n allowed_tools: [...BUILDER_ALLOWED_TOOLS],\n extra_args: ['--permission-mode', config.builder_permission_mode, ...settings_args()],\n },\n },\n };\n }\n return {\n // Containment root re-points to the worktree under `--worktree`, so\n // the model's writes, edits, and `bash` cwd land there and leave the\n // workspace untouched. When the sandbox is active its `docker exec` executor\n // runs `bash` in the container against the bind-mounted worktree; the\n // host `spawnSync` default stands in otherwise.\n tools:\n deps.tools === undefined\n ? builder_tools(\n build_root(config.workspace, config.worktree),\n bash_executor !== null ? { bash_executor } : {},\n )\n : [...deps.tools],\n ...(deps.on_tool_approval !== undefined ? { on_tool_approval: deps.on_tool_approval } : {}),\n max_steps: config.builder_max_steps,\n tool_error_policy: 'feed_back',\n tool_call_repair_attempts: BUILDER_TOOL_CALL_REPAIR_ATTEMPTS,\n max_tool_calls_per_step: config.builder_max_tool_calls,\n prepare_step: builder_prepare_step(config),\n // A capped turn that runs out before it calls a tool goes on to the next\n // step instead of ending the session; with no cap, a turn cut off at the\n // provider's own limit still ends it, as one cut off at a full context\n // window would only be cut off again.\n ...(config.builder_max_output_tokens !== null\n ? { max_tokens: config.builder_max_output_tokens, truncated_turn_policy: 'continue' as const }\n : {}),\n };\n}\n\n/** What the builder is told about the iteration before its own, besides the\n * critic's feedback. */\nexport type PreviousRound = {\n /** That iteration's check. Its output goes in the prompt when it failed. */\n check: CheckResult | null;\n /** The step limit that iteration's builder hit before it called finish, or\n * null when it stopped on its own. */\n step_limit_hit: number | null;\n};\n\nexport type BuilderPromptInput = {\n task: string;\n criteria: string;\n feedback: string | null;\n iteration: number;\n checkride: boolean;\n previous: PreviousRound | null;\n};\n\n/** How much of the last check's output the builder's prompt carries: a few KB,\n * whatever the runner. checkride's digest already fits in 8 kB, and the builder\n * can run the check again for the rest. */\nexport const PREVIOUS_CHECK_MAX_CHARS = 6000;\n\n/** The first `max` characters of `text`, saying where it was cut. */\nfunction head(text: string, max: number, rest: string): string {\n return text.length <= max ? text : `${text.slice(0, max)}\\n… (cut at ${String(max)} characters; ${rest})`;\n}\n\n/** The last `max` characters of `text`, saying what came before was cut. */\nfunction tail(text: string, max: number): string {\n return text.length <= max\n ? text\n : `… (the last ${String(max)} characters of ${String(text.length)})\\n${text.slice(-max)}`;\n}\n\n/** The part of a failed check the builder reads first: checkride's digest,\n * else the start of each failing slot's raw output, else the end of a\n * command's output, where test runners and compilers sum up. */\nfunction check_excerpt(check: CheckResult): string {\n const max = PREVIOUS_CHECK_MAX_CHARS;\n if (check.digest !== undefined) {\n return head(check.digest.trimEnd(), max, '.check/digest.md has the rest');\n }\n if (check.detail.length > 0) {\n const slots = check.detail.map((artifact) => {\n const source = artifact.path === null ? '' : ` (.check/${basename(artifact.path)})`;\n return `${artifact.slot}${source}:\\n${artifact.content.trimEnd()}`;\n });\n return head(slots.join('\\n\\n'), max, 'each slot\\'s raw output under .check/ has the rest');\n }\n return tail((check.log ?? '').trimEnd(), max);\n}\n\n/** The check section of a later iteration's prompt: what the deterministic\n * gate itself said about the last session's work, so the builder starts from\n * its words rather than the critic's account of them, or re-running it to\n * find out. Empty unless that check ran and failed. A check the user rejected\n * when it asked to run is recorded as failed but said nothing, and the\n * section says so rather than call the work failed. */\nfunction previous_check_section(check: CheckResult | null): string[] {\n if (check === null || !check.ran || check.ok) return [];\n const heading = ['', 'PREVIOUS CHECK RESULT', '---------------------'];\n if (check.log === CHECK_REJECTED) {\n return [\n ...heading,\n 'The check never ran on the work your last session left: it was rejected when it',\n 'asked to run, so nothing has verified that work yet.',\n ];\n }\n const runner = check.runner === 'checkride' ? 'checkride, ' : '';\n const exit = check.exit_code === null ? 'no exit code' : `exit ${String(check.exit_code)}`;\n const lines = [\n ...heading,\n `The check failed on the work your last session left (${runner}${exit}).`,\n ];\n if (check.failing_slots.length > 0) {\n lines.push(`Failing slots: ${check.failing_slots.join(', ')}.`);\n }\n const excerpt = check_excerpt(check);\n if (excerpt.length > 0) lines.push('', excerpt);\n return lines;\n}\n\n/** The line a later iteration's prompt carries when the last session ran out\n * of steps: it never got to verify, so this one should check first. */\nfunction step_limit_lines(step_limit_hit: number | null): string[] {\n if (step_limit_hit === null) return [];\n return [\n '',\n `Your last session hit its ${String(step_limit_hit)}-step limit before it called finish, so`,\n 'it may never have verified its work. Run the check first this time, and keep',\n 'enough steps in hand to verify again before you finish.',\n ];\n}\n\nexport function compose_builder_prompt(input: BuilderPromptInput): string {\n const parts = [\n 'TASK',\n '----',\n input.task,\n '',\n 'ACCEPTANCE CRITERIA',\n '-------------------',\n input.criteria,\n '',\n `ITERATION: ${input.iteration}`,\n ];\n if (input.iteration > 1 && input.feedback !== null) {\n parts.push(\n '',\n 'PREVIOUS CRITIC FEEDBACK',\n '------------------------',\n input.feedback,\n '',\n 'Address the feedback above. The workspace already contains your prior work;',\n 'read the current state, then make the necessary changes.',\n );\n }\n if (input.iteration > 1 && input.previous !== null) {\n parts.push(\n ...previous_check_section(input.previous.check),\n ...step_limit_lines(input.previous.step_limit_hit),\n );\n }\n if (input.checkride) {\n parts.push(\n '',\n 'The definition of done for this workspace includes checkride exiting 0. Run',\n '`pnpm exec checkride --digest`, the check volley gates on, after each batch of',\n 'edits and again before you finish. When it fails, read .check/digest.md',\n 'first: it lists each failing slot\\'s first findings. Open a slot\\'s raw',\n 'output under .check/ only if the digest isn\\'t enough, then fix and re-run.',\n );\n }\n return parts.join('\\n');\n}\n\n// A `max_steps` cutoff is not an error. The local builder burned its whole\n// step budget without calling `finish`, so its partial workspace goes to check\n// + critic exactly like a `finish`-terminated iteration (the critic sees\n// incomplete work and requests changes, the loop continues). The renderer\n// surfaces this as a warning and `finish_reason: 'max_steps'` is recorded in\n// the iteration summary — non-convergence is data, not an exception.\nfunction builder_max_steps_warning(max_steps: number): string {\n return (\n `builder hit the ${String(max_steps)}-step limit without calling finish; ` +\n 'handing the partial workspace to check + critic (raise --builder-max-steps if this recurs)'\n );\n}\n\nexport type BuilderDeps = {\n engine: Engine;\n config: ResolvedConfig;\n on_chunk: (chunk: StreamChunk) => void;\n /** The `bash` executor for a sandboxed local builder (`docker exec` against\n * the run's container), or null to use the host `spawnSync` default (the\n * unsandboxed escape hatch, or `claude_cli` which supplies no volley tools). */\n bash_executor?: BashExecutor | null;\n /** Tools to hand the builder in place of volley's own set; absent, it gets\n * that set. A `claude_cli` builder brings its own tools and never takes\n * these. */\n tools?: ReadonlyArray<Tool>;\n /** Which set `tools` is, so the prompt names the tools the builder holds;\n * absent, volley's own. */\n tool_set?: ToolSet;\n /** Answers each call to a tool that asks first (`needs_approval`). Like\n * `tools`, it reaches every builder but `claude_cli`. Absent, such a call\n * fails closed. */\n on_tool_approval?: ToolApprovalHandler;\n};\n\n/** The builder's model boundary: one call is one complete agentic session in\n * the build root, and its output is the whole `GenerateResult`, because the\n * phase records usage, cost, timing, and tool calls from it. */\nexport type BuilderStep = Step<ModelCallInput, GenerateResult>;\n\n/** Build the builder leaf for this run. Everything but the prompt is fixed for\n * the whole run, so it is wired once here: the provider's system prompt, its\n * tool surface, and the live chunk stream to the renderer. */\nexport function make_builder_step(deps: BuilderDeps): BuilderStep {\n const { config } = deps;\n return model_call({\n engine: deps.engine,\n id: 'builder',\n description: 'model call: one agentic session in the build root',\n provider: config.builder_provider,\n model: config.builder_model,\n system: resolve_builder_system(config, deps.tool_set),\n on_chunk: deps.on_chunk,\n ...builder_tool_options(deps),\n });\n}\n\nexport type BuilderRunDeps = {\n builder: BuilderStep;\n config: ResolvedConfig;\n warn: (message: string) => void;\n};\n\n/** Run one builder session on the opened iteration `state`, told what the\n * iteration before it left behind (`previous`, null on the first). */\nexport async function run_builder(\n deps: BuilderRunDeps,\n state: LoopState,\n previous: PreviousRound | null,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config } = deps;\n try {\n // Warn at builder start where a too-small context window is detectable —\n // it silently truncates tool schemas (the #1 local tool-calling failure) —\n // then pre-load the model so a cold multi-GB load doesn't blow the real\n // call's first-byte timeout. Both best-effort and Ollama-only; neither\n // blocks the build. Both go to the builder seat's own server.\n if (config.builder_provider === 'ollama') {\n const base_url = seat_base_url('ollama', config.builder_url, process.env);\n await warn_small_local_context(\n config.builder_provider,\n config.builder_model,\n base_url,\n deps.warn,\n ctx.abort,\n );\n await prewarm_ollama_model(base_url, config.builder_model, ctx.abort);\n }\n const result = await ctx.call(\n deps.builder,\n compose_builder_prompt({\n task: config.prompt,\n criteria: config.criteria,\n feedback: state.feedback,\n iteration: state.iteration,\n checkride: config.check_resolved === 'checkride',\n previous,\n }),\n );\n const built = accumulate(state, 'builder', result, config.builder_model);\n // `max_steps` is a backstop, not a failure — surface it, count it, and\n // carry on.\n if (result.finish_reason !== 'max_steps') return built;\n deps.warn(builder_max_steps_warning(config.builder_max_steps));\n return { ...built, builder_max_steps_hits: built.builder_max_steps_hits + 1 };\n } catch (err) {\n throw phase_error('builder', state.iteration, err);\n }\n}\n","/**\n * What the builder changed, and whether it touched the gate.\n *\n * Until now the harness's only view of a builder's work was \"the check exited\n * 0\" — which is exactly the thing a builder can arrange by editing the check.\n * The reckon run (`research/reckon-local-run-finding.md`) closed that hole by\n * hand: after a green all-local run, the salvage commit was inspected to confirm\n * it touched only the four source modules and no test, fixture, or manifest.\n * This module is that inspection, mechanized — diff the build root against a\n * baseline captured before the first iteration, classify every changed path\n * against the gate patterns, and hand the result to the critic prompt, the run\n * summary, and (opt-in) the loop's stopping condition.\n *\n * Everything here is best-effort and non-throwing. A build root that is not a\n * git repository simply has no change set (`null`) and the loop behaves exactly\n * as it did before: change detection is evidence, never a precondition.\n *\n * Deliberately *not* collected: diff hunks. The changed-path list is bounded and\n * cheap, while inlined content would blow a local critic's context (32k on the\n * reckon seats) for the one part of the picture its read tools can already\n * fetch — the critic learns *where* to look, then looks.\n */\nimport { spawnSync } from 'node:child_process';\nimport { command_env } from './engine.js';\nimport { config_error } from './types.js';\nimport type { ChangeSet, ChangeStatus, ChangedFile } from './types.js';\n\n/**\n * The default gate: paths whose edits change *what passing means* rather than\n * whether the work passes. Tests and fixtures are the executable half of the\n * spec; the check configuration and manifest decide which tests run at all.\n *\n * Deliberately broad and language-general — a false positive costs one line in\n * the critic's prompt, while a miss is the failure mode this exists to prevent.\n * A config's own `gate_paths` replaces the list outright (spec-writing tasks\n * legitimately own their tests).\n */\nexport const DEFAULT_GATE_PATTERNS: string[] = [\n '**/*.test.*',\n '**/*.spec.*',\n '**/*_test.*',\n '**/test/**',\n '**/tests/**',\n '**/__tests__/**',\n '**/spec/**',\n '**/fixtures/**',\n '**/checkride.config.*',\n '**/vitest.config.*',\n '**/jest.config.*',\n '**/playwright.config.*',\n '**/package.json',\n '.github/workflows/**',\n];\n\n/** Harness state, toolchain, and VCS internals: never the builder's work, even\n * when they sit in the build root and show up dirty. `.volley/` is the control\n * plane, `.check/` is the check's own artifacts, `node_modules/` rides in on the\n * worktree symlink. */\nconst EXCLUDED_PREFIXES = ['.volley/', '.volley.bak.', '.check/', '.git/', 'node_modules/'];\n\n/** How many changed paths the set carries. The cap bounds the critic prompt and\n * the archived summary on a sweeping refactor; `gate_edits` and `total` are\n * always computed over the full list, so nothing load-bearing is truncated. */\nconst DEFAULT_LIMIT = 200;\n\ntype GitResult = { status: number; stdout: string };\n\n/** Run git in `root`, best-effort: a missing binary, a broken repo, or a\n * non-zero exit all read as \"no output\". Change detection reports what it can\n * and never fails a run over what it cannot (unlike `worktree.ts`, where git is\n * a precondition the operator asked for). */\nfunction git(root: string, args: string[]): GitResult {\n try {\n const result = spawnSync('git', args, {\n cwd: root,\n env: command_env(process.env),\n encoding: 'utf8',\n maxBuffer: 32 * 1024 * 1024,\n });\n return { status: result.status ?? -1, stdout: result.stdout ?? '' };\n } catch {\n return { status: -1, stdout: '' };\n }\n}\n\n/** Is this directory inside a git repository? Asked of git rather than by\n * looking for `.git`, so a workspace nested under a repo root — and a linked\n * worktree, whose `.git` is a file — both answer correctly. */\nfunction in_git_repo(root: string): boolean {\n return git(root, ['rev-parse', '--git-dir']).status === 0;\n}\n\n/**\n * The commit a run's changes are measured against: the build root's HEAD, read\n * once before the first iteration. Null when the root is not a repository or has\n * no commits yet — in the latter case `collect_changes` still reports untracked\n * files, which is the whole of a from-scratch build.\n */\nexport function capture_baseline(root: string): string | null {\n const head = git(root, ['rev-parse', 'HEAD']);\n if (head.status !== 0) return null;\n const sha = head.stdout.trim();\n return sha.length > 0 ? sha : null;\n}\n\n/**\n * The commit a critique's change is measured from: `rev` (`--baseline`)\n * resolved in `root`, so the change is everything that differs from it,\n * committed or not, untracked files included. With no revision named it's\n * HEAD, so the uncommitted and untracked edits are the change, and, as for a\n * run, null where there's no repository or no commit yet. A named revision\n * that isn't a commit there, or one named where there's no repository, is a\n * config error.\n */\nexport function resolve_baseline(root: string, rev: string | undefined): string | null {\n if (rev === undefined) return capture_baseline(root);\n if (!in_git_repo(root)) {\n throw config_error(`--baseline needs the workspace to be a git repository: ${root}`);\n }\n // `--end-of-options` keeps a revision that starts with `-` from reading as a flag.\n const resolved = git(root, ['rev-parse', '--verify', '--quiet', '--end-of-options', `${rev}^{commit}`]);\n const sha = resolved.stdout.trim();\n if (resolved.status !== 0 || sha.length === 0) {\n throw config_error(`--baseline names no commit in ${root}: ${rev}`);\n }\n return sha;\n}\n\n/** git's status letters, folded onto the four cases worth naming. Rename and\n * copy both record the destination path — where the content lives now. */\nfunction change_status(code: string): ChangeStatus {\n const letter = code.charAt(0);\n if (letter === 'A') return 'added';\n if (letter === 'M' || letter === 'T') return 'modified';\n if (letter === 'D') return 'deleted';\n if (letter === 'R' || letter === 'C') return 'renamed';\n return 'unknown';\n}\n\ntype RawChange = { path: string; status: ChangeStatus };\n\n/**\n * Parse `git diff --name-status -z`: a flat NUL-separated stream of\n * `status, path` pairs, except renames and copies, which carry `status, source,\n * destination`. NUL separation (rather than lines) is what makes paths with\n * spaces or newlines in them safe to read.\n */\nfunction parse_name_status(stdout: string): RawChange[] {\n const tokens = stdout.split('\\0').filter((token) => token.length > 0);\n const changes: RawChange[] = [];\n let index = 0;\n while (index < tokens.length) {\n const code = tokens[index] ?? '';\n const paired = code.startsWith('R') || code.startsWith('C');\n const path = tokens[index + (paired ? 2 : 1)];\n if (path !== undefined) changes.push({ path, status: change_status(code) });\n index += paired ? 3 : 2;\n }\n return changes;\n}\n\n/** Parse a NUL-separated path list (`git ls-files -z`). */\nfunction parse_paths(stdout: string): string[] {\n return stdout.split('\\0').filter((path) => path.length > 0);\n}\n\nfunction excluded(path: string, excluded_dir: string | null): boolean {\n if (excluded_dir !== null && path.startsWith(`${excluded_dir}/`)) return true;\n return EXCLUDED_PREFIXES.some((prefix) => path.startsWith(prefix));\n}\n\n/**\n * Compile one glob to an anchored regular expression. Supports the three forms\n * the gate patterns need — `**` across separators, `*` within a segment, `?` for\n * one character — in a single pass, because sequential string replacement would\n * re-process the regex syntax its own earlier passes emit.\n *\n * A leading globstar-plus-separator collapses to \"any number of leading\n * segments, including none\", so one `test` pattern matches `test/a.mjs` and\n * `src/test/a.mjs` alike instead of needing a rule per depth.\n */\nfunction glob_to_regexp(pattern: string): RegExp {\n let source = '';\n let index = 0;\n while (index < pattern.length) {\n const char = pattern.charAt(index);\n if (char === '*' && pattern.charAt(index + 1) === '*') {\n const slashed = pattern.charAt(index + 2) === '/';\n source += slashed ? '(?:.*/)?' : '.*';\n index += slashed ? 3 : 2;\n continue;\n }\n if (char === '*') {\n source += '[^/]*';\n index += 1;\n continue;\n }\n if (char === '?') {\n source += '[^/]';\n index += 1;\n continue;\n }\n source += /[.+^${}()|[\\]\\\\]/.test(char) ? `\\\\${char}` : char;\n index += 1;\n }\n return new RegExp(`^${source}$`);\n}\n\n/** Does this path match any of these glob patterns? Exported for the gate-path\n * unit tests, which pin the matcher's semantics independently of git. */\nexport function matches_any(path: string, patterns: string[]): boolean {\n return patterns.some((pattern) => glob_to_regexp(pattern).test(path));\n}\n\nexport type CollectChangesOptions = {\n /** Where the builder's effects land — the worktree under `--worktree`, else\n * the workspace (`build_root`). */\n root: string;\n /** The run's baseline commit, from `capture_baseline`. */\n baseline: string | null;\n gate_patterns: string[];\n /** A state root inside `root`, relative to it (`state_root_within`): the\n * harness's files, never the builder's. */\n excluded_dir?: string | null;\n limit?: number;\n};\n\nfunction by_path(left: ChangedFile, right: ChangedFile): number {\n if (left.path < right.path) return -1;\n return left.path > right.path ? 1 : 0;\n}\n\n/**\n * Everything the builder changed in `root` since `baseline`, classified against\n * the gate patterns. Tracked edits come from the diff, brand-new files from the\n * untracked list — together they cover both checkpoint styles, since `--git`\n * commits the builder's work as it goes while a plain run leaves it dirty.\n *\n * Returns null when `root` is not a git repository: the one honest answer, and\n * the signal every consumer uses to omit the section rather than claim the\n * builder changed nothing.\n */\nexport function collect_changes(options: CollectChangesOptions): ChangeSet | null {\n const { root, baseline } = options;\n if (!in_git_repo(root)) return null;\n const limit = options.limit ?? DEFAULT_LIMIT;\n\n // `--relative` + `-- .` keep both halves scoped to the build root and its own\n // path vocabulary, for the case where the workspace sits under a repo root.\n const tracked =\n baseline === null\n ? []\n : parse_name_status(\n git(root, ['diff', '--name-status', '--relative', '-z', baseline, '--', '.']).stdout,\n );\n const untracked: RawChange[] = parse_paths(\n git(root, ['ls-files', '--others', '--exclude-standard', '-z']).stdout,\n ).map((path) => ({ path, status: 'added' }));\n\n const excluded_dir = options.excluded_dir ?? null;\n const seen = new Set<string>();\n const files: ChangedFile[] = [];\n for (const change of [...tracked, ...untracked]) {\n if (excluded(change.path, excluded_dir) || seen.has(change.path)) continue;\n seen.add(change.path);\n files.push({ ...change, gate: matches_any(change.path, options.gate_patterns) });\n }\n const sorted = files.toSorted(by_path);\n\n return {\n baseline,\n // Over the full list, before the cap: truncation must never hide a gate edit.\n gate_edits: sorted.filter((file) => file.gate).map((file) => file.path),\n total: sorted.length,\n files: sorted.slice(0, limit),\n truncated: sorted.length > limit,\n };\n}\n","/**\n * Critic prompt resolution and composition. Presets live as\n * markdown files in ./presets/ — discoverable by listing the directory —\n * and every critic system prompt gets the harness append.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { config_error } from '../types.js';\nimport type {\n ChangeSet,\n ChangeStatus,\n ChangedFile,\n CheckResult,\n ResolvedConfig,\n} from '../types.js';\nimport { state_path } from '../workspace.js';\nimport type { ToolSet } from '../workspace_tools.js';\nimport { build_root } from '../worktree.js';\n\n/** Walk up from this module to the package root (works from src/ under tsx\n * and from dist/ in the published package, which ships src/critic/presets). */\nexport function presets_dir(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const candidate = join(dir, 'src', 'critic', 'presets');\n if (existsSync(candidate)) return candidate;\n const local = join(dir, 'presets');\n if (existsSync(local)) return local;\n dir = dirname(dir);\n }\n throw config_error('critic presets directory not found');\n}\n\n/** The harness append that names the critic's reads. The CLI critic reads\n * via built-in Read/Grep/Glob and never takes an injected set; every other\n * critic, local or `openrouter`, reads via volley's read_file/search_files/\n * list_files, or under `volley acp` via fascicle's read_file/list_files/\n * search. */\nfunction harness_append_file(config: ResolvedConfig, tool_set: ToolSet): string {\n if (config.critic_provider === 'claude_cli') return 'harness_append.md';\n return tool_set === 'acp' ? 'harness_append_acp.md' : 'harness_append_local.md';\n}\n\nexport function resolve_critic_prompt(config: ResolvedConfig, tool_set: ToolSet = 'volley'): string {\n const base =\n config.critic_prompt_path !== null\n ? readFileSync(config.critic_prompt_path, 'utf8')\n : readFileSync(join(presets_dir(), `${config.critic_preset}.md`), 'utf8');\n const append = readFileSync(join(presets_dir(), harness_append_file(config, tool_set)), 'utf8');\n return `${base.trimEnd()}\\n\\n${place_iterations_dir(append, config).trimEnd()}`;\n}\n\nconst ITERATIONS_DIR = '{{iterations_dir}}';\n\n/** Fill the harness append's line about prior iteration state with where the\n * run's `iterations/` sits, relative to the build root the critic reads from,\n * or drop the line when the run's state is outside that root: a confined\n * critic can't reach it, and naming it would only spend the critic's steps on\n * a path it can't open. */\nfunction place_iterations_dir(append: string, config: ResolvedConfig): string {\n const path = relative(\n build_root(config.workspace, config.worktree),\n state_path(config, 'iterations'),\n );\n const outside = path === '..' || path.startsWith(`..${sep}`) || isAbsolute(path);\n return append\n .split('\\n')\n .filter((line) => !(outside && line.includes(ITERATIONS_DIR)))\n .join('\\n')\n .replaceAll(ITERATIONS_DIR, `${path}/`);\n}\n\nexport type CriticPromptInput = {\n criteria: string;\n iteration: number;\n check: CheckResult;\n /** What the builder changed since the run's baseline (`src/changes.ts`), or\n * null when the build root is not a git repository — then the section is\n * omitted rather than claiming the builder changed nothing. */\n changes: ChangeSet | null;\n};\n\n/** One-letter status column, so a hundred-path list stays readable. */\nconst STATUS_MARKS: Record<ChangeStatus, string> = {\n added: 'A',\n modified: 'M',\n deleted: 'D',\n renamed: 'R',\n unknown: '?',\n};\n\nfunction format_change(file: ChangedFile): string {\n return ` ${STATUS_MARKS[file.status]} ${file.path}`;\n}\n\n/**\n * What the builder actually touched, handed to the critic as evidence.\n *\n * Two things this fixes, both surfaced by the reckon run\n * (`research/reckon-local-run-finding.md`). A critic that sees only the finished\n * tree reviews *state* and re-reads code the check already blessed; a critic\n * that sees the change list reviews the *change*, and knows where to point its\n * read tools. And a builder that edited its own tests could previously pass both\n * gates in silence — the check because it was rewritten, the critic because\n * nothing told it that had happened.\n *\n * Paths only, never diff hunks: the list stays bounded for a 32k-context local\n * critic, which can read any file it wants once it knows which ones moved.\n */\nfunction format_changes_section(changes: ChangeSet | null): string | null {\n if (changes === null) return null;\n const scope = changes.baseline === null ? 'this run' : `baseline ${changes.baseline.slice(0, 8)}`;\n if (changes.total === 0) {\n return [\n `BUILDER CHANGES (since ${scope})`,\n '------------------------------',\n 'The builder changed no files. Unless the acceptance criteria were already',\n 'met before this run, that is itself grounds for changes_requested.',\n ].join('\\n');\n }\n const lines = [\n `BUILDER CHANGES (since ${scope})`,\n '------------------------------',\n 'Review the work as a change, not just as a finished tree. Read the files',\n 'below with your tools as needed.',\n '',\n ...changes.files.map(format_change),\n ];\n if (changes.truncated) {\n lines.push(\n ` … showing ${String(changes.files.length)} of ${String(changes.total)} changed paths`,\n );\n }\n if (changes.gate_edits.length > 0) {\n lines.push(\n '',\n `GATE EDITS (${String(changes.gate_edits.length)})`,\n '-----------',\n 'These changed paths are part of the gate — the tests, fixtures, and check',\n 'configuration that decide whether this work passes. A check the builder can',\n 'edit proves less than one it cannot.',\n '',\n ...changes.gate_edits.map((path) => ` ! ${path}`),\n '',\n 'Judge whether each of these edits was necessary and legitimate for the task',\n 'as specified. If any of them weakened the check, deleted a case, or moved a',\n 'target rather than meeting it, the work does not meet the criteria: return',\n 'changes_requested, name the file, and say what was weakened.',\n );\n }\n return lines.join('\\n');\n}\n\nfunction format_check_section(check: CheckResult): string {\n if (!check.ran) {\n return 'No deterministic check ran for this iteration. Base your verdict on workspace inspection alone.';\n }\n const lines = [\n `DETERMINISTIC CHECK (${check.runner})`,\n '------------------------------------',\n `result: ${check.ok ? 'PASSED' : 'FAILED'} (exit ${String(check.exit_code)})`,\n ];\n if (check.failing_slots.length > 0) {\n lines.push(`failing slots: ${check.failing_slots.join(', ')}`);\n }\n if (check.summary !== undefined) {\n lines.push('', 'summary.json:', '```json', JSON.stringify(check.summary, null, 2), '```');\n }\n for (const artifact of check.detail) {\n lines.push(\n '',\n `--- raw output for failing slot \"${artifact.slot}\"${artifact.truncated ? ` (truncated; full output archived at ${artifact.path ?? 'n/a'})` : ''} ---`,\n artifact.content,\n );\n }\n if (check.log !== undefined && check.log.length > 0) {\n lines.push('', 'check output:', '```', check.log, '```');\n }\n return lines.join('\\n');\n}\n\nexport function compose_critic_prompt(input: CriticPromptInput): string {\n const changes = format_changes_section(input.changes);\n return [\n 'ACCEPTANCE CRITERIA',\n '-------------------',\n input.criteria,\n '',\n `ITERATION: ${input.iteration}`,\n '',\n format_check_section(input.check),\n ...(changes === null ? [] : ['', changes]),\n '',\n 'Review the workspace against the acceptance criteria and return your',\n 'structured verdict.',\n ].join('\\n');\n}\n","/**\n * Critic invocation: a read-only session (`claude_cli`, or a local or\n * `openrouter` model with volley's read tools) returning a schema-validated\n * structured verdict. The\n * harness — not the critic — writes the run's `feedback.md` and `verdict`.\n */\nimport { z } from 'zod';\nimport { model_call } from 'fascicle';\nimport type {\n Engine,\n FallbackOutcome,\n GenerateOptions,\n GenerateResult,\n RetryOutcome,\n RunContext,\n Step,\n StreamChunk,\n Tool,\n} from 'fascicle';\nimport {\n CRITIC_ALLOWED_TOOLS,\n CRITIC_DISALLOWED_TOOLS,\n settings_args,\n} from '../claude_cli_permissions.js';\nimport { accumulate } from '../cost.js';\nimport { seat_base_url } from '../engine.js';\nimport { prewarm_ollama_model } from '../prewarm.js';\nimport { error_kind, phase_error } from '../types.js';\nimport type { CauseKind, DegradeCause, LoopState, ResolvedConfig } from '../types.js';\nimport type { ToolSet } from '../workspace_tools.js';\nimport { build_root } from '../worktree.js';\nimport { compose_critic_prompt, resolve_critic_prompt } from './prompt.js';\nimport { read_only_tools, workspace_inventory } from './tools.js';\n\n/** A critic that holds tools isn't constrain-decoded, so nothing stops it\n * answering null for the feedback or the unmet list, as GLM did on approving.\n * Both fields allow null and read it as empty, so that answer is a verdict\n * rather than a schema failure that ends the run. fascicle sends the schema's\n * input side, so the model sees each field as its type or null, still\n * required; `.describe()` comes last so the description stays on the field. */\nexport const verdict_schema = z.object({\n verdict: z.enum(['approved', 'changes_requested']),\n feedback: z\n .string()\n .nullable()\n .transform((feedback) => feedback ?? '')\n .describe(\n 'Free-form markdown for the builder. Concrete and actionable. ' +\n 'Will be passed verbatim into the next iteration.',\n ),\n unmet_criteria: z\n .array(z.string())\n .nullable()\n .transform((unmet) => unmet ?? [])\n .describe(\n 'The specific acceptance criteria judged unmet, verbatim. Empty when approved.',\n ),\n});\n\nexport type VerdictOutput = z.infer<typeof verdict_schema>;\n\nexport type CriticDeps = {\n engine: Engine;\n config: ResolvedConfig;\n on_chunk: (chunk: StreamChunk) => void;\n /** Tools to hand the critic's tool-bearing call in place of volley's reads;\n * absent, it gets those. A `claude_cli` critic reads through the CLI's own\n * tools and never takes these. The critic takes no approval handler, since\n * nothing it reads with should ever ask. */\n tools?: ReadonlyArray<Tool>;\n /** Which set `tools` is, so the harness append names the reads the critic\n * holds; absent, volley's own. */\n tool_set?: ToolSet;\n};\n\n/** Read-only tool wiring per provider. The claude_cli critic is confined at\n * the CLI permission layer (allowlist + explicit disallow, and the settings\n * blocks that keep its reads in the build root); every other critic,\n * local or `openrouter`, gets volley's own workspace-scoped read-only tools (or\n * the set the caller injected in their place) and no write path at all.\n *\n * The providers also enforce `verdict_schema` by different paths, the first\n * two verified live. The claude_cli critic compiles the schema for\n * `claude --json-schema`; that only works because fascicle 0.14.0's\n * `compile_schema` strips the top-level `$schema`/`$id` that zod v4 stamps (the\n * CLI rejects them) — `live_smoke` asserts a structured verdict comes back, so a\n * future fascicle regression there fails loudly rather than silently. The local\n * (ollama/lmstudio) critic instead gets Ollama **constrained decode** —\n * fascicle's ai_sdk default whenever a `schema` is passed — so the verdict is\n * structurally guaranteed at decode time, with no prompt-parse-repair;\n * `live_local_builder` exercises that path. Unchanged in v3: on ai_sdk\n * constrained decode needs no wiring, and under the deferred native flip it\n * would move to `provider_options.ollama.format` (parked). An `openrouter`\n * critic rides fascicle's native OpenAI-compatible core, which has no\n * constrained decode: the schema travels in the prompt, and the reply is parsed\n * and repaired. */\nfunction critic_tool_options(\n config: ResolvedConfig,\n tools?: ReadonlyArray<Tool>,\n): Pick<GenerateOptions<VerdictOutput>, 'tools' | 'provider_options' | 'max_steps'> {\n if (config.critic_provider === 'claude_cli') {\n return {\n provider_options: {\n claude_cli: {\n allowed_tools: [...CRITIC_ALLOWED_TOOLS],\n extra_args: ['--disallowedTools', CRITIC_DISALLOWED_TOOLS, ...settings_args()],\n },\n },\n };\n }\n // Read the builder's actual output: under `--worktree` that lives in\n // the worktree, so the local critic's read tools resolve through the same\n // re-pointed containment root as the builder's writes.\n return {\n tools:\n tools === undefined\n ? read_only_tools(build_root(config.workspace, config.worktree))\n : [...tools],\n max_steps: CRITIC_MAX_STEPS,\n };\n}\n\n/** The local critic's step budget for its tool-bearing call: reads plus the\n * verdict. Set explicitly rather than inherited from fascicle's engine default\n * (also 10), so a change to that default can't move it silently. */\nexport const CRITIC_MAX_STEPS = 10;\n\n/** Degradation ladder rung 1: how many times a local critic's call\n * is retried on a provider stream death before the ladder moves on. Capped at\n * one — the qwen3.6/Ollama tool-XML parser death is stochastic, so a same-call\n * retry often passes; past one attempt the failure is not transient and the\n * tool-less fallback must take over. */\nexport const MAX_CRITIC_RETRIES = 1;\n\n/** Is this critic failure the transient provider stream death the ladder\n * retries? Every provider but `claude_cli` (that path is proven and its\n * retries cost real money), and fascicle's typed `provider_error` only (no\n * message string-matching). A user abort never gets here: `retry` and\n * `fallback` pass control-flow signals through untouched, and `retry` checks the\n * signal before every attempt, so an abort stays exit-130. */\nfunction is_retryable_critic_error(config: ResolvedConfig, err: unknown): boolean {\n if (config.critic_provider === 'claude_cli') return false;\n return error_kind(err) === 'provider_error';\n}\n\n/** Did a schema call end without a verdict because the tool loop ran out —\n * its step budget spent, or its last turn a tool call — rather than because\n * the response was cut off or blocked? fascicle throws\n * `incomplete_generation_error` for every such finish; only these two are\n * fixed by taking the tools away. Matched on `kind` and `finish_reason`. */\nfunction is_step_exhaustion(err: unknown): boolean {\n if (error_kind(err) !== 'incomplete_generation_error') return false;\n const finish = (err as { finish_reason?: unknown }).finish_reason;\n return finish === 'max_steps' || finish === 'tool_calls';\n}\n\n/** Does this failure send a local critic to the tool-less rung? A stream death\n * the retry rung gave up on, or step exhaustion, which no retry would fix. A\n * `length` or `content_filter` finish is neither, and stays fatal. */\nfunction is_degradable_critic_error(config: ResolvedConfig, err: unknown): boolean {\n if (config.critic_provider === 'claude_cli') return false;\n return error_kind(err) === 'provider_error' || is_step_exhaustion(err);\n}\n\n/** fascicle's `provider_error.cause_kind` is `... | undefined`; fold the\n * missing case into `'unknown'` so a recorded retry always names a cause. */\nfunction retry_cause_kind_of(err: unknown): CauseKind {\n const cause = (err as { cause_kind?: unknown }).cause_kind;\n return cause === 'provider_5xx' || cause === 'network' ? cause : 'unknown';\n}\n\n/** Bookkeeping stamped onto a critic record by the degradation ladder: how many\n * tool-bearing retries preceded this verdict, the last retry's cause, and — on the\n * tool-less rung — the `critic_degraded` mark. */\ntype LadderMark = {\n retries: number;\n retry_cause_kind: CauseKind | undefined;\n critic_degraded?: boolean;\n degrade_cause?: DegradeCause;\n};\n\n/** Fold a successful critic `generate` result into loop state, stamping the\n * ladder bookkeeping onto the critic record. Shared by the tool-bearing path and\n * the tool-less fallback so both shape the record identically (the fallback just\n * adds `critic_degraded: true`). */\nfunction finalize_critic(\n state: LoopState,\n result: GenerateResult<VerdictOutput>,\n model: string,\n mark: LadderMark,\n duration_ms: number,\n): LoopState {\n const next = accumulate(state, 'critic', result, model, duration_ms);\n return {\n ...next,\n critic:\n next.critic === null\n ? null\n : {\n ...next.critic,\n retries: mark.retries,\n ...(mark.retry_cause_kind !== undefined\n ? { retry_cause_kind: mark.retry_cause_kind }\n : {}),\n ...(mark.critic_degraded === true ? { critic_degraded: true } : {}),\n ...(mark.degrade_cause !== undefined ? { degrade_cause: mark.degrade_cause } : {}),\n },\n verdict: result.content.verdict,\n feedback: result.content.feedback,\n unmet_criteria: result.content.unmet_criteria,\n };\n}\n\n/** The tool-less fallback's prompt: the normal critic prompt plus a notice that\n * read tools are gone this pass and a paths+sizes workspace inventory, so\n * the critic still judges from the criteria, the raw check artifacts already in\n * the prompt, and the file layout — grounded, just shallower. */\nexport function toolless_critic_prompt(config: ResolvedConfig, tool_prompt: string): string {\n return [\n tool_prompt,\n '',\n 'NOTE: file-read tools are unavailable for this review. Judge from the',\n 'acceptance criteria, the deterministic check output above, and the workspace',\n 'file inventory below (paths and sizes only — file contents are not shown).',\n '',\n 'WORKSPACE FILE INVENTORY',\n '------------------------',\n workspace_inventory(build_root(config.workspace, config.worktree)),\n ].join('\\n');\n}\n\n/** What the critic arm answers with: the call that produced the verdict, and\n * how the ladder reached it. */\nexport type CriticAnswer = {\n result: GenerateResult<VerdictOutput>;\n mark: LadderMark;\n};\n\n/** The critic's model boundary: the whole degradation ladder behind one step\n * (composed in `../flow.ts`). */\nexport type CriticStep = Step<string, CriticAnswer>;\n\n/** One critic call returning the validated verdict in its `GenerateResult`. */\nexport type CriticCall = Step<string, GenerateResult<VerdictOutput>>;\n\nfunction critic_call_config(deps: CriticDeps) {\n const { config } = deps;\n return {\n engine: deps.engine,\n provider: config.critic_provider,\n model: config.critic_model,\n system: resolve_critic_prompt(config, deps.tool_set),\n schema: verdict_schema,\n on_chunk: deps.on_chunk,\n };\n}\n\n/** Rung 1's leaf: the critic with its read tools (or the CLI's read-only\n * allowlist). */\nexport function make_critic_tools_step(deps: CriticDeps): CriticCall {\n return model_call({\n ...critic_call_config(deps),\n id: 'critic_tools',\n description: 'model call with read-only workspace tools',\n ...critic_tool_options(deps.config, deps.tools),\n });\n}\n\n/** Rung 2's leaf: the same critic with no tools at all, so nothing enters\n * Ollama's broken tool parser; constrained decode (`schema`) still guarantees\n * the verdict. */\nexport function make_critic_toolless_step(deps: CriticDeps): CriticCall {\n return model_call({\n ...critic_call_config(deps),\n id: 'critic_toolless',\n description: 'model call judging from the check output and a file list',\n });\n}\n\n/** What the retry rung knew about the error that ended it: the attempt it\n * died on, and the cause of the stream death it last retried. fascicle's\n * `retry` rethrows that error untouched, so the fallback's projection looks it\n * up here to count the retries behind a degraded verdict. */\ntype LadderTrace = { attempt: number; retried_cause: CauseKind | undefined };\n\nconst ladder_traces = new WeakMap<object, LadderTrace>();\n\n/** The ladder's retry predicate for this run's critic provider: stream deaths\n * only. It also traces every failure it sees, so a degraded verdict can say how\n * many retries preceded it and why. A first attempt starts a fresh critique, so\n * it forgets the last one's retries. */\nexport function critic_retryable(\n config: ResolvedConfig,\n): (err: unknown, attempt: number) => boolean {\n let retried_cause: CauseKind | undefined;\n return (err, attempt) => {\n if (attempt === 1) retried_cause = undefined;\n if (typeof err === 'object' && err !== null) {\n ladder_traces.set(err, { attempt, retried_cause });\n }\n const retryable = is_retryable_critic_error(config, err);\n if (retryable) retried_cause = retry_cause_kind_of(err);\n return retryable;\n };\n}\n\n/** The ladder's fallback predicate: a stream death the retry rung gave up on,\n * or step exhaustion, which it never retries. */\nexport function critic_degradable(config: ResolvedConfig): (err: unknown) => boolean {\n return (err) => is_degradable_critic_error(config, err);\n}\n\n/** Rung 1's projection: a verdict the tool-bearing critic produced, marked with\n * how many stream deaths it took and the last one's cause. */\nexport function with_retries(outcome: RetryOutcome<GenerateResult<VerdictOutput>>): CriticAnswer {\n const last = outcome.errors.at(-1);\n return {\n result: outcome.value,\n mark: {\n retries: outcome.attempts - 1,\n retry_cause_kind: last === undefined ? undefined : retry_cause_kind_of(last),\n },\n };\n}\n\n/** Rung 2's answer, marked degraded so it never passes silently as a full\n * critique. Why it degraded, and the retries before it, are the ladder's to\n * stamp (`with_fallback_cause`), since the tool-less call can't see them. */\nexport function as_degraded(result: GenerateResult<VerdictOutput>): CriticAnswer {\n return {\n result,\n mark: { retries: 0, retry_cause_kind: undefined, critic_degraded: true },\n };\n}\n\n/** The ladder's projection: the tool-less backup cannot see why it ran, so the\n * mark comes from the error that sent it there.\n *\n * - A stream death the retry rung gave up on: every retry was spent, and the\n * cause is that error's own.\n * - Step exhaustion, never retried: the retries are the stream deaths before\n * it, usually none, and the cause is the last of those.\n *\n * An error the retry rung never traced reads as one that spent every retry. */\nexport function with_fallback_cause(outcome: FallbackOutcome<CriticAnswer>): CriticAnswer {\n if (outcome.source === 'primary') return outcome.value;\n const err = outcome.primary_error;\n const trace =\n typeof err === 'object' && err !== null ? ladder_traces.get(err) : undefined;\n const retries = trace === undefined ? MAX_CRITIC_RETRIES : trace.attempt - 1;\n const exhausted = is_step_exhaustion(err);\n const retry_cause_kind = exhausted ? trace?.retried_cause : retry_cause_kind_of(err);\n return {\n ...outcome.value,\n mark: {\n ...outcome.value.mark,\n retries,\n retry_cause_kind,\n degrade_cause: exhausted ? 'step_exhaustion' : 'stream_error',\n },\n };\n}\n\n/** What the `--dry-run` canary learned about the critic seat:\n * `ok` — the tool-bearing call came back; `degraded` — the tool-bearing\n * call died on a provider stream error or ran out of steps, but a tool-less\n * pass survived, so a real run will likely finish via the fallback ladder\n * (`critic_degraded`);\n * `failed` — even the tool-less pass died, so the combo would fail a real run\n * degraded or not. */\nexport type CanaryOutcome =\n | { outcome: 'ok' }\n | { outcome: 'degraded'; detail: string }\n | { outcome: 'failed'; detail: string };\n\n/** The canary must *elicit a real tool call*: the qwen3.6 death happens at\n * tool-markup emission inside Ollama's server-side parser, so a call that never\n * invokes a tool could not fail and would prove nothing. The target path need\n * not exist — a tool error is fed back and the model answers anyway; entering\n * the parser is the test. No token cap: the budget is behavioral (one tool call,\n * then an immediate one-word verdict), because a hard `max_tokens` could\n * truncate a thinking model mid-verdict and report `failed` for a combo that\n * works. A model that skips the tool and just answers passes stochastically —\n * acceptable: the canary is early warning, the ladder is the guarantee. */\nconst CANARY_PROMPT = [\n 'CANARY CHECK — a tiny wiring probe, not a real review.',\n 'First, call the read_file tool on the path \"package.json\".',\n 'Whatever the tool returns (content or an error), immediately answer with',\n 'verdict \"approved\", feedback exactly \"canary\", and empty unmet_criteria.',\n].join('\\n');\n\n/** The canary's tool-less rung: same schema-constrained call, no tool ask. */\nconst CANARY_TOOLLESS_PROMPT = [\n 'CANARY CHECK — a tiny wiring probe, not a real review.',\n 'Answer with verdict \"approved\", feedback exactly \"canary\", and empty',\n 'unmet_criteria.',\n].join('\\n');\n\nfunction canary_detail(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * The `--dry-run` critic-seat canary: one tiny generate through the *real*\n * production tool wiring (`critic_tool_options`) and `verdict_schema`, $0 on a\n * local model. The caller (preflight) gates it to local critics only —\n * `claude_cli` is proven, and its calls and `openrouter`'s cost real money.\n *\n * A tool-bearing death is classified by the same discriminant as the run-time\n * ladder's fallback (a typed `provider_error`, or step exhaustion), then probed\n * tool-less exactly as rung 2 would run, so the canary *predicts the ladder*\n * instead of guessing:\n * tool-less survives → `degraded` (warn — the combo completes a real run,\n * marked); tool-less dies too → `failed` (the endpoint-down / model-missing\n * class that earns exit 5 because not even degradation would save it).\n */\nexport async function critic_canary(\n engine: Engine,\n config: ResolvedConfig,\n env: Record<string, string | undefined> = process.env,\n): Promise<CanaryOutcome> {\n // Same cold-load guard as the real critic phase: without it a disk-cold model\n // would die on the first-byte timeout and the canary would cry wolf.\n if (config.critic_provider === 'ollama') {\n await prewarm_ollama_model(\n seat_base_url('ollama', config.critic_url, env),\n config.critic_model,\n );\n }\n const base: Omit<GenerateOptions<VerdictOutput>, 'prompt' | 'tools' | 'provider_options'> = {\n provider: config.critic_provider,\n model: config.critic_model,\n system: resolve_critic_prompt(config),\n schema: verdict_schema,\n };\n try {\n await engine.generate({\n ...base,\n prompt: CANARY_PROMPT,\n ...critic_tool_options(config),\n });\n return { outcome: 'ok' };\n } catch (err) {\n if (!is_degradable_critic_error(config, err)) {\n return { outcome: 'failed', detail: canary_detail(err) };\n }\n const tool_death = canary_detail(err);\n try {\n await engine.generate({ ...base, prompt: CANARY_TOOLLESS_PROMPT });\n return { outcome: 'degraded', detail: tool_death };\n } catch (fallback_err) {\n return { outcome: 'failed', detail: canary_detail(fallback_err) };\n }\n }\n}\n\nexport type CriticRunDeps = {\n critic: CriticStep;\n config: ResolvedConfig;\n};\n\nexport async function run_critic(\n deps: CriticRunDeps,\n state: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config } = deps;\n if (state.check === null) {\n throw phase_error('critic', state.iteration, new Error('check phase did not run'));\n }\n const check = state.check;\n try {\n // Same cold-load guard as the builder: pre-load an Ollama critic model on\n // the critic seat's own server so a cold multi-GB load doesn't blow the real\n // call's first-byte timeout. Best-effort; when both seats share a server and\n // a model, the builder's warm-up already loaded it and this returns at once.\n if (config.critic_provider === 'ollama') {\n await prewarm_ollama_model(\n seat_base_url('ollama', config.critic_url, process.env),\n config.critic_model,\n ctx.abort,\n );\n }\n const prompt = compose_critic_prompt({\n criteria: config.criteria,\n iteration: state.iteration,\n check,\n changes: state.changes,\n });\n // The phase's duration spans every rung that ran, not just the call that\n // answered: a retried or degraded verdict took that long to get, and no one\n // result's `timing` covers the attempts before it.\n const started = Date.now();\n const { result, mark } = await ctx.call(deps.critic, prompt);\n return finalize_critic(state, result, config.critic_model, mark, Date.now() - started);\n } catch (err) {\n throw phase_error('critic', state.iteration, err);\n }\n}\n","/**\n * Display formatting: glyph taxonomy, role colors, truncation.\n * All human output goes to stderr; these helpers only build strings.\n */\nimport pc from 'picocolors';\n\nexport const GLYPH_TOOL = '🔧';\nexport const GLYPH_OK = '✅';\nexport const GLYPH_ERR = '❌';\nexport const GLYPH_COST = '💰';\nexport const GLYPH_PHASE_START = '▶';\nexport const GLYPH_PHASE_OK = '✓';\nexport const GLYPH_PHASE_FAIL = '✗';\n\nexport const VERBOSE_TRUNCATE_CHARS = 4000;\n\nexport type Role = 'builder' | 'critic' | 'check';\n\nexport function colors_enabled(\n env: Record<string, string | undefined> = process.env,\n is_tty: boolean = process.stderr.isTTY === true,\n): boolean {\n if (env['NO_COLOR'] !== undefined || env['VOLLEY_NO_COLOR'] !== undefined) {\n return false;\n }\n return is_tty;\n}\n\nexport function paint(role: Role | 'cost' | 'error', text: string, color: boolean): string {\n if (!color) return text;\n switch (role) {\n case 'builder':\n return pc.cyan(text);\n case 'critic':\n return pc.yellow(text);\n case 'check':\n return pc.green(text);\n case 'cost':\n return pc.magenta(text);\n case 'error':\n return pc.bold(pc.red(text));\n }\n}\n\nexport function dim(text: string, color: boolean): string {\n return color ? pc.dim(text) : text;\n}\n\nexport function truncate(text: string, max: number, pointer: string): string {\n if (text.length <= max) return text;\n return `${text.slice(0, max)}\\n… [truncated at ${String(max)} chars; ${pointer}]`;\n}\n\n/** Controls, format characters (bidi overrides, zero-widths), and line and\n * paragraph separators: what can move the cursor, hide text, or reorder a line\n * in a terminal. */\nconst UNSAFE_CHARACTERS = /[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}]/gu;\n\n/** A value from a file volley can't vouch for, quoted for a person to judge,\n * with every character that could redraw or reorder the line escaped, so a\n * rewritten config can't make the warning about it say something else. JSON\n * quoting escapes the C0 controls, the quote, and the backslash; the rest are\n * written as `\\u{…}`. */\nexport function shown(value: string): string {\n return JSON.stringify(value).replace(\n UNSAFE_CHARACTERS,\n (character) => `\\\\u{${(character.codePointAt(0) ?? 0).toString(16)}}`,\n );\n}\n\nexport function format_usd(value: number | null): string {\n return value === null ? '$?' : `$${value.toFixed(3)}`;\n}\n\n/** One-line summary of a tool input for the default streaming mode. */\nexport function summarize_value(value: unknown, max = 120): string {\n let text: string;\n try {\n text = typeof value === 'string' ? value : JSON.stringify(value) ?? '';\n } catch {\n text = String(value);\n }\n const flat = text.replace(/\\s+/g, ' ');\n return flat.length > max ? `${flat.slice(0, max)}…` : flat;\n}\n","/**\n * Iteration archiving, run-level summary, and resume-state recovery.\n * `feedback.md` and `verdict` are harness-written projections\n * of the critic's validated structured output.\n */\nimport {\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { basename, join, resolve } from 'node:path';\nimport { read_failing_artifacts } from './check/checkride.js';\nimport type { CheckrideSummary, CheckrideSummaryCheck } from './check/checkride.js';\nimport { EMPTY_USAGE } from './cost.js';\nimport { shown } from './render/format.js';\nimport { config_error } from './types.js';\nimport type {\n BuilderPermissionMode,\n BuilderProvider,\n CheckArtifact,\n CheckResult,\n CriticProvider,\n LoopState,\n PhaseRecord,\n ResolvedConfig,\n RunResult,\n RunStatus,\n Verdict,\n VolleyConfig,\n} from './types.js';\nimport { detect_containment } from './containment.js';\nimport { config_signed } from './trust.js';\nimport {\n CONFIG_SIGNATURE,\n iteration_dir,\n RUN_ID_PATTERN,\n run_state_dir,\n state_path,\n} from './workspace.js';\nimport type { StateLocation } from './workspace.js';\n\nfunction write_json(path: string, value: unknown): void {\n writeFileSync(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction persist_verdict_files(\n config: ResolvedConfig,\n feedback: string,\n verdict: Verdict,\n): void {\n writeFileSync(state_path(config, 'feedback.md'), feedback.endsWith('\\n') ? feedback : `${feedback}\\n`);\n writeFileSync(state_path(config, 'verdict'), `${verdict}\\n`);\n}\n\nfunction phase_summary(record: PhaseRecord | null): Record<string, unknown> | null {\n if (record === null) return null;\n return {\n provider: record.provider,\n model: record.model,\n session_id: record.session_id,\n duration_ms: record.duration_ms,\n usage: record.usage,\n cost_usd: record.cost_usd,\n cost_source: record.cost_source,\n finish_reason: record.finish_reason,\n tool_calls: record.tool_calls,\n salvaged_tool_calls: record.salvaged_tool_calls,\n // Salvage rate (a health metric): the share of tool calls recovered from\n // assistant text. A high rate on a local run means the model's native\n // tool-call encoding is drifting from its runtime's parser (pin them as one\n // unit). 0 when the phase made no tool calls (the CLI builder's own loop).\n salvage_rate: record.tool_calls === 0 ? 0 : record.salvaged_tool_calls / record.tool_calls,\n // Turns cut off at the builder's output cap before a tool call. Emitted\n // only when there were any. Additive.\n ...(record.truncated_turns !== undefined ? { truncated_turns: record.truncated_turns } : {}),\n // Degradation-ladder bookkeeping, critic-only: the provider-error\n // retries that preceded this verdict, their cause, whether it was rendered\n // by the tool-less fallback, and why. Emitted only when set, so the builder\n // record and old summary consumers are untouched. `critic_degraded` and\n // `degrade_cause` are the on-disk half of the contract — the comparison\n // block reads them back from here.\n ...(record.retries !== undefined ? { retries: record.retries } : {}),\n ...(record.retry_cause_kind !== undefined\n ? { retry_cause_kind: record.retry_cause_kind }\n : {}),\n ...(record.critic_degraded === true ? { critic_degraded: true } : {}),\n ...(record.degrade_cause !== undefined ? { degrade_cause: record.degrade_cause } : {}),\n // Model speed, where fascicle could time the turns (never `claude_cli`).\n // Emitted only when measured. Additive.\n ...(record.throughput !== undefined ? { throughput: record.throughput } : {}),\n // Each builder turn's request size, timing split, and tool output sizes,\n // so a session's growth can be read back (#7). Builder-only. Additive.\n ...(record.steps !== undefined ? { steps: record.steps } : {}),\n };\n}\n\n/** Archive one completed iteration: verdict files, check artifacts, and the\n * per-iteration summary. */\nexport function archive_iteration(config: ResolvedConfig, state: LoopState): void {\n const dir = iteration_dir(config, state.iteration);\n mkdirSync(join(dir, 'check'), { recursive: true });\n\n if (state.verdict !== null && state.feedback !== null) {\n persist_verdict_files(config, state.feedback, state.verdict);\n writeFileSync(join(dir, 'feedback.md'), readFileSync(state_path(config, 'feedback.md')));\n writeFileSync(join(dir, 'verdict'), `${state.verdict}\\n`);\n }\n\n const check = state.check;\n if (check !== null && check.ran) {\n if (check.runner === 'checkride') {\n if (check.summary !== undefined) {\n write_json(join(dir, 'check', 'summary.json'), check.summary);\n }\n for (const artifact of check.detail) {\n if (artifact.path !== null && existsSync(artifact.path)) {\n writeFileSync(join(dir, 'check', basename(artifact.path)), readFileSync(artifact.path));\n }\n }\n if (check.digest !== undefined) {\n writeFileSync(join(dir, 'check', 'digest.md'), check.digest);\n }\n // A checkride check has a log only when it was rejected, and the log\n // says so.\n if (check.log !== undefined) {\n writeFileSync(join(dir, 'check', 'check.log'), check.log);\n }\n } else {\n writeFileSync(join(dir, 'check', 'check.log'), check.log ?? '');\n writeFileSync(join(dir, 'check', 'check.exit'), `${String(check.exit_code)}\\n`);\n }\n }\n\n const completed_at = new Date().toISOString();\n write_json(join(dir, 'summary.json'), {\n iteration: state.iteration,\n started_at: state.iteration_started_at,\n completed_at,\n duration_ms: Date.parse(completed_at) - Date.parse(state.iteration_started_at),\n builder: phase_summary(state.builder),\n check:\n check === null\n ? null\n : {\n ran: check.ran,\n runner: check.runner,\n ok: check.ok,\n exit_code: check.exit_code,\n duration_ms: check.duration_ms,\n failing_slots: check.failing_slots,\n },\n critic: phase_summary(state.critic),\n // What the builder reached for this iteration (`src/changes.ts`), archived\n // beside the check's verdict so the two can be read against each other after\n // the fact: green + a gate edit is a different result from green alone.\n // Null when the build root is not a git repository. Additive.\n changes: state.changes,\n verdict: state.verdict,\n // The criteria the critic judged unmet, verbatim. The run-level summary\n // reads the last iteration's list, so a non-converged run says what it was\n // still missing when it stopped instead of only that it stopped. Additive.\n unmet_criteria: state.unmet_criteria,\n iteration_cost_usd: state.iteration_cost_usd,\n iteration_total_cost_usd: state.total_cost_usd,\n });\n}\n\nexport function run_result_from_state(\n config: ResolvedConfig,\n state: LoopState,\n status: RunStatus,\n completed_at: string | null,\n): RunResult {\n return {\n run_id: config.run_id,\n status,\n started_at: config.started_at,\n completed_at,\n iterations_completed: state.iteration,\n total_usage: state.total_usage,\n total_cost_usd: state.total_cost_usd,\n builder_cost_usd: state.builder_cost_usd,\n critic_cost_usd: state.critic_cost_usd,\n check_duration_ms: state.check_duration_ms,\n builder_max_steps_hits: state.builder_max_steps_hits,\n final_verdict: state.verdict,\n // The loop itself never salvages: the orchestrator re-stamps this after\n // teardown when a converged `--worktree` run's work was kept on its branch,\n // which is the only moment the branch's survival is known.\n salvaged_branch: null,\n run_state_dir: run_state_dir(config),\n mode: config.mode,\n };\n}\n\nexport type ResumeState = {\n raw_config: VolleyConfig;\n run_id: string;\n started_at: string;\n state: LoopState;\n iterations_completed: number;\n /** Whether this machine's signature held over the run's config: false only\n * when `trust_config` let an unsigned one through, and null inside the\n * sandbox, where nothing is checked. */\n config_signed: boolean | null;\n};\n\nexport type ResumeOptions = {\n /** Resume a config this machine didn't sign (`--trust-config`): another\n * machine's, an older volley's, one edited by hand, or a contained run's,\n * whose builder could have rewritten it. */\n trust_config?: boolean;\n env?: Readonly<Record<string, string | undefined>>;\n};\n\n/** Why a host-side resume won't run a config this machine didn't sign. */\nfunction untrusted_config(run_id: string, config_path: string): Error {\n return config_error(\n `run ${run_id}'s config.json has no signature from volley on this machine, so a resume here ` +\n \"won't run it: inside the sandbox a run's builder can rewrite its config, and a resume runs \" +\n 'the check and the seats it names. Resume a contained run inside its container, with the same ' +\n `mount. If ${config_path} is another machine's, an older volley's, or one you edited, read it, ` +\n 'then pass --trust-config.',\n );\n}\n\n/** Whether a host-side resume may run the config in `text`: signed by this\n * machine, or trusted by the caller. Inside the sandbox nothing is checked: a\n * resume there runs only within the container, as the builder already does. */\nfunction check_config_trust(\n text: string,\n run: StateLocation,\n options: ResumeOptions,\n): boolean | null {\n const env = options.env ?? process.env;\n if (detect_containment(env)) return null;\n const signature_path = state_path(run, CONFIG_SIGNATURE);\n const signature = existsSync(signature_path) ? readFileSync(signature_path, 'utf8') : null;\n const signed = config_signed(text, signature, env);\n if (!signed && options.trust_config !== true) {\n throw untrusted_config(run.run_id, state_path(run, 'config.json'));\n }\n return signed;\n}\n\n/** The run id an older volley's `.volley/config.json` records, or null when\n * there is none to read. */\nfunction legacy_run_id(workspace: string): string | null {\n try {\n const recorded = JSON.parse(readFileSync(join(workspace, '.volley', 'config.json'), 'utf8')) as {\n run_id?: unknown;\n };\n return typeof recorded.run_id === 'string' ? recorded.run_id : null;\n } catch {\n return null;\n }\n}\n\n/** Where `volley resume <run_id>` finds a run: under `root` (`--state-dir`,\n * else the default root) at `<root>/<run_id>/`, returned as that root, or, for\n * a run an older volley kept in the workspace, `.volley/`, returned as null so\n * the resumed run stays there. Finding neither is a config error naming both\n * places it looked. The id becomes a path, so it must be one a run could have\n * had. */\nexport function find_run_state(workspace: string, run_id: string, root: string): string | null {\n if (!RUN_ID_PATTERN.test(run_id)) {\n throw config_error(`not a run id: ${run_id} (letters, digits, '-', and '_', starting with a letter or digit)`);\n }\n if (existsSync(join(root, run_id, 'config.json'))) return root;\n const legacy = legacy_run_id(workspace);\n if (legacy === run_id) return null;\n // Read from a file nothing has vouched for, so quoted and escaped.\n const holds = legacy === null ? '' : ` (it holds run ${shown(legacy)})`;\n throw config_error(\n `run ${run_id} not found in ${join(root, run_id)} or in ${join(resolve(workspace), '.volley')}${holds}; ` +\n 'pass --state-dir for the root it ran under, or --workspace for a run kept in .volley/',\n );\n}\n\n/** A resumed run writes into its state directory, and a contained run's\n * builder could have written there first, so a symlink anywhere in it would\n * aim the resume's writes, or its pruning of a half-finished iteration, at a\n * file of the host's. volley never makes one, so any is refused. The walk\n * reads each entry's own type and never descends a link, which Node's\n * recursive `readdirSync` would. */\nfunction refuse_symlinks(dir: string): void {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isSymbolicLink()) {\n throw config_error(`refusing to resume: ${path} is a symbolic link, which volley never writes`);\n }\n if (entry.isDirectory()) refuse_symlinks(path);\n }\n}\n\n/** The part of an archived iteration's `summary.json` a resumed run reads\n * back. Every field is unknown until checked, since the archive could be torn\n * or older than this volley. */\ntype ArchivedRound = {\n builder?: unknown;\n check?: {\n ran?: unknown;\n runner?: unknown;\n ok?: unknown;\n exit_code?: unknown;\n duration_ms?: unknown;\n failing_slots?: unknown;\n } | null;\n};\n\n/** An archived file's text, or undefined when there's no file to read there. */\nfunction read_text(path: string): string | undefined {\n try {\n return readFileSync(path, 'utf8');\n } catch {\n return undefined;\n }\n}\n\nfunction read_json(path: string): unknown {\n const text = read_text(path);\n if (text === undefined) return null;\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return null;\n }\n}\n\n/** The failing slots' raw artifacts from an archived iteration's `check/`,\n * which holds each under its base name, found through the archived checkride\n * summary. */\nfunction archived_artifacts(check_dir: string, failing_slots: string[]): CheckArtifact[] {\n const summary = read_json(join(check_dir, 'summary.json')) as Partial<CheckrideSummary> | null;\n const checks = Array.isArray(summary?.checks) ? summary.checks : [];\n const failing = failing_slots.map((name): CheckrideSummaryCheck => {\n const output_file = checks.find((check) => check.name === name)?.output_file;\n return {\n name,\n adapter: null,\n ok: false,\n exit_code: null,\n duration_ms: 0,\n output_file: typeof output_file === 'string' ? basename(output_file) : null,\n };\n });\n return read_failing_artifacts(check_dir, failing);\n}\n\n/** The check an archived iteration ran, rebuilt from its directory with the\n * output its failure is shown by: the digest and the failing slots' artifacts\n * for checkride, the log for a command or a rejected check. Null when it ran\n * none. */\nfunction archived_check(dir: string, recorded: ArchivedRound['check']): CheckResult | null {\n if (recorded?.ran !== true || typeof recorded.ok !== 'boolean') return null;\n const runner = recorded.runner === 'checkride' ? 'checkride' : 'command';\n const failing_slots = Array.isArray(recorded.failing_slots)\n ? recorded.failing_slots.filter((slot): slot is string => typeof slot === 'string')\n : [];\n const check: CheckResult = {\n ran: true,\n runner,\n ok: recorded.ok,\n exit_code: typeof recorded.exit_code === 'number' ? recorded.exit_code : null,\n duration_ms: typeof recorded.duration_ms === 'number' ? recorded.duration_ms : 0,\n failing_slots,\n detail: [],\n };\n if (check.ok) return check;\n const check_dir = join(dir, 'check');\n const log = read_text(join(check_dir, 'check.log'));\n const logged = log === undefined ? check : { ...check, log };\n if (runner === 'command') return logged;\n const digest = read_text(join(check_dir, 'digest.md'));\n return {\n ...logged,\n detail: archived_artifacts(check_dir, failing_slots),\n ...(digest !== undefined ? { digest } : {}),\n };\n}\n\n/** An archived builder record, as `archive_iteration` wrote it from the\n * phase's own, or null when there is none with a finish reason. */\nfunction archived_builder(recorded: unknown): PhaseRecord | null {\n if (typeof recorded !== 'object' || recorded === null) return null;\n return typeof (recorded as Partial<PhaseRecord>).finish_reason === 'string'\n ? (recorded as PhaseRecord)\n : null;\n}\n\n/** What the last completed iteration left for the next build: its check and\n * its builder's record, which tell the resumed run's first builder what the\n * gate said and whether the last session ran out of steps, as a run that never\n * stopped would have. Null for both before the first iteration. */\nfunction archived_round(\n run: StateLocation,\n completed: number,\n): Pick<LoopState, 'check' | 'builder'> {\n if (completed === 0) return { check: null, builder: null };\n const dir = iteration_dir(run, completed);\n const recorded = read_json(join(dir, 'summary.json')) as ArchivedRound | null;\n return {\n check: archived_check(dir, recorded?.check),\n builder: archived_builder(recorded?.builder),\n };\n}\n\n/** Recover a resumable run from its state directory (`.volley/`, or\n * `<state_dir>/<run_id>/` under a state root): settings from config.json,\n * totals from summary.json, feedback from feedback.md. An iteration directory\n * without a summary.json was interrupted mid-phase and is discarded. A\n * directory with a symlink in it is refused before anything is read. */\nexport function load_resume_state(\n workspace: string,\n run_id: string,\n state_dir: string | null = null,\n options: ResumeOptions = {},\n): ResumeState {\n const run = { workspace, state_dir, run_id };\n const run_dir = run_state_dir(run);\n if (existsSync(run_dir)) {\n if (lstatSync(run_dir).isSymbolicLink()) {\n throw config_error(`refusing to resume: ${run_dir} is a symbolic link, which volley never writes`);\n }\n refuse_symlinks(run_dir);\n }\n const config_path = state_path(run, 'config.json');\n if (!existsSync(config_path)) {\n throw config_error(`no resumable run found: ${config_path} missing`);\n }\n const config_text = readFileSync(config_path, 'utf8');\n const signed = check_config_trust(config_text, run, options);\n const recorded = JSON.parse(config_text) as Record<string, unknown>;\n if (recorded['run_id'] !== run_id) {\n throw config_error(\n `run ${run_id} not found in ${run_state_dir(run)} (recorded run: ${String(recorded['run_id'])})`,\n );\n }\n if (recorded['mode'] === 'critique') {\n throw config_error(\n `run ${run_id} is a critique, which has one round and nothing to resume; run volley critique again`,\n );\n }\n\n const iterations_root = state_path(run, 'iterations');\n const dirs = existsSync(iterations_root)\n ? readdirSync(iterations_root).filter((d) => /^\\d{3}$/.test(d)).toSorted()\n : [];\n let completed = 0;\n for (const dir of dirs) {\n const full = join(iterations_root, dir);\n if (existsSync(join(full, 'summary.json'))) {\n completed = Number(dir);\n } else {\n rmSync(full, { recursive: true, force: true });\n }\n }\n\n const summary_path = state_path(run, 'summary.json');\n const summary = existsSync(summary_path)\n ? (JSON.parse(readFileSync(summary_path, 'utf8')) as RunResult)\n : null;\n\n const feedback_path = state_path(run, 'feedback.md');\n const feedback = existsSync(feedback_path) ? readFileSync(feedback_path, 'utf8') : null;\n\n const raw_config: VolleyConfig = {\n prompt: String(recorded['prompt']),\n workspace: String(recorded['workspace']),\n criteria: String(recorded['criteria']),\n check: String(recorded['check']),\n builder_model: String(recorded['builder_model']),\n builder_provider: (recorded['builder_provider'] ?? 'claude_cli') as BuilderProvider,\n ...(typeof recorded['builder_url'] === 'string'\n ? { builder_url: recorded['builder_url'] }\n : {}),\n ...(recorded['builder_max_steps'] === undefined\n ? {}\n : { builder_max_steps: Number(recorded['builder_max_steps']) }),\n ...(recorded['builder_max_tool_calls'] === undefined\n ? {}\n : { builder_max_tool_calls: Number(recorded['builder_max_tool_calls']) }),\n // Null when the run left it unset, as any run before it was recorded did.\n ...(typeof recorded['builder_max_output_tokens'] === 'number'\n ? { builder_max_output_tokens: recorded['builder_max_output_tokens'] }\n : {}),\n // Null (off) when the run left it unset, as any run before it was recorded did.\n ...(typeof recorded['builder_trim_history'] === 'number'\n ? { builder_trim_history: recorded['builder_trim_history'] }\n : {}),\n critic_model: String(recorded['critic_model']),\n critic_provider: (recorded['critic_provider'] ?? 'claude_cli') as CriticProvider,\n ...(typeof recorded['critic_url'] === 'string' ? { critic_url: recorded['critic_url'] } : {}),\n builder_permission_mode: recorded['builder_permission_mode'] as BuilderPermissionMode,\n critic:\n recorded['critic_preset'] === 'custom'\n ? String(recorded['critic_prompt_path'])\n : String(recorded['critic_preset']),\n max_iterations: Number(recorded['max_iterations']),\n max_cost_usd: recorded['max_cost_usd'] as number | null,\n git_checkpoints: recorded['git_checkpoints'] === true,\n worktree: recorded['worktree'] === true,\n discard_worktree: recorded['discard_worktree'] === true,\n ...(Array.isArray(recorded['gate_paths'])\n ? { gate_paths: recorded['gate_paths'] as string[] }\n : {}),\n fail_on_gate_edit: recorded['fail_on_gate_edit'] === true,\n ...(recorded['sandbox_image'] === undefined\n ? {}\n : { sandbox_image: recorded['sandbox_image'] as string }),\n ...(typeof recorded['state_dir'] === 'string' ? { state_dir: recorded['state_dir'] } : {}),\n };\n\n const state: LoopState = {\n iteration: completed,\n iteration_started_at: new Date().toISOString(),\n feedback,\n verdict: null,\n unmet_criteria: [],\n ...archived_round(run, completed),\n // Re-measured by the resumed run's first `build` step, against a baseline\n // captured at resume — a resumed run reports what it changes from there.\n changes: null,\n critic: null,\n total_usage: summary?.total_usage ?? EMPTY_USAGE,\n total_cost_usd: summary?.total_cost_usd ?? 0,\n builder_cost_usd: summary?.builder_cost_usd ?? 0,\n critic_cost_usd: summary?.critic_cost_usd ?? 0,\n check_duration_ms: summary?.check_duration_ms ?? 0,\n // An older volley's summary has no count.\n builder_max_steps_hits: summary?.builder_max_steps_hits ?? 0,\n iteration_cost_usd: 0,\n halt: null,\n cost_warned: false,\n };\n\n return {\n raw_config,\n run_id,\n started_at: String(recorded['started_at']),\n state,\n iterations_completed: completed,\n config_signed: signed,\n };\n}\n","/**\n * Enriched run summary (the run's `summary.json`): the `RunResult` projection plus\n * a `comparison` block that makes the two blessed examples' runs diff-able.\n * The block gathers the seven comparison metrics — transport,\n * iterations-to-converge, wall-clock, cost, verdict, the deterministic check\n * trajectory, and the local salvage rate — into one self-contained surface so\n * the model-vs-transport write-up (verification §4) reads them from a single\n * object rather than re-deriving them from the per-iteration archive.\n *\n * This is the only writer of `summary.json`; the flow's `record` step calls it\n * every iteration (status `running`, `completed_at` still null), the orchestrator\n * once more with the final status, and — when a `--worktree` run's work was\n * salvaged onto its branch rather than integrated — a third time, to stamp the\n * surviving branch on `salvaged_branch`, which teardown only names after the\n * final status is known.\n * Each write recomputes the comparison from what is currently archived under\n * the run's `iterations/`, so the trajectory grows as the run does.\n */\nimport { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';\nimport type {\n BuilderProvider,\n CriticProvider,\n DegradeCause,\n ResolvedConfig,\n RunResult,\n Verdict,\n} from './types.js';\nimport { state_path } from './workspace.js';\n\n/** How a role reached the model. volley stays on the `ai_sdk` transport for the\n * local providers (fascicle 0.14.0 defaults `transport` to `'ai_sdk'`, so\n * volley sets no field); `openrouter` runs on fascicle's `native` transport\n * (`src/engine.ts` sets it); `claude_cli` drives Claude through its own CLI\n * subprocess, not an ai-sdk transport at all. Recording each keeps the\n * transport a clean second variable in the comparison (model vs transport). */\nexport type Transport = 'ai_sdk' | 'native' | 'claude_cli';\n\nexport function transport_of(provider: BuilderProvider | CriticProvider): Transport {\n switch (provider) {\n case 'claude_cli':\n return 'claude_cli';\n case 'openrouter':\n return 'native';\n case 'ollama':\n case 'lmstudio':\n return 'ai_sdk';\n }\n}\n\n/** One iteration's deterministic-gate outcome, in run order. */\nexport type CheckTrajectoryPoint = {\n iteration: number;\n ran: boolean;\n ok: boolean;\n failing_slots: string[];\n};\n\n/** Run-level salvage aggregate (a health metric): the share of builder tool\n * calls recovered from assistant text rather than returned structurally. A high\n * rate on a local run means the model's native tool-call encoding is drifting\n * from its runtime's parser. `rate` is 0 when the builder made no tool calls\n * (the `claude_cli` builder runs its own loop and reports none). */\nexport type SalvageStats = {\n tool_calls: number;\n salvaged_tool_calls: number;\n rate: number;\n};\n\n/** The self-contained comparison surface the two blessed examples are read\n * through. Cost and verdict echo the `RunResult` top level on\n * purpose — this block is the single object the write-up diffs, so it carries\n * every comparison metric rather than pointing back out for some of them. */\nexport type ComparisonSummary = {\n /** Null for a critique, which has no builder. */\n builder_transport: Transport | null;\n critic_transport: Transport;\n /** The iteration the run converged on (check green + critic approved); null\n * when it never converged (budget/cap/interrupt/error). */\n iterations_to_converge: number | null;\n /** Total wall-clock across the run; null until `completed_at` is stamped. */\n wall_clock_ms: number | null;\n total_cost_usd: number;\n builder_cost_usd: number;\n critic_cost_usd: number;\n final_verdict: Verdict | null;\n check_trajectory: CheckTrajectoryPoint[];\n local_salvage: SalvageStats;\n /** Every gate path any iteration's builder edited — the tests, fixtures, and\n * check configuration that decide whether its own work passes (`src/changes.ts`).\n * Empty on a run that only touched the implementation, which is the shape of\n * the by-hand verification `research/reckon-local-run-finding.md` recommends\n * making routine: a green check plus an empty list is worth more than a green\n * check alone. Sorted and de-duplicated across iterations. */\n gate_edits: string[];\n /** What the critic still judged unmet when the run stopped — the last\n * iteration's `unmet_criteria`, verbatim. Empty on a converged run. This is the\n * \"why not\" a non-success status alone cannot give: `budget_exhausted` says the\n * run ran out of iterations, not what it was still missing. */\n unmet_criteria: string[];\n /** Any iteration's critic verdict was rendered by the tool-less fallback:\n * the tool-bearing critique kept dying on the provider's stream, so\n * the critic judged without read access — real, but shallower. The run's\n * headline honesty flag, and the \"degraded\" column the matrix runner\n * reads straight from this block. */\n critic_degraded: boolean;\n /** Why the degraded verdicts degraded, each cause once, in the order the\n * iterations first hit it. Empty when no verdict degraded. Additive. */\n critic_degrade_causes: DegradeCause[];\n};\n\n/** `RunResult` plus the comparison block; the run's `summary.json` mirrors this. */\nexport type RunSummary = RunResult & { comparison: ComparisonSummary };\n\n/** The subset of an archived per-iteration summary (written by\n * `archive_iteration`) the comparison block reads. Every field is optional so a\n * half-written or older archive degrades to zeros/empties rather than throwing. */\ntype IterationArchive = {\n iteration?: number;\n builder?: { tool_calls?: number; salvaged_tool_calls?: number } | null;\n check?: { ran?: boolean; ok?: boolean; failing_slots?: string[] } | null;\n changes?: { gate_edits?: string[] } | null;\n critic?: { critic_degraded?: boolean; degrade_cause?: DegradeCause } | null;\n unmet_criteria?: string[];\n};\n\n/** Read the archived per-iteration summaries in order. A missing archive root\n * (a run that failed before the first `record`) or an unreadable entry yields an\n * empty/short list — the run summary still writes, just without that trajectory\n * detail. */\nfunction read_iteration_archives(config: ResolvedConfig): IterationArchive[] {\n const root = state_path(config, 'iterations');\n if (!existsSync(root)) return [];\n const dirs = readdirSync(root)\n .filter((dir) => /^\\d{3}$/.test(dir))\n .toSorted();\n const archives: IterationArchive[] = [];\n for (const dir of dirs) {\n const path = state_path(config, 'iterations', dir, 'summary.json');\n if (!existsSync(path)) continue;\n try {\n archives.push(JSON.parse(readFileSync(path, 'utf8')) as IterationArchive);\n } catch {\n // A torn/half-written archive is skipped, never fatal to the run summary.\n }\n }\n return archives;\n}\n\nfunction check_trajectory(archives: IterationArchive[]): CheckTrajectoryPoint[] {\n return archives.map((archive, index) => ({\n iteration: typeof archive.iteration === 'number' ? archive.iteration : index + 1,\n ran: archive.check?.ran === true,\n ok: archive.check?.ok === true,\n failing_slots: archive.check?.failing_slots ?? [],\n }));\n}\n\n/** The run degraded if any archived iteration's critic verdict came from the\n * tool-less fallback. Reads the same on-disk archives as the other\n * comparison metrics, so it grows with the run. */\nfunction any_critic_degraded(archives: IterationArchive[]): boolean {\n return archives.some((archive) => archive.critic?.critic_degraded === true);\n}\n\n/** Each distinct reason an archived critic verdict degraded. An archive from\n * before the cause was recorded reads as a stream error, the only way a verdict\n * could degrade then. */\nfunction critic_degrade_causes(archives: IterationArchive[]): DegradeCause[] {\n const causes = archives\n .filter((archive) => archive.critic?.critic_degraded === true)\n .map((archive) => archive.critic?.degrade_cause ?? 'stream_error');\n return [...new Set(causes)];\n}\n\n/** Every gate path the run's builder touched, across all iterations: an edit in\n * iteration 1 that a later iteration reverted still happened, so the run-level\n * answer is the union rather than the last iteration's list. */\nfunction all_gate_edits(archives: IterationArchive[]): string[] {\n const edits = new Set<string>();\n for (const archive of archives) {\n for (const path of archive.changes?.gate_edits ?? []) edits.add(path);\n }\n return [...edits].toSorted();\n}\n\nfunction salvage_stats(archives: IterationArchive[]): SalvageStats {\n let tool_calls = 0;\n let salvaged_tool_calls = 0;\n for (const archive of archives) {\n tool_calls += archive.builder?.tool_calls ?? 0;\n salvaged_tool_calls += archive.builder?.salvaged_tool_calls ?? 0;\n }\n return {\n tool_calls,\n salvaged_tool_calls,\n rate: tool_calls === 0 ? 0 : salvaged_tool_calls / tool_calls,\n };\n}\n\n/** Fold the comparison block onto a `RunResult`, reading the per-iteration\n * archive for the check trajectory and salvage aggregate. Pure over its inputs\n * plus the on-disk archive; `write_run_summary` persists the result. */\nexport function build_run_summary(config: ResolvedConfig, result: RunResult): RunSummary {\n const archives = read_iteration_archives(config);\n const wall_clock_ms =\n result.completed_at === null\n ? null\n : Date.parse(result.completed_at) - Date.parse(result.started_at);\n return {\n ...result,\n comparison: {\n builder_transport: config.mode === 'critique' ? null : transport_of(config.builder_provider),\n critic_transport: transport_of(config.critic_provider),\n iterations_to_converge:\n result.status === 'success' ? result.iterations_completed : null,\n wall_clock_ms,\n total_cost_usd: result.total_cost_usd,\n builder_cost_usd: result.builder_cost_usd,\n critic_cost_usd: result.critic_cost_usd,\n final_verdict: result.final_verdict,\n check_trajectory: check_trajectory(archives),\n gate_edits: all_gate_edits(archives),\n unmet_criteria: archives.at(-1)?.unmet_criteria ?? [],\n local_salvage: salvage_stats(archives),\n critic_degraded: any_critic_degraded(archives),\n critic_degrade_causes: critic_degrade_causes(archives),\n },\n };\n}\n\n/** Write the enriched summary to the run's `summary.json` (the projection the\n * examples' comparison is read from). */\nexport function write_run_summary(config: ResolvedConfig, result: RunResult): void {\n writeFileSync(\n state_path(config, 'summary.json'),\n `${JSON.stringify(build_run_summary(config, result), null, 2)}\\n`,\n );\n}\n","/**\n * The step bodies behind the nodes of `./flow.ts`, one function per node. Each\n * takes the loop's carry-state and returns the next one. The phase modules they\n * call (`./builder.ts`, `./check/`, `./critic/`) do the work; these bodies add\n * what surrounds it: the renderer lines an operator watches, change detection,\n * git checkpoints, the per-iteration archive, and the progress events a\n * trajectory reader follows the run by.\n */\nimport { aborted_error } from 'fascicle';\nimport type { RunContext, StreamChunk, ToolApprovalHandler } from 'fascicle';\nimport { run_builder } from './builder.js';\nimport type { BuilderStep, PreviousRound } from './builder.js';\nimport { collect_changes } from './changes.js';\nimport { run_checkride } from './check/checkride.js';\nimport { CHECK_REJECTED, rejected_check, run_command_check, skipped_check } from './check/command.js';\nimport { run_critic } from './critic/run.js';\nimport { command_env } from './engine.js';\nimport type { CriticStep } from './critic/run.js';\nimport { archive_iteration, run_result_from_state } from './iteration.js';\nimport type { Renderer } from './render/renderer.js';\nimport { write_run_summary } from './summary.js';\nimport { error_kind, phase_error } from './types.js';\nimport type { ChangeSet, CheckResult, LoopState, ResolvedConfig, Verdict } from './types.js';\nimport { git_checkpoint, state_root_within } from './workspace.js';\nimport { build_root } from './worktree.js';\n\n/** A round starting, emitted as the build opens it. */\nexport type RoundStartEvent = { volley: 'round_start'; round: number };\n\n/** The check starting, with the command line it runs. */\nexport type CheckStartEvent = { volley: 'check_start'; round: number; command: string };\n\n/** The check's outcome. */\nexport type CheckEndEvent = {\n volley: 'check_end';\n round: number;\n ok: boolean;\n exit_code: number | null;\n failing_slots: string[];\n duration_ms: number;\n};\n\n/** The critic's verdict, with what it still found missing, and whether it\n * came from the tool-less fallback. */\nexport type VerdictEvent = {\n volley: 'verdict';\n round: number;\n verdict: Verdict;\n feedback: string;\n unmet_criteria: string[];\n degraded: boolean;\n};\n\n/** The progress events the phases emit through `ctx.emit`, discriminated by\n * `volley`, since `ctx.emit` overwrites `kind` with `'emit'`. A CLI run's\n * trajectory keeps them for a viewer, and under acp they become the round\n * lines, the verdict thought, and the rest of what the editor shows. */\nexport type PhaseEvent = RoundStartEvent | CheckStartEvent | CheckEndEvent | VerdictEvent;\n\n/** The step id the check's card is recorded under: the check step's own, in\n * `./flow.ts`, so each round's check counts as a fresh run of it and opens a\n * card of its own. */\nexport const CHECK_STEP_ID = 'check';\n\n/** The raw call id and tool name of the check's card. The name sits outside\n * the workspace tools, so nothing dresses the card as one of theirs. */\nconst CHECK_CALL = { id: 'check', name: 'check' } as const;\n\nfunction emit(ctx: RunContext, event: PhaseEvent): void {\n ctx.emit(event);\n}\n\n/** Record one chunk of the check's card, the way `model_call` records a tool\n * call's, under a streamed run only, since nothing reads a card otherwise. */\nfunction record_check_chunk(ctx: RunContext, chunk: StreamChunk): void {\n if (ctx.streaming) ctx.trajectory.record({ kind: 'model_chunk', step_id: CHECK_STEP_ID, chunk });\n}\n\n/** The command line the check runs, or null when no check is configured. */\nfunction check_command(config: ResolvedConfig): string | null {\n if (config.check_resolved === 'checkride') return 'pnpm exec checkride --json --digest';\n if (config.check_resolved === 'command') return config.check;\n return null;\n}\n\n/** How the check runs when the caller sets it, as `volley acp` does. Left\n * out, the check runs unasked with volley's environment less the seats' keys,\n * as on the CLI. */\nexport type CheckGate = {\n /** The whole environment the check runs with, in place of volley's own less\n * the seats' keys. */\n env?: Readonly<Record<string, string>>;\n /** Asked on the check's card before each check, the way a model call asks\n * before a gated tool runs. Anything short of an allow keeps the check from\n * running, and it's recorded as failed. */\n on_approval?: ToolApprovalHandler;\n};\n\n/** What every step body closes over, fixed for the whole run. */\nexport type PhaseDeps = {\n config: ResolvedConfig;\n renderer: Renderer;\n /** The commit every iteration's change set is measured against, read after\n * the worktree exists and before the builder writes anything. Null when the\n * build root is not a git repo — then the run reports no changes at all\n * rather than guessing at them. */\n baseline: string | null;\n check?: CheckGate;\n};\n\n/** How many gate edits a warning names before it summarises the rest. */\nconst LISTED_GATE_EDITS = 5;\n\n/**\n * Say what the builder reached for, every iteration. The count is an info line;\n * a gate edit is a warning, because it is the fact that changes how much a green\n * check is worth — and the operator should hear it from the harness rather than\n * discover it in the diff afterwards (the by-hand check that\n * `research/reckon-local-run-finding.md` recommends making routine).\n */\nfunction report_changes(\n config: ResolvedConfig,\n renderer: Renderer,\n changes: ChangeSet | null,\n): void {\n if (changes === null) return;\n renderer.info(\n `changes: ${String(changes.total)} file(s) changed since the run baseline` +\n (changes.truncated ? ` (listing the first ${String(changes.files.length)})` : ''),\n );\n if (changes.gate_edits.length === 0) return;\n const hidden = changes.gate_edits.length - LISTED_GATE_EDITS;\n const listed = changes.gate_edits.slice(0, LISTED_GATE_EDITS).join(', ');\n // A critique's change has no builder behind it, as far as volley knows.\n const [who, whose, edits] =\n config.mode === 'critique'\n ? ['the change under review touches', 'whether it passes', 'the change edits']\n : ['the builder changed', 'whether its work passes', 'the builder can edit'];\n renderer.warn(\n `gate edit: ${who} ${String(changes.gate_edits.length)} file(s) that decide ` +\n `${whose} — ${listed}${hidden > 0 ? ` (+${String(hidden)} more)` : ''}. ` +\n `A green check proves less when ${edits} the gate; the critic is told about ` +\n 'this and the run summary records it.' +\n // The halt lands at the loop guard, after this iteration's check and\n // critic have had their say — so promise the outcome, not the timing.\n (config.fail_on_gate_edit\n ? ' This run will end without success (--fail-on-gate-edit, exit 8).'\n : ''),\n );\n}\n\n/** Run the configured check, checkride or a command, with the environment\n * the caller set for it, else volley's own less the seats' keys, since the\n * check runs code the builder wrote. */\nasync function execute_check(deps: PhaseDeps, abort: AbortSignal): Promise<CheckResult> {\n const { config } = deps;\n // The check gates the tree the builder actually wrote: the worktree\n // under `--worktree`, else the workspace.\n const root = build_root(config.workspace, config.worktree);\n const options = { abort, env: deps.check?.env ?? command_env(process.env) };\n return config.check_resolved === 'checkride'\n ? run_checkride({ ...options, workspace: root })\n : run_command_check({ ...options, command: config.check, workspace: root });\n}\n\n/** Whether the check may run `command`: yes, unless the caller set an\n * approval and it answers no. It asks on the check's card under the command\n * line as its tool name, which titles the prompt the way the card is titled,\n * and which names none of fascicle's gated tools, so the prompt offers Allow\n * and Reject alone, never an \"always\" that would cover the builder's commands\n * too. A stop while it asks ends the check as a stop, not a rejection. */\nasync function check_allowed(\n deps: PhaseDeps,\n command: string,\n abort: AbortSignal,\n): Promise<boolean> {\n const approve = deps.check?.on_approval;\n if (approve === undefined) return true;\n const allowed = await approve({\n tool_name: command,\n input: { command },\n tool_call_id: CHECK_CALL.id,\n step_index: 0,\n abort,\n });\n if (abort.aborted) throw new aborted_error('check aborted');\n return allowed;\n}\n\n/** Open the next iteration: advance the counter and clear every per-iteration\n * field, so nothing from the last round leaks into this one. */\nfunction next_iteration(s: LoopState): LoopState {\n return {\n ...s,\n iteration: s.iteration + 1,\n iteration_started_at: new Date().toISOString(),\n iteration_cost_usd: 0,\n builder: null,\n critic: null,\n check: null,\n verdict: null,\n unmet_criteria: [],\n };\n}\n\n/** What the builder of the iteration after `s` hears about it beyond the\n * critic's feedback: its check, and whether its builder ran out of steps. Null\n * before the first iteration. A resumed run's state carries both, read back\n * from the last archived iteration. */\nfunction previous_round(config: ResolvedConfig, s: LoopState): PreviousRound | null {\n if (s.iteration === 0) return null;\n return {\n check: s.check,\n step_limit_hit: s.builder?.finish_reason === 'max_steps' ? config.builder_max_steps : null,\n };\n}\n\n/** What changed in the build root since the baseline, reported as it's\n * measured: the count, and a warning for any gate edit. A run measures the\n * builder's work this way after every build, and a critique measures the\n * change under review the same way, so the critic is shown one shape either\n * way. */\nfunction measure_changes(deps: PhaseDeps, root: string): ChangeSet | null {\n const { config, renderer } = deps;\n const changes = collect_changes({\n root,\n baseline: deps.baseline,\n gate_patterns: config.gate_paths,\n excluded_dir: state_root_within(root, config.state_dir),\n });\n report_changes(config, renderer, changes);\n return changes;\n}\n\n/** `build`: one builder session edits the build root, then volley measures what\n * it changed and, under `--git`, checkpoints it. */\nexport async function build_phase(\n deps: PhaseDeps,\n builder: BuilderStep,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config, renderer } = deps;\n const next = next_iteration(s);\n emit(ctx, { volley: 'round_start', round: next.iteration });\n renderer.phase_start(next.iteration, 'builder');\n const built = await run_builder(\n { builder, config, warn: renderer.warn },\n next,\n previous_round(config, s),\n ctx,\n );\n renderer.phase_end(built.iteration, 'builder', true);\n renderer.cost_line(\n built.iteration,\n 'builder',\n built.builder?.cost_usd ?? null,\n built.total_cost_usd,\n );\n if (built.cost_warned && !s.cost_warned) {\n renderer.warn('cost unavailable for this phase; recording null (run totals sum what is known)');\n }\n // What the builder actually did, measured before the check runs — so the\n // check's verdict and the builder's reach are two independent facts about\n // the same iteration rather than one inferred from the other.\n const root = build_root(config.workspace, config.worktree);\n const changes = measure_changes(deps, root);\n if (config.git_checkpoints) {\n git_checkpoint(\n root,\n `volley iter ${String(built.iteration)}: build`,\n state_root_within(root, config.state_dir),\n );\n }\n return { ...built, changes };\n}\n\n/** `measure`: a critique's one round opens, and the change under review is\n * measured from the baseline, as a run measures the builder's work. */\nexport function measure_phase(deps: PhaseDeps, s: LoopState, ctx: RunContext): LoopState {\n const next = next_iteration(s);\n emit(ctx, { volley: 'round_start', round: next.iteration });\n const root = build_root(deps.config.workspace, deps.config.worktree);\n return { ...next, changes: measure_changes(deps, root) };\n}\n\n/** `skip_verify`: the build alone crossed the cost cap, so the check is recorded\n * as skipped and no critic is called — a doomed iteration spends nothing more.\n * The loop guard then halts the run on the cap. */\nexport function skip_verify_phase(deps: PhaseDeps, s: LoopState): LoopState {\n deps.renderer.warn('cost cap crossed during build; skipping check and critic');\n return { ...s, check: skipped_check('cost_cap') };\n}\n\n/** Open the check's card on a streamed run: the call's start, then the\n * command as its input, the two chunks `model_call` records for a tool call\n * before it runs. */\nfunction open_check_card(ctx: RunContext, command: string): void {\n record_check_chunk(ctx, { kind: 'tool_call_start', ...CHECK_CALL, step_index: 0 });\n record_check_chunk(ctx, { kind: 'tool_call_end', id: CHECK_CALL.id, input: { command }, step_index: 0 });\n}\n\n/** Close the check's card with its result, which the card's reader renders,\n * or with the error that stopped the check before it had one. */\nfunction close_check_card(ctx: RunContext, outcome: { result: CheckResult } | { error: unknown }): void {\n record_check_chunk(\n ctx,\n 'result' in outcome\n ? { kind: 'tool_result', id: CHECK_CALL.id, output: outcome.result, step_index: 0 }\n : {\n kind: 'tool_result',\n id: CHECK_CALL.id,\n error: {\n message: outcome.error instanceof Error ? outcome.error.message : String(outcome.error),\n },\n step_index: 0,\n },\n );\n}\n\n/** `check`: the deterministic gate over the tree the builder wrote. A check\n * that runs a command emits its start and end, and on a streamed run also\n * records its card as a tool call, so a reader of the stream shows it running\n * while it runs. When the caller set an approval, the check asks on that card\n * first, and a rejected check closes it failed and is recorded as failed. */\nexport async function check_phase(\n deps: PhaseDeps,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { config, renderer } = deps;\n renderer.phase_start(s.iteration, 'check');\n const command = check_command(config);\n if (command === null) {\n renderer.info('no deterministic check configured; loop is critic-gated only');\n return { ...s, check: skipped_check('none') };\n }\n emit(ctx, { volley: 'check_start', round: s.iteration, command });\n open_check_card(ctx, command);\n try {\n const allowed = await check_allowed(deps, command, ctx.abort);\n const result = allowed\n ? await execute_check(deps, ctx.abort)\n : rejected_check(config.check_resolved);\n close_check_card(ctx, allowed ? { result } : { error: CHECK_REJECTED });\n emit(ctx, {\n volley: 'check_end',\n round: s.iteration,\n ok: result.ok,\n exit_code: result.exit_code,\n failing_slots: result.failing_slots,\n duration_ms: result.duration_ms,\n });\n renderer.phase_end(\n s.iteration,\n 'check',\n result.ok,\n !allowed\n ? 'rejected'\n : result.failing_slots.length > 0\n ? `failing: ${result.failing_slots.join(', ')}`\n : undefined,\n );\n return {\n ...s,\n check: result,\n check_duration_ms: s.check_duration_ms + result.duration_ms,\n };\n } catch (err) {\n close_check_card(ctx, { error: err });\n if (error_kind(err) === 'check_error') throw err;\n throw phase_error('check', s.iteration, err);\n }\n}\n\n/** `critique`: the read-only critic's verdict, feedback, and unmet criteria. */\nexport async function critique_phase(\n deps: PhaseDeps,\n critic: CriticStep,\n s: LoopState,\n ctx: RunContext,\n): Promise<LoopState> {\n const { renderer } = deps;\n renderer.phase_start(s.iteration, 'critic');\n const critiqued = await run_critic({ critic, config: deps.config }, s, ctx);\n if (critiqued.verdict !== null) {\n emit(ctx, {\n volley: 'verdict',\n round: critiqued.iteration,\n verdict: critiqued.verdict,\n feedback: critiqued.feedback ?? '',\n unmet_criteria: critiqued.unmet_criteria,\n degraded: critiqued.critic?.critic_degraded === true,\n });\n }\n renderer.phase_end(\n critiqued.iteration,\n 'critic',\n critiqued.verdict === 'approved',\n critiqued.verdict ?? undefined,\n );\n renderer.cost_line(\n critiqued.iteration,\n 'critic',\n critiqued.critic?.cost_usd ?? null,\n critiqued.total_cost_usd,\n );\n return critiqued;\n}\n\n/** `record`: archive the iteration and rewrite the run summary, so the on-disk\n * state is consistent after every round (resume reads it back). */\nexport function record_phase(deps: PhaseDeps, s: LoopState): LoopState {\n const { config } = deps;\n archive_iteration(config, s);\n write_run_summary(config, run_result_from_state(config, s, 'running', null));\n if (config.git_checkpoints) {\n const root = build_root(config.workspace, config.worktree);\n git_checkpoint(\n root,\n `volley iter ${String(s.iteration)}: critique (${s.verdict ?? 'skipped'})`,\n state_root_within(root, config.state_dir),\n );\n }\n return s;\n}\n","/**\n * What a volley turn reads from the editor's thread, and what it shows there.\n *\n * In: the turn's task is the conversation so far, oldest first, then the new\n * prompt. A stopped turn says so where it stopped, an earlier prompt's\n * attached files shrink to a line naming each (they are still on disk), and\n * an earlier reply keeps only its end, where the run's summary sits.\n *\n * Out: `progress_updates` wraps fascicle's `to_session_updates`, so every\n * event still reaches it, and adds what volley's own events say:\n *\n * round_start a **Round N** line in the reply\n * the check's chunks the card fascicle opens, given the look of a command:\n * titled with the command line, closed with its output\n * verdict a thought: the verdict, the feedback, the unmet criteria\n * summary the turn's last message: how the run ended, or failed\n *\n * `check_start` and `check_end` add nothing here, since the card says both.\n */\nimport { StringDecoder } from 'node:string_decoder';\nimport type { TrajectoryEvent, TrajectoryLogger } from 'fascicle';\nimport { to_session_updates } from 'fascicle/acp';\nimport type { AcpHistoryEntry, AcpMapperState, AcpTurn } from 'fascicle/acp';\nimport type { CheckrideSummary } from './check/checkride.js';\nimport { CHECK_STEP_ID } from './phases.js';\nimport type { PhaseEvent, VerdictEvent } from './phases.js';\nimport type { RunSummary } from './summary.js';\nimport { error_kind } from './types.js';\nimport type { CheckResult, PhaseError, RunStatus, Verdict, VolleyPhase } from './types.js';\n\ntype SessionUpdate = ReturnType<typeof to_session_updates>[number];\n\n/** How a run that returned ended, read from its summary: whether it\n * converged, in how many rounds, with what last verdict, and what the editor\n * hears nowhere else (the unmet criteria, gate edits, a degraded verdict),\n * since stderr reaches only the agent log. */\nexport type FinishedSummary = {\n volley: 'summary';\n outcome: 'finished';\n status: RunStatus;\n rounds: number;\n verdict: Verdict | null;\n unmet_criteria: string[];\n gate_edits: string[];\n critic_degraded: boolean;\n};\n\n/** How a run that threw failed: the round it reached, the phase that threw,\n * when the error names one, and what went wrong. */\nexport type FailedSummary = {\n volley: 'summary';\n outcome: 'failed';\n round: number;\n phase: VolleyPhase | null;\n error: string;\n};\n\ntype SummaryEvent = FinishedSummary | FailedSummary;\n\n/** Everything volley emits that this module reads. */\ntype ProgressEvent = PhaseEvent | SummaryEvent;\n\n/** What the model reads after the last text of a turn the user stopped, in\n * fascicle's acp-agent wording. */\nconst STOPPED = '[The user stopped this turn here. Leave what it asked for unless they ask again.]';\n\n/** How much of an earlier reply the task keeps: its end, where the summary sits. */\nexport const AGENT_TAIL_CHARS = 2000;\n\n/** The most of the check's output a card shows, as `run_command` cuts its own. */\nexport const CHECK_OUTPUT_LIMIT_BYTES = 32_000;\n\n/** Where a turn's attached files start: fascicle puts each file's\n * `<context ref=\"…\">` block after the prompt, a blank line before each. */\nconst FIRST_CONTEXT = '\\n\\n<context ref=\"';\n\n/** The seam between two attached files' blocks. A file's own text can hold a\n * `</context>`, so a block ends only where the next one starts. */\nconst CONTEXT_SEAM = /\\n<\\/context>\\n\\n(?=<context ref=\")/;\n\nconst VERDICT_WORDS: Record<Verdict, string> = {\n approved: 'approved',\n changes_requested: 'changes requested',\n};\n\nconst PHASE_WORDS: Record<VolleyPhase, string> = {\n builder: 'the build',\n check: 'the check',\n critic: 'the critique',\n};\n\nfunction rounds(count: number): string {\n return `${String(count)} ${count === 1 ? 'round' : 'rounds'}`;\n}\n\nfunction verdict_words(verdict: Verdict | null): string {\n return verdict === null ? 'none' : VERDICT_WORDS[verdict];\n}\n\nfunction bullets(items: readonly string[]): string {\n return items.map((item) => `- ${item}`).join('\\n');\n}\n\n/** An earlier prompt without its attached files' text, and a line naming each. */\nfunction without_context(text: string): string {\n const start = text.indexOf(FIRST_CONTEXT);\n if (start === -1) return text;\n const refs = text\n .slice(start + 2)\n .split(CONTEXT_SEAM)\n .map((block) => `[attached: ${/^<context ref=\"([^\"]*)\">/.exec(block)?.[1] ?? 'a file'}]`);\n return [text.slice(0, start), ...refs].join('\\n');\n}\n\n/** An earlier reply's end, marked as cut when it was. */\nfunction agent_tail(text: string): string {\n return text.length <= AGENT_TAIL_CHARS ? text : `…${text.slice(-AGENT_TAIL_CHARS)}`;\n}\n\nfunction history_entry(entry: AcpHistoryEntry): string {\n const said =\n entry.role === 'user'\n ? `User: ${without_context(entry.text)}`\n : `Volley: ${agent_tail(entry.text)}`;\n return entry.cancelled === true ? `${said}\\n\\n${STOPPED}` : said;\n}\n\n/** A turn's task, and its criteria: the conversation so far, then the new\n * prompt with its attached files whole. A first turn is its prompt alone. */\nexport function turn_task(turn: AcpTurn): string {\n if (turn.history.length === 0) return turn.text;\n return [\n 'The conversation so far, oldest first:',\n ...turn.history.map(history_entry),\n 'The request now:',\n turn.text,\n ].join('\\n\\n');\n}\n\n/** The summary of a run that returned. */\nexport function summary_event(summary: RunSummary): FinishedSummary {\n return {\n volley: 'summary',\n outcome: 'finished',\n status: summary.status,\n rounds: summary.iterations_completed,\n verdict: summary.final_verdict,\n unmet_criteria: summary.comparison.unmet_criteria,\n gate_edits: summary.comparison.gate_edits,\n critic_degraded: summary.comparison.critic_degraded,\n };\n}\n\nfunction message_of(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** The summary of a run that threw in `round` (0 before the first). A phase\n * error names its phase and carries the error underneath, which is the part\n * worth saying; a check error comes from the check. */\nexport function failure_event(err: unknown, round: number): FailedSummary {\n const kind = error_kind(err);\n if (kind === 'phase_error') {\n const { phase, cause } = err as PhaseError;\n return { volley: 'summary', outcome: 'failed', round, phase, error: message_of(cause) };\n }\n const phase = kind === 'check_error' ? 'check' : null;\n return { volley: 'summary', outcome: 'failed', round, phase, error: message_of(err) };\n}\n\n/** `sink`, and the last round a run started while recording through it, read\n * off its `round_start` events as they pass. */\nexport function follow_rounds(sink: TrajectoryLogger): {\n sink: TrajectoryLogger;\n round: () => number;\n} {\n let round = 0;\n return {\n sink: {\n ...sink,\n record: (event) => {\n if (event.kind === 'emit' && event['volley'] === 'round_start') {\n const started = event['round'];\n if (typeof started === 'number') round = started;\n }\n sink.record(event);\n },\n },\n round: () => round,\n };\n}\n\n/** Text in a `console` code block whose fence outruns any backticks that\n * open one of its lines, so nothing the check printed can close it early. */\nfunction console_block(text: string): string {\n const longest = Math.max(2, ...Array.from(text.matchAll(/^`+/gm), ([run]) => run.length));\n const fence = '`'.repeat(longest + 1);\n return `${fence}console\\n${text}\\n${fence}`;\n}\n\n/** At most `CHECK_OUTPUT_LIMIT_BYTES` of `text`, with a marker when it was\n * cut. A cut inside a character drops its partial bytes. */\nfunction cut(text: string): string {\n const size = Buffer.byteLength(text);\n if (size <= CHECK_OUTPUT_LIMIT_BYTES) return text;\n const kept = new StringDecoder('utf8').write(\n Buffer.from(text).subarray(0, CHECK_OUTPUT_LIMIT_BYTES),\n );\n return `${kept}\\n[output cut at ${String(CHECK_OUTPUT_LIMIT_BYTES)} bytes of ${String(size)}]`;\n}\n\n/** checkride's run as text: each slot and how it went, then each failing\n * slot's own output. */\nfunction checkride_text(result: CheckResult): string {\n const checks = (result.summary as CheckrideSummary | undefined)?.checks ?? [];\n const slots = checks\n .map((check) => `${check.skipped === true ? 'skip' : check.ok ? 'ok ' : 'FAIL'} ${check.name}`)\n .join('\\n');\n const outputs = result.detail.map(\n (artifact) =>\n `── ${artifact.slot} ──\\n${artifact.content.trimEnd()}` +\n (artifact.truncated ? `\\n[cut; the whole output is in ${artifact.path ?? 'the run state'}]` : ''),\n );\n return [slots, ...outputs].filter((part) => part !== '').join('\\n\\n');\n}\n\n/** What the check's card shows: what it printed, cut as `run_command`'s\n * output is, then how it exited. */\nfunction check_text(result: CheckResult): string {\n const printed = (result.runner === 'checkride' ? checkride_text(result) : (result.log ?? '')).trimEnd();\n const exit = result.exit_code === null ? '[ended by a signal]' : `[exit code ${String(result.exit_code)}]`;\n return `${printed === '' ? '[no output]' : cut(printed)}\\n${exit}`;\n}\n\nfunction as_record(value: unknown): Record<string, unknown> {\n return typeof value === 'object' && value !== null ? (value as Record<string, unknown>) : {};\n}\n\n/** One of the check card's updates, given a command's look: opened as an\n * `execute` card, titled with the command line once its input arrives, and\n * closed `completed` or `failed` with its output. A check that threw closes\n * as fascicle closes any failed call, with the error's text. */\nfunction dress_check_update(update: SessionUpdate, chunk: Record<string, unknown>): SessionUpdate {\n if (update.sessionUpdate === 'tool_call') return { ...update, kind: 'execute' };\n if (update.sessionUpdate !== 'tool_call_update') return update;\n if (chunk['kind'] === 'tool_call_end') {\n const command = as_record(chunk['input'])['command'];\n return typeof command === 'string' ? { ...update, title: command } : update;\n }\n if (chunk['kind'] !== 'tool_result' || chunk['error'] !== undefined) return update;\n const result = chunk['output'] as CheckResult;\n return {\n ...update,\n status: result.ok ? 'completed' : 'failed',\n rawOutput: { ok: result.ok, exit_code: result.exit_code, failing_slots: result.failing_slots },\n content: [{ type: 'content', content: { type: 'text', text: console_block(check_text(result)) } }],\n };\n}\n\nfunction message(text: string): SessionUpdate {\n return { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text } };\n}\n\nfunction thought(text: string): SessionUpdate {\n return { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text } };\n}\n\n/** A round's opening line, apart from the reply before it. */\nfunction round_line(round: number): string {\n return `${round === 1 ? '' : '\\n\\n'}**Round ${String(round)}**\\n\\n`;\n}\n\n/** The critic's verdict as a thought: the verdict, the feedback, and what it\n * still found missing. */\nfunction verdict_text(event: VerdictEvent): string {\n const head = `**Round ${String(event.round)} verdict: ${verdict_words(event.verdict)}**`;\n const parts = [\n event.degraded ? `${head} (judged without its tools)` : head,\n event.feedback.trim(),\n event.unmet_criteria.length > 0 ? `Unmet criteria:\\n${bullets(event.unmet_criteria)}` : '',\n ];\n return `\\n\\n${parts.filter((part) => part !== '').join('\\n\\n')}`;\n}\n\nconst ENDINGS: Partial<Record<RunStatus, (count: number) => string>> = {\n success: (count) => `**Converged** in ${rounds(count)}.`,\n budget_exhausted: (count) => `**Not converged** after ${rounds(count)}, the most this run allows.`,\n cost_cap_reached: (count) => `**Not converged**: the run reached its cost cap after ${rounds(count)}.`,\n gate_edit_blocked: (count) =>\n `**Stopped** after ${rounds(count)}: the builder edited the gate, and --fail-on-gate-edit ends the run.`,\n};\n\nfunction finished_text(event: FinishedSummary): string {\n const ending =\n ENDINGS[event.status]?.(event.rounds) ?? `**Ended ${event.status}** after ${rounds(event.rounds)}.`;\n const converged = event.status === 'success';\n return [\n `${ending} Last verdict: ${verdict_words(event.verdict)}.`,\n !converged && event.unmet_criteria.length > 0\n ? `Still unmet:\\n${bullets(event.unmet_criteria)}`\n : '',\n event.gate_edits.length > 0\n ? `The builder edited files that decide whether its work passes: ${event.gate_edits.join(', ')}.`\n : '',\n event.critic_degraded\n ? 'At least one verdict came from a critic that judged without its tools, so it saw less than usual.'\n : '',\n ]\n .filter((part) => part !== '')\n .join('\\n\\n');\n}\n\nfunction failed_text(event: FailedSummary): string {\n const where = event.round === 0 ? 'before the first round' : `in round ${String(event.round)}`;\n const during = event.phase === null ? '' : `, during ${PHASE_WORDS[event.phase]}`;\n return `**Run failed** ${where}${during}: ${event.error}`;\n}\n\n/** The turn's last message: how the run ended, or how it failed. */\nfunction summary_text(event: SummaryEvent): string {\n return `\\n\\n${event.outcome === 'finished' ? finished_text(event) : failed_text(event)}`;\n}\n\n/** An `emit` event's payload, when volley emitted it. */\nfunction progress_event(event: TrajectoryEvent): ProgressEvent | null {\n return event.kind === 'emit' && typeof event['volley'] === 'string'\n ? (event as unknown as ProgressEvent)\n : null;\n}\n\nfunction progress_of(event: ProgressEvent): SessionUpdate[] {\n switch (event.volley) {\n case 'round_start':\n return [message(round_line(event.round))];\n case 'verdict':\n return [thought(verdict_text(event))];\n case 'summary':\n return [message(summary_text(event))];\n case 'check_start':\n case 'check_end':\n return [];\n }\n}\n\n/** volley's `to_updates`: fascicle's own mapping for every event, the check's\n * card dressed as a command, and volley's progress events added. */\nexport function progress_updates(event: TrajectoryEvent, state: AcpMapperState): SessionUpdate[] {\n const updates = to_session_updates(event, state);\n if (event.kind === 'model_chunk' && event['step_id'] === CHECK_STEP_ID) {\n const chunk = as_record(event['chunk']);\n return updates.map((update) => dress_check_update(update, chunk));\n }\n const progress = progress_event(event);\n return progress === null ? updates : [...updates, ...progress_of(progress)];\n}\n","/**\n * The seats' tool sets under `volley acp`.\n *\n * Volley's own `write_file`, `edit_file`, and `bash` set no `needs_approval`,\n * so served to an editor they would edit and run commands unasked in every\n * mode. Under acp the builder gets fascicle's workspace tools instead, whose\n * writes and `run_command` ask as the session's mode says, plus volley's\n * `finish`; the critic gets that set's three reads, which never ask. Neither\n * gets `fetch`, which would reach the network unasked.\n *\n * Both sets are built from the session itself, since fascicle keys a\n * session's cards and prompts on it: a copy would lose each edit's diff, each\n * command's terminal, and the \"always\" a prompt offers. The session holds\n * `session.cwd` alone, because volley serves no additional directories\n * (`./acp.ts`), and both sets skip volley's `IGNORED_DIRS` rather than\n * fascicle's shorter default, so a seat sees the same tree under acp as on the\n * CLI.\n *\n * The builder's commands and the check run with the agent's environment less\n * every key a seat reads, so nothing the builder writes can read them. The\n * check asks, through the session, exactly when `run_command`'s own gate would\n * ask before the same command; outside a container, with no opt-out, Auto\n * isn't offered, so that gate asks in every mode the user can pick.\n */\nimport { workspace_tools } from 'fascicle/acp';\nimport type { AcpSession } from 'fascicle/acp';\nimport type { Tool, ToolApprovalHandler } from 'fascicle';\nimport { finish_tool } from './builder/tools.js';\nimport { command_env } from './engine.js';\nimport type { CheckGate } from './phases.js';\nimport { IGNORED_DIRS } from './workspace_tools.js';\nimport type { ToolSet } from './workspace_tools.js';\n\n/** The reads the critic takes from the session's set. */\nconst CRITIC_READS: ReadonlySet<string> = new Set(['read_file', 'list_files', 'search']);\n\ntype Env = Readonly<Record<string, string | undefined>>;\n\ntype AcpToolOptions = {\n /** The agent's environment, which the builder's commands and the check run\n * with, less the seats' keys; default: the process's. */\n env?: Env;\n};\n\n/** One seat's tools, with the name of their set, which its prompt names. */\ntype AcpSeatTools = { tools: ReadonlyArray<Tool>; tool_set: ToolSet };\n\n/** Whether `tool` asks before a call with `input`. A set without the tool\n * asks, so a check never runs unasked by mistake. */\nasync function asks_before(tool: Tool | undefined, input: unknown): Promise<boolean> {\n if (tool === undefined) return true;\n const needs = tool.needs_approval;\n return typeof needs === 'function' ? needs(input) : needs === true;\n}\n\n/** What one session gives the seats and the check: the builder's six\n * workspace tools plus `finish`, asking through `session.approve`; the\n * critic's three reads out of the same set; and the check's environment,\n * the same as the builder's commands get, with an approval that asks through\n * the session exactly when the builder's `run_command` would ask before\n * running the same command. */\nexport function acp_seat_tools(\n session: AcpSession,\n options: AcpToolOptions = {},\n): {\n builder: AcpSeatTools & { on_tool_approval: ToolApprovalHandler };\n critic: AcpSeatTools;\n check: CheckGate;\n} {\n const env = command_env(options.env ?? process.env);\n const tools = workspace_tools(session, { ignore: [...IGNORED_DIRS], command_env: env });\n const run_command = tools.find((tool) => tool.name === 'run_command');\n return {\n builder: {\n tools: [...tools, finish_tool()],\n tool_set: 'acp',\n on_tool_approval: session.approve,\n },\n critic: { tools: tools.filter((tool) => CRITIC_READS.has(tool.name)), tool_set: 'acp' },\n check: {\n env,\n on_approval: async (request) =>\n (await asks_before(run_command, request.input)) ? session.approve(request) : true,\n },\n };\n}\n","/**\n * `--check` resolution: `auto` detects checkride in the workspace;\n * `none` disables the gate; anything else is a shell command — unless it is\n * recognizably checkride itself, which gets the structured runner.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { CheckMode, CheckRunnerKind } from '../types.js';\n\nfunction package_check_script_is_checkride(workspace: string): boolean {\n const path = join(workspace, 'package.json');\n if (!existsSync(path)) return false;\n try {\n const pkg = JSON.parse(readFileSync(path, 'utf8')) as {\n scripts?: Record<string, string>;\n };\n const script = pkg.scripts?.['check'];\n return typeof script === 'string' && /(^|\\s)checkride(\\s|$)/.test(script);\n } catch {\n return false;\n }\n}\n\nexport function checkride_detected(workspace: string): boolean {\n return (\n existsSync(join(workspace, 'checkride.config.json')) ||\n package_check_script_is_checkride(workspace) ||\n existsSync(join(workspace, 'node_modules', '.bin', 'checkride'))\n );\n}\n\nexport function resolve_check_runner(\n check: CheckMode,\n workspace: string,\n): CheckRunnerKind {\n if (check === 'none') return 'none';\n if (check === 'auto') {\n return checkride_detected(workspace) ? 'checkride' : 'none';\n }\n return /(^|\\s)checkride(\\s|$)/.test(check.trim()) ? 'checkride' : 'command';\n}\n","/**\n * Config resolution: merge CLI flags over an optional config file\n * over defaults, expand `@file` references, validate, and produce the\n * immutable `ResolvedConfig` that the run's `config.json` records.\n */\nimport { accessSync, constants, existsSync, readFileSync, statSync } from 'node:fs';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { randomUUID } from 'node:crypto';\nimport { DEFAULT_GATE_PATTERNS } from './changes.js';\nimport { resolve_check_runner } from './check/detect.js';\nimport { detect_containment } from './containment.js';\nimport { openrouter_api_key, SEAT_URL_PROVIDERS, takes_seat_url } from './engine.js';\nimport { config_error } from './types.js';\nimport { default_state_root, RUN_ID_PATTERN } from './workspace.js';\nimport type {\n RunMode,\n BuilderPermissionMode,\n BuilderProvider,\n CriticPreset,\n CriticProvider,\n ResolvedConfig,\n VolleyConfig,\n} from './types.js';\n\nexport const DEFAULT_BUILDER_MODEL = 'opus';\nconst DEFAULT_CRITIC_MODEL = 'opus';\nexport const DEFAULT_MAX_ITERATIONS = 10;\nexport const DEFAULT_BUILDER_MAX_STEPS = 50;\nexport const DEFAULT_BUILDER_MAX_TOOL_CALLS = 1;\nexport const DEFAULT_BUILDER_MAX_OUTPUT_TOKENS = 16384;\nexport const DEFAULT_CHECK = 'auto';\nconst DEFAULT_CRITIC = 'reviewer';\nconst DEFAULT_BUILDER_PROVIDER: BuilderProvider = 'claude_cli';\nconst DEFAULT_CRITIC_PROVIDER: CriticProvider = 'claude_cli';\nconst DEFAULT_PERMISSION_MODE: BuilderPermissionMode = 'acceptEdits';\n/** The image volley's own `Dockerfile` builds; the local-builder sandbox runs\n * it unless `--sandbox-image` / `VOLLEY_SANDBOX_IMAGE` overrides it. */\nexport const DEFAULT_SANDBOX_IMAGE = 'volley-sandbox:latest';\n\nconst BUILDER_PROVIDERS: ReadonlyArray<BuilderProvider> = [\n 'claude_cli',\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\n/** Builder providers that drive their model through volley's own tool loop —\n * a real `bash` (write + exec), wherever the model runs. Refused unless volley\n * is running inside a container (the correct blast-radius default) or the\n * operator explicitly opts out; `claude_cli` has its own permission model and\n * is exempt. */\nconst TOOL_LOOP_BUILDER_PROVIDERS: ReadonlyArray<BuilderProvider> = [\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\nconst CRITIC_PROVIDERS: ReadonlyArray<CriticProvider> = [\n 'claude_cli',\n 'ollama',\n 'lmstudio',\n 'openrouter',\n];\n\nconst CRITIC_PRESETS: ReadonlyArray<CriticPreset> = [\n 'reviewer',\n 'optimizer',\n 'researcher',\n];\n\nconst PERMISSION_MODES: ReadonlyArray<BuilderPermissionMode> = [\n 'acceptEdits',\n 'bypassPermissions',\n];\n\n/** `@path/to/file` reads the file; any other string passes through. */\nexport function expand_at_file(value: string, cwd: string): string {\n if (!value.startsWith('@')) return value;\n const path = resolve(cwd, value.slice(1));\n if (!existsSync(path)) {\n throw config_error(`file not found: ${path} (from ${value})`);\n }\n return readFileSync(path, 'utf8');\n}\n\nfunction is_critic_preset(value: string): value is CriticPreset {\n return (CRITIC_PRESETS as ReadonlyArray<string>).includes(value);\n}\n\n/** Load a `volley.config.ts` / `.js` file's default export. */\nexport async function load_config_file(path: string): Promise<VolleyConfig> {\n const abs = resolve(path);\n if (!existsSync(abs)) {\n throw config_error(`config file not found: ${abs}`);\n }\n let loaded: unknown;\n try {\n const mod = (await import(pathToFileURL(abs).href)) as {\n default?: unknown;\n };\n loaded = mod.default;\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw config_error(`failed to load config file ${abs}: ${detail}`);\n }\n if (typeof loaded !== 'object' || loaded === null) {\n throw config_error(`config file ${abs} must default-export a VolleyConfig object`);\n }\n return loaded as VolleyConfig;\n}\n\nfunction validate_workspace(workspace: string): string {\n const abs = isAbsolute(workspace) ? workspace : resolve(workspace);\n if (!existsSync(abs)) {\n throw config_error(`workspace not found: ${abs}`);\n }\n if (!statSync(abs).isDirectory()) {\n throw config_error(`workspace is not a directory: ${abs}`);\n }\n try {\n accessSync(abs, constants.W_OK);\n } catch {\n throw config_error(`workspace not writable: ${abs}`);\n }\n return abs;\n}\n\nfunction resolve_critic(\n critic: string,\n cwd: string,\n): { critic_preset: CriticPreset | 'custom'; critic_prompt_path: string | null } {\n if (is_critic_preset(critic)) {\n return { critic_preset: critic, critic_prompt_path: null };\n }\n const path = resolve(cwd, critic);\n if (!existsSync(path)) {\n throw config_error(\n `--critic must be one of ${CRITIC_PRESETS.join(', ')} or a path to a prompt file; got: ${critic}`,\n );\n }\n return { critic_preset: 'custom', critic_prompt_path: path };\n}\n\nexport type ResolveOptions = {\n cwd?: string;\n run_id?: string;\n started_at?: string;\n env?: Record<string, string | undefined>;\n /** What happens to a tool-loop builder with nothing between its commands\n * and the host (`unguarded_builder`): the CLI `refuse`s it, the default,\n * while under `volley acp` each of its commands `ask`s a person first, which\n * takes the container's place. */\n uncontained_builder?: 'refuse' | 'ask';\n /** Where the run's state goes, in place of what the config says: `volley\n * resume` passes the root it found the run under, or null for a run an older\n * volley kept in the workspace's `.volley/`, which resumes there. */\n state_dir?: string | null;\n /** A run (the default), or a critique, which has no builder or loop. */\n mode?: RunMode;\n};\n\n/** What only a builder, or the loop around it, uses, with the flag that sets\n * each: a critique has no use for any of them, so naming one is an error\n * rather than something quietly ignored. */\nconst CRITIQUE_REFUSED: ReadonlyArray<readonly [keyof VolleyConfig, string]> = [\n ['builder_model', '--builder-model'],\n ['builder_provider', '--builder-provider'],\n ['builder_url', '--builder-url'],\n ['builder_max_steps', '--builder-max-steps'],\n ['builder_max_tool_calls', '--builder-max-tool-calls'],\n ['builder_max_output_tokens', '--builder-max-output-tokens'],\n ['builder_trim_history', '--builder-trim-history'],\n ['builder_permission_mode', '--builder-permission-mode'],\n ['allow_unsandboxed_builder', '--allow-unsandboxed-builder'],\n ['sandbox_image', '--sandbox-image'],\n ['max_iterations', '--max-iterations'],\n ['max_cost_usd', '--max-cost-usd'],\n ['git_checkpoints', '--git'],\n ['worktree', '--worktree'],\n ['discard_worktree', '--discard-worktree'],\n ['fail_on_gate_edit', '--fail-on-gate-edit'],\n];\n\nfunction refuse_builder_settings(raw: VolleyConfig): void {\n for (const [field, flag] of CRITIQUE_REFUSED) {\n if (raw[field] !== undefined && raw[field] !== false) {\n throw config_error(\n `volley critique refuses ${flag} (${field}): a critique runs no builder and no loop`,\n );\n }\n }\n}\n\n/** A tool-loop builder's count: its step cap, its tool calls per turn, or\n * its output tokens per turn, with the value it takes when nothing sets it. */\ntype BuilderCount<fallback extends number | null = number> = {\n flag: string;\n env_var: string;\n fallback: fallback;\n};\n\nconst BUILDER_MAX_STEPS: BuilderCount = {\n flag: '--builder-max-steps',\n env_var: 'VOLLEY_BUILDER_MAX_STEPS',\n fallback: DEFAULT_BUILDER_MAX_STEPS,\n};\n\nconst BUILDER_MAX_TOOL_CALLS: BuilderCount = {\n flag: '--builder-max-tool-calls',\n env_var: 'VOLLEY_BUILDER_MAX_TOOL_CALLS',\n fallback: DEFAULT_BUILDER_MAX_TOOL_CALLS,\n};\n\n/** The builders whose turns are capped when nothing sets a cap: the local\n * ones, where nothing else bounds a turn. Ollama's MLX runner lets an unset\n * `num_predict` run to the model's trained context less the prompt, which is\n * how one qwen3.8 turn spent 30,847 tokens thinking. A hosted model on\n * OpenRouter has its own output limit, and a request for more than it allows\n * can be refused, so it's capped only when asked. */\nconst CAPPED_BY_DEFAULT: ReadonlyArray<BuilderProvider> = ['ollama', 'lmstudio'];\n\n/** The output cap's flag and env var, and its default for `provider`: 16k\n * tokens on a local builder, else the provider's own limit (null). */\nfunction builder_max_output_tokens_count(provider: BuilderProvider): BuilderCount<number | null> {\n return {\n flag: '--builder-max-output-tokens',\n env_var: 'VOLLEY_BUILDER_MAX_OUTPUT_TOKENS',\n fallback: CAPPED_BY_DEFAULT.includes(provider) ? DEFAULT_BUILDER_MAX_OUTPUT_TOKENS : null,\n };\n}\n\n/** The history trim's size: off unless something sets it. */\nconst BUILDER_TRIM_HISTORY: BuilderCount<null> = {\n flag: '--builder-trim-history',\n env_var: 'VOLLEY_BUILDER_TRIM_HISTORY',\n fallback: null,\n};\n\n/** A builder count's flag or config value wins over its env var, which wins\n * over the default, and either must be a positive integer. Local builder\n * only; ignored by the `claude_cli` arm. */\nfunction resolve_builder_count<fallback extends number | null>(\n value: number | undefined,\n env: Record<string, string | undefined>,\n count: BuilderCount<fallback>,\n): number | fallback {\n if (value !== undefined) return positive_count(value, value, count);\n const env_value = env[count.env_var];\n if (env_value !== undefined && env_value !== '') {\n return positive_count(Number(env_value), env_value, count);\n }\n return count.fallback;\n}\n\nfunction positive_count(\n value: number,\n original: unknown,\n count: Pick<BuilderCount, 'flag' | 'env_var'>,\n): number {\n if (!Number.isInteger(value) || value < 1) {\n throw config_error(\n `${count.flag} / ${count.env_var} must be a positive integer; got: ${String(original)}`,\n );\n }\n return value;\n}\n\n/** `--sandbox-image` (a merged flag/config value) wins over the\n * `VOLLEY_SANDBOX_IMAGE` env var, which wins over the default image. Used only\n * on the local-builder Docker sandbox path; the `claude_cli` path never\n * runs Docker. */\nfunction resolve_sandbox_image(\n raw: VolleyConfig,\n env: Record<string, string | undefined>,\n): string {\n if (raw.sandbox_image !== undefined && raw.sandbox_image !== '') {\n return raw.sandbox_image;\n }\n const env_value = env['VOLLEY_SANDBOX_IMAGE'];\n if (env_value !== undefined && env_value !== '') {\n return env_value;\n }\n return DEFAULT_SANDBOX_IMAGE;\n}\n\n/** The `--allow-unsandboxed-builder` flag/config value wins; otherwise\n * `VOLLEY_ALLOW_UNSANDBOXED_BUILDER=1` (or `=true`) opts out. Any other value\n * (incl. `0`/`false`/unset) leaves a tool-loop builder refused unless\n * contained. */\nfunction resolve_allow_unsandboxed_builder(\n raw: Pick<VolleyConfig, 'allow_unsandboxed_builder'>,\n env: Record<string, string | undefined>,\n): boolean {\n if (raw.allow_unsandboxed_builder === true) return true;\n const env_value = env['VOLLEY_ALLOW_UNSANDBOXED_BUILDER'];\n return env_value === '1' || env_value === 'true';\n}\n\n/** A seat's own model server URL (`--builder-url` / `--critic-url`), trimmed,\n * or null when unset; an empty value counts as unset, as it does for the env\n * vars it overrides. Only a provider volley reaches at a base URL takes one: on\n * a `claude_cli` seat the setting would silently do nothing, so it is refused.\n * The URL must be plain http(s), with no credentials, query, or fragment:\n * volley appends API paths to it for prewarm and the context probe, which a\n * query or fragment would break, and it is persisted and printed, which\n * credentials must never be. */\nfunction resolve_seat_url(\n seat: 'builder' | 'critic',\n value: unknown,\n provider: BuilderProvider | CriticProvider,\n): string | null {\n const setting = `--${seat}-url (${seat}_url)`;\n if (value === undefined || value === null) return null;\n if (typeof value !== 'string') {\n throw config_error(`${setting} must be a URL string; got a ${typeof value}`);\n }\n const url = value.trim();\n if (url === '') return null;\n if (!takes_seat_url(provider)) {\n const url_providers = new Intl.ListFormat('en', { type: 'disjunction' }).format(\n SEAT_URL_PROVIDERS,\n );\n throw config_error(\n `${setting} applies only to a ${seat} on ${url_providers}; ` +\n `${seat}-provider is ${provider}`,\n );\n }\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw config_error(`${setting} must be an http(s) URL; got: ${url}`);\n }\n // Checked first, so no later message echoes the credentials back.\n if (parsed.username !== '' || parsed.password !== '') {\n throw config_error(`${setting} must not carry credentials`);\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw config_error(`${setting} must be an http(s) URL; got: ${url}`);\n }\n if (parsed.search !== '' || parsed.hash !== '') {\n throw config_error(`${setting} must not carry a query or fragment; got: ${url}`);\n }\n return url;\n}\n\n/** `--state-dir` (`state_dir`): the root each run's state sits under at\n * `<root>/<run_id>/`, resolved against `cwd` so a resumed run finds the same\n * place. Unset, or empty as a seat URL may be, it's the default root,\n * `$XDG_STATE_HOME/volley`, else `~/.local/state/volley`: outside the\n * workspace, where no check that reads every file can trip over the run's own\n * feedback. */\nfunction resolve_state_dir(\n value: unknown,\n cwd: string,\n env: Record<string, string | undefined>,\n): string {\n if (value === undefined || value === null) return default_state_root(env);\n if (typeof value !== 'string') {\n throw config_error(`--state-dir (state_dir) must be a path string; got a ${typeof value}`);\n }\n const path = value.trim();\n return path === '' ? default_state_root(env) : resolve(cwd, path);\n}\n\nfunction is_writable_dir(path: string): boolean {\n try {\n if (!statSync(path).isDirectory()) return false;\n accessSync(path, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/** The run's state directory must be one volley can write: the directory\n * itself when it's there, as a contained run's mount is, else the nearest\n * directory above it, where volley creates it. Checked before any spend,\n * because otherwise the run dies as it starts on a raw EROFS or EACCES. Inside\n * the sandbox the root filesystem is read-only, so that is what an unmounted\n * run directory looks like, and the message says what to mount. */\nfunction validate_run_state_dir(dir: string, contained: boolean): void {\n let existing = dir;\n while (!existsSync(existing) && dirname(existing) !== existing) existing = dirname(existing);\n if (is_writable_dir(existing)) return;\n throw config_error(\n contained\n ? `run state directory not writable: ${dir}. Inside the sandbox, mount the run's own host ` +\n `directory there (sandbox_run_args run_state, or -v <root>/<run id>:${dir}), created on the ` +\n 'host first, and pass volley the same --run-id; or point --state-dir at a writable mount'\n : `run state directory not writable: ${dir}. Point --state-dir at a directory volley can write`,\n );\n}\n\n/** Whether a tool-loop builder's commands would reach the host with nothing in\n * between: volley isn't contained, and the operator hasn't opted out with\n * `--allow-unsandboxed-builder` or `VOLLEY_ALLOW_UNSANDBOXED_BUILDER`. */\nexport function unguarded_builder(\n raw: Pick<VolleyConfig, 'allow_unsandboxed_builder'>,\n env: Record<string, string | undefined>,\n): boolean {\n return !detect_containment(env) && !resolve_allow_unsandboxed_builder(raw, env);\n}\n\n/** A caller's run id, held to `RUN_ID_PATTERN`; none gets a fresh UUID. */\nfunction resolve_run_id(run_id: string | undefined): string {\n if (run_id === undefined) return randomUUID();\n if (!RUN_ID_PATTERN.test(run_id)) {\n throw config_error(\n `--run-id must be letters, digits, '-', and '_', starting with a letter or digit; got: ${run_id}`,\n );\n }\n return run_id;\n}\n\n/** Merge, expand, and validate a raw `VolleyConfig` into a `ResolvedConfig`.\n * `check_resolved` comes from check detection against the workspace, so the\n * SDK and the CLI resolve `auto` and a command check the same way. */\nexport function resolve_config(\n raw: VolleyConfig,\n options: ResolveOptions = {},\n): ResolvedConfig {\n const cwd = options.cwd ?? process.cwd();\n const env = options.env ?? process.env;\n // A critique runs no builder, so it reads nothing a run reads for one: the\n // builder's settings are refused, its env vars go unread, and its seat keeps\n // the defaults.\n const critique = options.mode === 'critique';\n if (critique) refuse_builder_settings(raw);\n const builder_env = critique ? {} : env;\n\n const has_prompt = typeof raw.prompt === 'string' && raw.prompt.length > 0;\n if (!has_prompt && !critique) {\n throw config_error('missing required option: --prompt');\n }\n if (typeof raw.workspace !== 'string' || raw.workspace.length === 0) {\n throw config_error('missing required option: --workspace');\n }\n if (typeof raw.criteria !== 'string' || raw.criteria.length === 0) {\n throw config_error('missing required option: --criteria');\n }\n\n const workspace = validate_workspace(resolve(cwd, raw.workspace));\n const prompt = has_prompt ? expand_at_file(raw.prompt, cwd) : '';\n const criteria = expand_at_file(raw.criteria, cwd);\n\n const max_iterations = raw.max_iterations ?? (critique ? 1 : DEFAULT_MAX_ITERATIONS);\n if (!Number.isInteger(max_iterations) || max_iterations < 1) {\n throw config_error(`--max-iterations must be a positive integer; got: ${String(raw.max_iterations)}`);\n }\n\n const max_cost_usd = raw.max_cost_usd ?? null;\n if (max_cost_usd !== null && !(typeof max_cost_usd === 'number' && max_cost_usd > 0)) {\n throw config_error(`--max-cost-usd must be a positive number; got: ${String(raw.max_cost_usd)}`);\n }\n\n const builder_permission_mode = raw.builder_permission_mode ?? DEFAULT_PERMISSION_MODE;\n if (!PERMISSION_MODES.includes(builder_permission_mode)) {\n throw config_error(\n `--builder-permission-mode must be one of ${PERMISSION_MODES.join(', ')}; got: ${String(raw.builder_permission_mode)}`,\n );\n }\n\n const { critic_preset, critic_prompt_path } = resolve_critic(\n raw.critic ?? DEFAULT_CRITIC,\n cwd,\n );\n\n const builder_provider = raw.builder_provider ?? DEFAULT_BUILDER_PROVIDER;\n if (!BUILDER_PROVIDERS.includes(builder_provider)) {\n throw config_error(\n `--builder-provider must be one of ${BUILDER_PROVIDERS.join(', ')}; got: ${String(raw.builder_provider)}`,\n );\n }\n\n // Safety gate: a tool-loop builder gets a real `bash` (write + exec), local\n // model or hosted, so refuse it — before any model spend — unless volley is\n // running *inside* a container (the correct blast-radius default) or the\n // operator explicitly opts out to run uncontained on the host. Under acp,\n // a person approves each command instead, so nothing is refused here.\n const allow_unsandboxed_builder = resolve_allow_unsandboxed_builder(raw, builder_env);\n const contained = detect_containment(env);\n if (\n TOOL_LOOP_BUILDER_PROVIDERS.includes(builder_provider) &&\n options.uncontained_builder !== 'ask' &&\n unguarded_builder(raw, builder_env)\n ) {\n throw config_error(\n `builder-provider '${builder_provider}' runs volley's tool loop with a real bash ` +\n `(write + exec) — refused unless contained. Launch volley inside its sandbox container ` +\n `(docker run <hardened flags> <image> volley run …, which sets VOLLEY_CONTAINED=1), or pass ` +\n `--allow-unsandboxed-builder (VOLLEY_ALLOW_UNSANDBOXED_BUILDER=1) to run uncontained on the host.`,\n );\n }\n\n const builder_max_steps = resolve_builder_count(raw.builder_max_steps, builder_env, BUILDER_MAX_STEPS);\n const builder_max_tool_calls = resolve_builder_count(\n raw.builder_max_tool_calls,\n builder_env,\n BUILDER_MAX_TOOL_CALLS,\n );\n const builder_max_output_tokens = resolve_builder_count(\n raw.builder_max_output_tokens,\n builder_env,\n builder_max_output_tokens_count(builder_provider),\n );\n const builder_trim_history = resolve_builder_count(\n raw.builder_trim_history,\n builder_env,\n BUILDER_TRIM_HISTORY,\n );\n\n const critic_provider = raw.critic_provider ?? DEFAULT_CRITIC_PROVIDER;\n if (!CRITIC_PROVIDERS.includes(critic_provider)) {\n throw config_error(\n `--critic-provider must be one of ${CRITIC_PROVIDERS.join(', ')}; got: ${String(raw.critic_provider)}`,\n );\n }\n\n const builder_url = resolve_seat_url('builder', raw.builder_url, builder_provider);\n const critic_url = resolve_seat_url('critic', raw.critic_url, critic_provider);\n\n // An openrouter seat sends `OPENROUTER_API_KEY`, so an unset key is refused\n // here, naming the variable, before any work rather than at the first call.\n if (builder_provider === 'openrouter' || critic_provider === 'openrouter') {\n openrouter_api_key(env);\n }\n\n // Containment auth gate: `claude_cli`'s subscription/OAuth credentials\n // do not survive containerization — the token is mangled inside the container —\n // so a contained run may drive Claude only by API key (a plain env var that\n // travels the boundary). Refuse a contained `claude_cli` role (builder and/or\n // critic) that is not explicitly in `api_key` mode; the all-Claude path stays\n // on the host and Docker-free by design, where subscription auth works.\n if (contained) {\n const claude_roles = [\n builder_provider === 'claude_cli' && !critique ? 'builder' : null,\n critic_provider === 'claude_cli' ? 'critic' : null,\n ].filter((role): role is string => role !== null);\n const auth_mode = env['VOLLEY_AUTH_MODE'] ?? 'auto';\n if (claude_roles.length > 0 && auth_mode !== 'api_key') {\n throw config_error(\n `claude_cli (${claude_roles.join(', ')}) cannot use its subscription/OAuth token inside a ` +\n `container — it is mangled there. Set VOLLEY_AUTH_MODE=api_key (with ANTHROPIC_API_KEY) to ` +\n `drive Claude contained, or run claude_cli on the host uncontained.`,\n );\n }\n }\n\n if (raw.git_checkpoints === true && !existsSync(resolve(workspace, '.git'))) {\n throw config_error(`--git requires the workspace to be a git repository: ${workspace}`);\n }\n\n // A worktree is checked out from the workspace's git history, so refuse the\n // flag before any model spend when the workspace is not a repository.\n const worktree = raw.worktree ?? false;\n if (worktree && !existsSync(resolve(workspace, '.git'))) {\n throw config_error(`--worktree requires the workspace to be a git repository: ${workspace}`);\n }\n\n // `--discard-worktree`: opt in to the throw-away mode — a converged run's\n // effects go away with its branch instead of being kept on it. Only meaningful\n // under `--worktree`, so a lone flag is refused rather than silently ignored:\n // it would otherwise read as isolation the run does not have.\n const discard_worktree = raw.discard_worktree ?? false;\n if (discard_worktree && !worktree) {\n throw config_error(\n '--discard-worktree applies only to a --worktree run: there is no worktree to discard',\n );\n }\n\n // What counts as the gate is the task's call, so a config's own list replaces\n // the defaults outright rather than extending them: a test-writing task owns\n // its tests, and an empty list turns the report off entirely.\n const gate_paths = raw.gate_paths ?? DEFAULT_GATE_PATTERNS;\n if (!Array.isArray(gate_paths) || gate_paths.some((glob) => typeof glob !== 'string')) {\n throw config_error('gate_paths must be an array of glob strings');\n }\n\n const sandbox_image = resolve_sandbox_image(raw, builder_env);\n const state_dir =\n options.state_dir !== undefined ? options.state_dir : resolve_state_dir(raw.state_dir, cwd, env);\n // Each run's folder would land among the workspace's own files, where no\n // exclusion can tell earlier runs' state from the builder's work.\n if (state_dir === workspace) {\n throw config_error(`--state-dir (state_dir) can't be the workspace itself: ${workspace}`);\n }\n const run_id = resolve_run_id(options.run_id);\n // A legacy `.volley/` lives in the workspace, already checked writable.\n if (state_dir !== null) validate_run_state_dir(join(state_dir, run_id), contained);\n const check = raw.check ?? DEFAULT_CHECK;\n\n return {\n version: 2,\n run_id,\n started_at: options.started_at ?? new Date().toISOString(),\n mode: critique ? 'critique' : 'run',\n prompt,\n criteria,\n check,\n check_resolved: resolve_check_runner(check, workspace),\n builder_model: raw.builder_model ?? DEFAULT_BUILDER_MODEL,\n builder_provider,\n builder_url,\n builder_max_steps,\n builder_max_tool_calls,\n builder_max_output_tokens,\n builder_trim_history,\n allow_unsandboxed_builder,\n critic_model: raw.critic_model ?? DEFAULT_CRITIC_MODEL,\n critic_provider,\n critic_url,\n builder_permission_mode,\n critic_preset,\n critic_prompt_path,\n max_iterations,\n max_cost_usd,\n git_checkpoints: raw.git_checkpoints ?? false,\n worktree,\n discard_worktree,\n gate_paths: [...gate_paths],\n fail_on_gate_edit: raw.fail_on_gate_edit ?? false,\n sandbox_image,\n state_dir,\n workspace,\n verbose: raw.verbose ?? false,\n quiet: raw.quiet ?? false,\n json: raw.json ?? false,\n show_thinking: raw.show_thinking ?? true,\n };\n}\n","/**\n * The loop's carry-state across its life: the fresh state a run starts from,\n * the stopping rule the loop guard applies after every iteration, and the run\n * status the final state resolves to. Pure functions over `LoopState`; the\n * flow (`./flow.ts`) plugs them in.\n */\nimport { cost_cap_hit, EMPTY_USAGE } from './cost.js';\nimport type { LoopState, ResolvedConfig, RunStatus } from './types.js';\n\nexport function initial_state(): LoopState {\n return {\n iteration: 0,\n iteration_started_at: new Date().toISOString(),\n feedback: null,\n verdict: null,\n unmet_criteria: [],\n check: null,\n changes: null,\n builder: null,\n critic: null,\n total_usage: EMPTY_USAGE,\n total_cost_usd: 0,\n builder_cost_usd: 0,\n critic_cost_usd: 0,\n check_duration_ms: 0,\n builder_max_steps_hits: 0,\n iteration_cost_usd: 0,\n halt: null,\n cost_warned: false,\n };\n}\n\n/** How many rounds the loop may still run: the whole budget on a fresh run, what\n * the resumed run's completed iterations left of it otherwise. */\nexport function remaining_iterations(\n config: ResolvedConfig,\n resume_from: LoopState | null,\n): number {\n return config.max_iterations - (resume_from?.iteration ?? 0);\n}\n\n/** Did this iteration's builder edit the gate that judges it, with the operator\n * having asked for that to stop the run? Reported either way (the critic prompt\n * and the summary always carry it); only `--fail-on-gate-edit` makes it fatal. */\nfunction gate_edit_halt(config: ResolvedConfig, state: LoopState): boolean {\n return config.fail_on_gate_edit && (state.changes?.gate_edits.length ?? 0) > 0;\n}\n\n/** All stopping conditions live here: acceptance, cost cap, the gate\n * edit refusal, and — implicitly via `max_rounds` — the iteration budget.\n * Success wins when it and the cap land on the same iteration.\n *\n * A gate edit is the one condition that *beats* success rather than losing to\n * it: the run passed a check the builder had rewritten, so the pass is exactly\n * what is in question. It stops the run instead of iterating, because a model\n * that just edited the gate is not a promising candidate to be asked again. */\nexport function gate(\n config: ResolvedConfig,\n state: LoopState,\n): { stop: boolean; state: LoopState } {\n const gate_edit = gate_edit_halt(config, state);\n const success = state.check?.ok === true && state.verdict === 'approved' && !gate_edit;\n const cap = cost_cap_hit(config, state);\n const halt = gate_edit ? 'gate_edit' : !success && cap ? 'cost_cap' : null;\n return {\n stop: success || cap || gate_edit,\n state: { ...state, halt },\n };\n}\n\nexport function status_of(value: LoopState, converged: boolean): RunStatus {\n if (value.halt === 'gate_edit') return 'gate_edit_blocked';\n if (value.halt === 'cost_cap') return 'cost_cap_reached';\n return converged ? 'success' : 'budget_exhausted';\n}\n","/**\n * The volley flow: the whole topology of one run, and nothing else. Step bodies\n * live in `./phases.ts`, the model boundaries in `./builder.ts` and\n * `./critic/run.ts`, the stopping rule in `./loop_state.ts`, and the shell\n * around the flow (workspace setup, the worktree lifecycle, `run`, the final\n * summary) in `./orchestrator.ts`.\n *\n * A critique (`build_critique_flow`) is one round over a change already made,\n * so it has no builder, no loop, and no guard: `measure`, which opens the\n * round and measures the change from its baseline, then the same `check`,\n * `critique`, and `record` a run's round ends with.\n *\n * fascicle's `describe.diagram` draws the tree below from the flow itself, and\n * `test/unit/flow_diagram.test.ts` holds it to the code: change a row by changing\n * its step's `description`, then paste `pnpm diagram --prefix ' * '` over it.\n *\n * volley loop: one round per iteration, up to max_iterations\n * ├─ iteration sequence\n * │ ├─ build open the iteration, run the builder, measure the change\n * │ │ └─ builder model call: one agentic session in the build root\n * │ ├─ verify branch: did the build alone cross the cost cap?\n * │ │ ├─ then skip_verify record the check as skipped and call no critic\n * │ │ └─ else sequence\n * │ │ ├─ check the deterministic gate: checkride, a command, or none\n * │ │ └─ critique the read-only critic's verdict and feedback\n * │ │ └─ critic fallback: judge without tools if a critic on any provider but claude_cli keeps dying or runs out of steps\n * │ │ ├─ retry one more try after a stream death, on any provider but claude_cli\n * │ │ │ └─ critic_tools model call with read-only workspace tools\n * │ │ └─ pipe mark the verdict degraded\n * │ │ └─ critic_toolless model call judging from the check output and a file list\n * │ └─ record archive the iteration and rewrite the run summary\n * └─ guard gate stop on approval over a green check, the cost cap, or a gate edit\n */\nimport { branch, fallback, loop, pipe, retry, sequence, step } from 'fascicle';\nimport type { Step } from 'fascicle';\nimport { make_builder_step } from './builder.js';\nimport type { BuilderDeps } from './builder.js';\nimport type { BashExecutor } from './builder/tools.js';\nimport { cost_cap_hit } from './cost.js';\nimport {\n as_degraded,\n critic_degradable,\n critic_retryable,\n make_critic_toolless_step,\n make_critic_tools_step,\n MAX_CRITIC_RETRIES,\n toolless_critic_prompt,\n with_fallback_cause,\n with_retries,\n} from './critic/run.js';\nimport type { CriticDeps, CriticStep } from './critic/run.js';\nimport { gate, initial_state, remaining_iterations } from './loop_state.js';\nimport {\n build_phase,\n check_phase,\n critique_phase,\n measure_phase,\n record_phase,\n skip_verify_phase,\n} from './phases.js';\nimport type { PhaseDeps } from './phases.js';\nimport type { LoopState, RunInput } from './types.js';\n\n/** The builder seat: the engine its calls go through, and, when the caller\n * injects them, the tools that replace volley's own set, the name of that set\n * (which its prompt names), and the handler that answers their approval\n * requests. */\nexport type BuilderSeat = Pick<BuilderDeps, 'engine' | 'tools' | 'tool_set' | 'on_tool_approval'>;\n\n/** The critic seat: its engine and, when injected, the tools that replace its\n * reads and the name of their set. It takes no approval handler, since its\n * reads never ask. */\nexport type CriticSeat = Pick<CriticDeps, 'engine' | 'tools' | 'tool_set'>;\n\n/** What the flow is built from: the step bodies' dependencies, plus each\n * seat's model wiring and the builder's `bash` executor. The two seats share\n * one engine unless they reach one provider at different URLs. */\nexport type FlowDeps = PhaseDeps & {\n seats: { builder: BuilderSeat; critic: CriticSeat };\n /** The local builder's `bash` executor, or null for the host `spawnSync`\n * default (and for `claude_cli`, which supplies no volley tools). */\n bash_executor: BashExecutor | null;\n};\n\n/** What the flow resolves to: the final state, and whether the guard stopped the\n * loop (success, the cost cap, a gate edit) rather than the round budget. */\nexport type LoopOutcome = { value: LoopState; converged: boolean };\n\n/** The critic arm: the degradation ladder. A critic on any provider but\n * `claude_cli` whose tool-bearing stream dies is retried at once (the death is\n * stochastic parser failure, not load, so waiting buys nothing), then judged\n * once without tools. One that runs out of steps skips the retry, since\n * another identical tool loop would only run out again, and goes straight to\n * the tool-less pass. Anything else propagates from either rung untouched. */\nexport function build_critic(deps: CriticDeps): CriticStep {\n const retryable = critic_retryable(deps.config);\n return fallback(\n retry(make_critic_tools_step(deps), {\n description: 'one more try after a stream death, on any provider but claude_cli',\n max_attempts: MAX_CRITIC_RETRIES + 1,\n backoff_ms: 0,\n when: retryable,\n project: with_retries,\n }),\n pipe(make_critic_toolless_step(deps), as_degraded, {\n description: 'mark the verdict degraded',\n }),\n {\n name: 'critic',\n description: 'judge without tools if a critic on any provider but claude_cli keeps dying or runs out of steps',\n when: critic_degradable(deps.config),\n handoff: (prompt) => toolless_critic_prompt(deps.config, prompt),\n project: with_fallback_cause,\n },\n );\n}\n\n/** The steps a run and a critique share, built one way for both. */\nfunction check_step(deps: PhaseDeps): Step<LoopState, LoopState> {\n return step('check', (s: LoopState, ctx) => check_phase(deps, s, ctx), {\n description: 'the deterministic gate: checkride, a command, or none',\n });\n}\n\nfunction critique_step(deps: PhaseDeps, seat: CriticSeat): Step<LoopState, LoopState> {\n const critic = build_critic({ ...seat, config: deps.config, on_chunk: deps.renderer.critic_chunk });\n return step('critique', (s: LoopState, ctx) => critique_phase(deps, critic, s, ctx), {\n description: \"the read-only critic's verdict and feedback\",\n arm: critic,\n });\n}\n\nfunction record_step(deps: PhaseDeps): Step<LoopState, LoopState> {\n return step('record', (s: LoopState) => record_phase(deps, s), {\n description: 'archive the iteration and rewrite the run summary',\n });\n}\n\nexport function build_flow(\n deps: FlowDeps,\n resume_from: LoopState | null,\n): Step<RunInput, LoopOutcome> {\n const { config, renderer } = deps;\n\n const builder = make_builder_step({\n ...deps.seats.builder,\n config,\n on_chunk: renderer.builder_chunk,\n bash_executor: deps.bash_executor,\n });\n\n // `build` and `critique` hand their model boundary to `ctx.call` from inside\n // the body, because the prompt comes from the carried state and the result\n // folds back into it. Each declares that boundary as its `arm`, so it shows\n // up under the step in `describe` and the trajectory's flow structure.\n const build = step('build', (s: LoopState, ctx) => build_phase(deps, builder, s, ctx), {\n description: 'open the iteration, run the builder, measure the change',\n arm: builder,\n });\n const skip_verify = step('skip_verify', (s: LoopState) => skip_verify_phase(deps, s), {\n description: 'record the check as skipped and call no critic',\n });\n const check = check_step(deps);\n const critique = critique_step(deps, deps.seats.critic);\n const record = record_step(deps);\n\n const verify: Step<LoopState, LoopState> = branch({\n name: 'verify',\n description: 'did the build alone cross the cost cap?',\n when: (s: LoopState) => cost_cap_hit(config, s),\n // fascicle names this arm `then`. It holds a Step object, never a function,\n // so nothing can mistake the config for a thenable.\n // oxlint-disable-next-line unicorn/no-thenable\n then: skip_verify,\n otherwise: sequence([check, critique]),\n });\n\n const iteration: Step<LoopState, LoopState> = sequence([build, verify, record], {\n name: 'iteration',\n });\n\n return loop<RunInput, LoopState, LoopOutcome>({\n name: 'volley',\n description: 'one round per iteration, up to max_iterations',\n init: (input) => input.resume_from ?? initial_state(),\n body: iteration,\n guard: step('gate', (s: LoopState) => gate(config, s), {\n description: 'stop on approval over a green check, the cost cap, or a gate edit',\n }),\n finish: (s, { converged }) => ({ value: s, converged }),\n max_rounds: remaining_iterations(config, resume_from),\n });\n}\n\n/** What a critique's flow is built from: the step bodies' dependencies and the\n * critic seat. There's no builder seat, so no builder is ever constructed. */\nexport type CritiqueFlowDeps = PhaseDeps & { critic: CriticSeat };\n\n/** A critique: one round over a change already made. `measure` opens it and\n * measures the change from the baseline, then the check, the critic, and the\n * record, as in a run's round. No loop and no guard: there is nothing to\n * iterate on, and the caller reads the outcome off the final state. */\nexport function build_critique_flow(deps: CritiqueFlowDeps): Step<LoopState, LoopState> {\n const measure = step('measure', (s: LoopState, ctx) => measure_phase(deps, s, ctx), {\n description: 'open the round and measure the change under review',\n });\n return sequence([measure, check_step(deps), critique_step(deps, deps.critic), record_step(deps)], {\n name: 'critique_run',\n });\n}\n","/**\n * The shell around the volley flow (`./flow.ts`): set up the workspace, wrap\n * the run in the worktree lifecycle, execute the flow with a single `run` call,\n * and turn its outcome into the run summary. No hand-rolled runner — rounds,\n * abort threading, signal handlers, and cleanup order all belong to the\n * substrate.\n *\n * run_volley\n * ├─ initialize the run's state (or preserve it, on resume)\n * ├─ with_worktree off unless --worktree\n * │ ├─ capture the change baseline\n * │ ├─ run_loop run the flow (streamed when a sink is given), then the final summary\n * │ └─ integrate a successful --worktree --git run only\n * └─ report a kept checkout, or a salvaged branch (re-stamping the summary)\n *\n * run_critique\n * ├─ resolve the baseline --baseline, else HEAD; a bad revision exits 5\n * ├─ initialize the run's state\n * └─ run the critique flow one round on the critic's engine alone, then the final summary\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { run } from 'fascicle';\nimport { filesystem_logger, tee_logger } from 'fascicle/adapters';\nimport type { Engine, RunOptions, Step, TrajectoryLogger } from 'fascicle';\nimport type { BashExecutor } from './builder/tools.js';\nimport { capture_baseline, resolve_baseline } from './changes.js';\nimport { detect_containment } from './containment.js';\nimport { create_seat_engines, create_volley_engine, dispose_seat_engines } from './engine.js';\nimport type { SeatEngines } from './engine.js';\nimport { build_critique_flow, build_flow } from './flow.js';\nimport type { BuilderSeat, CriticSeat } from './flow.js';\nimport type { CheckGate } from './phases.js';\nimport { run_result_from_state } from './iteration.js';\nimport { initial_state, status_of } from './loop_state.js';\nimport { write_run_summary } from './summary.js';\nimport { trust_key_path } from './trust.js';\nimport type { Renderer } from './render/renderer.js';\nimport { config_error, error_kind } from './types.js';\nimport type { LoopState, ResolvedConfig, RunResult, RunStatus } from './types.js';\nimport {\n initialize_run_state,\n integrate_worktree,\n run_state_dir,\n state_path,\n write_resolved_config,\n} from './workspace.js';\nimport {\n build_root,\n report_worktree_fate,\n with_worktree,\n worktree_branch,\n worktree_fate,\n} from './worktree.js';\n\nexport type OrchestratorDeps = {\n renderer: Renderer;\n /** An engine to run both seats on in place of the ones built from the\n * config. It serves both seats as-is, so the seat URLs then steer only\n * volley's own requests (prewarm and the context probe), not model calls. */\n engine?: Engine;\n /** What to hand each seat in place of volley's own wiring: the builder's\n * tools and the handler that answers their approval requests, and the\n * critic's tools. A seat or a field left out keeps today's wiring, and a\n * `claude_cli` seat, which brings its own tools, takes none of it. */\n seats?: {\n builder?: Omit<BuilderSeat, 'engine'>;\n critic?: Omit<CriticSeat, 'engine'>;\n };\n /** A second sink for the run's trajectory, beside the run's\n * `trajectory.jsonl`. With one, the flow runs through `run.stream`, so the\n * sink also receives each model call's streamed chunks as `model_chunk`\n * events, which the file never keeps. */\n trajectory?: TrajectoryLogger;\n /** The environment the check runs with and the approval it asks first, in\n * place of inheriting volley's environment and running unasked. */\n check?: CheckGate;\n abort?: AbortSignal;\n install_signal_handlers?: boolean;\n};\n\nexport async function run_volley(\n config: ResolvedConfig,\n deps: OrchestratorDeps,\n resume_from: LoopState | null = null,\n): Promise<RunResult> {\n const { renderer } = deps;\n\n if (resume_from === null) {\n initialize_run_state(config);\n // Unsigned on the host only when the machine's key can't be read or made.\n if (!write_resolved_config(config) && !detect_containment(process.env)) {\n renderer.warn(\n `could not sign this run's config with this machine's key (${trust_key_path(process.env)}), ` +\n 'so resuming it here will need --trust-config',\n );\n }\n } else {\n initialize_run_state(config, { preserve: true });\n }\n renderer.info(`state: ${run_state_dir(config)}`);\n\n // Say what this run will do with its effects before it spends anything — the\n // same notice `--dry-run` prints, repeated here so a run started without a dry\n // run still hears it (the same predict-then-warn shape).\n report_worktree_fate(config, renderer);\n\n // The worktree lifecycle wraps the whole builder loop: created before the\n // first iteration, torn down after the last. Off unless `--worktree` is set\n // (config.worktree), so the default path never touches git here.\n const branch = worktree_branch(config.run_id);\n const fate = worktree_fate(config);\n const outcome = await with_worktree<RunResult>(\n {\n enabled: config.worktree,\n workspace: config.workspace,\n branch,\n log: (message) => renderer.info(message),\n // The one case teardown must keep rather than force-delete: a converged run\n // that integrated nothing, whose only copy of its work is the worktree.\n salvage: (result) => fate === 'salvage' && result.status === 'success',\n },\n async () => {\n // Whole-process containment: volley runs *inside* its hardened\n // container already — the operator/example's `docker run … <volley args>`\n // launched it — so there is no container lifecycle to orchestrate here. `bash`\n // is the local `host_bash_executor` running in-container (null executor,\n // the host `spawnSync` default) and the file tools write straight to the\n // bind-mounted worktree; the retired `docker exec` path is gone. The\n // hardened `docker run` invocation spec the example uses lives in\n // `src/sandbox.ts`.\n // The commit every iteration's change set is measured against, read after\n // the worktree exists and before the builder writes anything. Null when the\n // build root is not a git repo — then the run reports no changes at all\n // rather than guessing at them.\n const baseline = capture_baseline(build_root(config.workspace, config.worktree));\n const result = await run_loop(config, deps, resume_from, null, baseline);\n // Integration: a *successful* `--worktree --git` run squash-merges the\n // phase branch's checkpoints onto the workspace branch before teardown\n // discards it. Any non-success outcome (cost cap, budget, interrupt,\n // error) is abandoned — teardown discards the branch wholesale, nothing\n // integrated. Gated on `--git` too (`fate === 'integrate'`), so volley only\n // commits to the workspace branch when the operator opted into checkpoints;\n // without it the same work is salvaged onto its own branch instead.\n if (fate === 'integrate' && result.status === 'success') {\n integrate_worktree(config.workspace, branch, `volley run ${config.run_id}: integrate worktree (squash)`);\n renderer.info(`worktree: squash-merged ${branch} onto the workspace branch`);\n }\n return result;\n },\n );\n\n if (outcome.kept_path !== null) {\n renderer.warn(\n `worktree: could not commit this run's work onto ${branch}, so the checkout at ` +\n `${outcome.kept_path} was left standing rather than deleted — its files are intact, and ` +\n 'the next --worktree run rotates the directory aside instead of destroying it.',\n );\n }\n if (outcome.salvaged_branch === null) return outcome.value;\n renderer.info(\n `worktree: this run was not integrated; its work is preserved on branch ` +\n `${outcome.salvaged_branch} (git switch ${outcome.salvaged_branch}, or cherry-pick it).`,\n );\n // Teardown salvaged the branch *after* `run_loop` wrote the final summary, so\n // re-stamp it: the run's `summary.json` and `--json` both name the survivor.\n const salvaged: RunResult = { ...outcome.value, salvaged_branch: outcome.salvaged_branch };\n write_run_summary(config, salvaged);\n return salvaged;\n}\n\nasync function run_loop(\n config: ResolvedConfig,\n deps: OrchestratorDeps,\n resume_from: LoopState | null,\n bash_executor: BashExecutor | null,\n baseline: string | null,\n): Promise<RunResult> {\n const { renderer } = deps;\n\n // The Claude session runs in the build root (the worktree under `--worktree`),\n // because that is where the check, the change report, the checkpoints, and the\n // critic all look. The run's state stays where `state_dir` puts it either\n // way. The seats share one engine unless they reach one provider at\n // different URLs.\n const engines: SeatEngines =\n deps.engine === undefined\n ? await create_seat_engines({\n workspace: build_root(config.workspace, config.worktree),\n builder_provider: config.builder_provider,\n builder_url: config.builder_url,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n })\n : { builder: deps.engine, critic: deps.engine };\n\n const seats = {\n builder: { ...deps.seats?.builder, engine: engines.builder },\n critic: { ...deps.seats?.critic, engine: engines.critic },\n };\n const flow = build_flow(\n {\n seats,\n config,\n renderer,\n bash_executor,\n baseline,\n ...(deps.check !== undefined ? { check: deps.check } : {}),\n },\n resume_from,\n );\n\n try {\n const { value, converged } = await execute_flow(config, deps, flow, { resume_from });\n const status = status_of(value, converged);\n const result = run_result_from_state(config, value, status, new Date().toISOString());\n write_run_summary(config, result);\n return result;\n } catch (err) {\n finalize_failed_run(config, err);\n throw err;\n } finally {\n await dispose_seat_engines(engines);\n }\n}\n\n/** Run the flow into its file trajectory and, when the caller passed one, its\n * own sink. Without a sink this is the one `run` it has always been. With one,\n * it goes through `run.stream`, because only a streamed run records each model\n * call's chunks as `model_chunk` events, which are what an outer consumer maps\n * to text, tool cards, and approval prompts. The sink is that consumer, so the\n * handle's own event stream is closed at once rather than left to buffer, and\n * the file skips the chunks, so it holds the same kinds of event either way.\n *\n * The file goes first in the tee because the first sink's span ids are the\n * ones the run hands out as parents, so the file's parent links stay whole.\n * The sink sees parent ids it never issued, which costs an ACP consumer\n * nothing: it counts a step's runs by the `id` on each `span_start`. */\nfunction execute_flow<I, O>(\n config: ResolvedConfig,\n deps: Pick<OrchestratorDeps, 'trajectory' | 'abort' | 'install_signal_handlers'>,\n flow: Step<I, O>,\n input: I,\n): Promise<O> {\n const file = filesystem_logger({\n output_path: state_path(config, 'trajectory.jsonl'),\n });\n const options: RunOptions = {\n ...(deps.abort !== undefined ? { abort: deps.abort } : {}),\n ...(deps.install_signal_handlers !== undefined\n ? { install_signal_handlers: deps.install_signal_handlers }\n : {}),\n };\n if (deps.trajectory === undefined) return run(flow, input, { ...options, trajectory: file });\n const handle = run.stream(flow, input, {\n ...options,\n trajectory: tee_logger(without_model_chunks(file), deps.trajectory),\n });\n void handle.events[Symbol.asyncIterator]().return?.();\n return handle.result;\n}\n\n/** A logger that passes `inner` every event but a model call's streamed\n * chunks. */\nfunction without_model_chunks(inner: TrajectoryLogger): TrajectoryLogger {\n return {\n ...inner,\n record: (event) => {\n if (event.kind !== 'model_chunk') inner.record(event);\n },\n };\n}\n\n/** Best-effort status stamp on the run summary when the loop threw; the\n * on-disk iteration state is already consistent (record runs per round). */\nfunction finalize_failed_run(config: ResolvedConfig, err: unknown): void {\n const kind = error_kind(err);\n const cause = kind === 'phase_error' ? error_kind((err as { cause?: unknown }).cause) : null;\n const status: RunStatus =\n kind === 'aborted_error' || cause === 'aborted_error' ? 'interrupted' : 'error';\n try {\n // Preserve accumulated totals when `record` already wrote a summary.\n const summary_path = state_path(config, 'summary.json');\n const prior = existsSync(summary_path)\n ? (JSON.parse(readFileSync(summary_path, 'utf8')) as RunResult)\n : run_result_from_state(config, initial_state(), status, null);\n // A summary an older volley wrote, resumed here, has no run_state_dir\n // and no step-limit count.\n write_run_summary(config, {\n ...prior,\n builder_max_steps_hits: (prior.builder_max_steps_hits as number | undefined) ?? 0,\n run_state_dir: run_state_dir(config),\n status,\n completed_at: new Date().toISOString(),\n });\n } catch {\n // Never mask the original failure with a bookkeeping error.\n }\n}\n\n/** What a critique runs with: what a run does, less the builder's seat, plus\n * the revision its change is measured from. */\nexport type CritiqueDeps = Omit<OrchestratorDeps, 'seats'> & {\n /** The revision the change under review is measured from (`--baseline`):\n * everything that differs from it, committed or not, untracked files\n * included. HEAD when absent, so the uncommitted edits are the change. */\n baseline?: string;\n /** The critic's tools in place of volley's reads, as for a run's critic. */\n critic?: Omit<CriticSeat, 'engine'>;\n};\n\n/**\n * `volley critique`: the check and the critic, once, over a change already\n * made. No builder is constructed, and the engine serves the critic's seat\n * alone, so a critic can be measured on fixed, labeled changes without paying\n * for builder turns. It writes the state a one-round run does, with the mode\n * recorded, and ends `success` on approval over a green check, else\n * `rejected`.\n */\nexport async function run_critique(config: ResolvedConfig, deps: CritiqueDeps): Promise<RunResult> {\n if (config.mode !== 'critique') {\n throw config_error(\"run_critique needs a config resolved with mode 'critique'\");\n }\n const { renderer } = deps;\n // First, so a revision that isn't a commit fails before any state is written.\n const baseline = resolve_baseline(config.workspace, deps.baseline);\n initialize_run_state(config);\n write_resolved_config(config);\n renderer.info(`state: ${run_state_dir(config)}`);\n renderer.info(\n baseline === null\n ? 'baseline: none (not a git repository, or no commit yet); the critic reviews the tree'\n : `baseline: ${baseline}`,\n );\n\n const engine =\n deps.engine ??\n create_volley_engine({\n workspace: config.workspace,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n });\n const flow = build_critique_flow({\n config,\n renderer,\n baseline,\n critic: { ...deps.critic, engine },\n ...(deps.check !== undefined ? { check: deps.check } : {}),\n });\n try {\n const value = await execute_flow(config, deps, flow, initial_state());\n const passed = value.check?.ok === true && value.verdict === 'approved';\n const result = run_result_from_state(\n config,\n value,\n passed ? 'success' : 'rejected',\n new Date().toISOString(),\n );\n write_run_summary(config, result);\n return result;\n } catch (err) {\n finalize_failed_run(config, err);\n throw err;\n } finally {\n await engine.dispose();\n }\n}\n","/**\n * Live output renderer: consumes `StreamChunk`s from each\n * `generate` call plus volley's own phase/cost lines, and writes human\n * progress to stderr. Streaming is a display concern only — the trajectory\n * jsonl is the durable record.\n */\nimport type { StreamChunk } from 'fascicle';\nimport type { RunResult } from '../types.js';\nimport {\n GLYPH_COST,\n GLYPH_ERR,\n GLYPH_OK,\n GLYPH_PHASE_FAIL,\n GLYPH_PHASE_OK,\n GLYPH_PHASE_START,\n GLYPH_TOOL,\n VERBOSE_TRUNCATE_CHARS,\n dim,\n format_usd,\n paint,\n summarize_value,\n truncate,\n} from './format.js';\nimport type { Role } from './format.js';\n\nexport type RenderMode = 'default' | 'verbose' | 'quiet' | 'json';\n\nexport type RendererOptions = {\n mode: RenderMode;\n show_thinking: boolean;\n color: boolean;\n max_cost_usd: number | null;\n /** Where the run's trajectory is written, named when verbose output is cut\n * short (default: \"the run's trajectory.jsonl\"). */\n trajectory_path?: string;\n write?: (text: string) => void;\n};\n\nexport type Renderer = {\n builder_chunk: (chunk: StreamChunk) => void;\n critic_chunk: (chunk: StreamChunk) => void;\n phase_start: (iteration: number, phase: Role) => void;\n phase_end: (iteration: number, phase: Role, ok: boolean, detail?: string) => void;\n cost_line: (iteration: number, phase: Role, phase_cost: number | null, run_total: number) => void;\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n final_summary: (result: RunResult) => void;\n};\n\nexport function create_renderer(options: RendererOptions): Renderer {\n const write = options.write ?? ((text: string) => process.stderr.write(text));\n const { mode, color } = options;\n const see_trajectory = `see ${options.trajectory_path ?? \"the run's trajectory.jsonl\"}`;\n const silent = mode === 'json';\n const streaming = mode === 'default' || mode === 'verbose';\n\n // Tracks whether streamed prose left the cursor mid-line, so glyph lines\n // start on their own line.\n let mid_line = false;\n\n const line = (text: string): void => {\n if (silent) return;\n write(`${mid_line ? '\\n' : ''}${text}\\n`);\n mid_line = false;\n };\n\n const chunk_renderer = (role: Role) => (chunk: StreamChunk): void => {\n if (!streaming) return;\n switch (chunk.kind) {\n case 'text': {\n write(paint(role, chunk.text, color));\n mid_line = !chunk.text.endsWith('\\n');\n return;\n }\n case 'reasoning': {\n if (!options.show_thinking) return;\n write(dim(chunk.text, color));\n mid_line = !chunk.text.endsWith('\\n');\n return;\n }\n case 'tool_call_end': {\n const summary =\n mode === 'verbose'\n ? truncate(\n JSON.stringify(chunk.input, null, 2) ?? '',\n VERBOSE_TRUNCATE_CHARS,\n see_trajectory,\n )\n : summarize_value(chunk.input);\n line(`${GLYPH_TOOL} ${paint(role, chunk.id, color)} ${summary}`);\n return;\n }\n case 'tool_result': {\n const ok = chunk.error === undefined;\n if (mode === 'verbose') {\n const body = ok ? summarize_output(chunk.output) : chunk.error?.message ?? '';\n line(`${ok ? GLYPH_OK : GLYPH_ERR} ${truncate(body, VERBOSE_TRUNCATE_CHARS, see_trajectory)}`);\n } else {\n line(`${ok ? GLYPH_OK : GLYPH_ERR} ${ok ? '' : summarize_value(chunk.error?.message)}`);\n }\n return;\n }\n case 'tool_call_start': {\n line(`${GLYPH_TOOL} ${paint(role, chunk.name, color)} …`);\n return;\n }\n default:\n return;\n }\n };\n\n return {\n builder_chunk: chunk_renderer('builder'),\n critic_chunk: chunk_renderer('critic'),\n phase_start: (iteration, phase) => {\n if (mode === 'json') return;\n line(paint(phase, `${GLYPH_PHASE_START} [iter ${String(iteration)}] ${phase}`, color));\n },\n phase_end: (iteration, phase, ok, detail) => {\n if (mode === 'json') return;\n const glyph = ok ? GLYPH_PHASE_OK : GLYPH_PHASE_FAIL;\n const suffix = detail !== undefined ? ` — ${detail}` : '';\n line(paint(phase, `${glyph} [iter ${String(iteration)}] ${phase}${suffix}`, color));\n },\n cost_line: (iteration, phase, phase_cost, run_total) => {\n if (mode === 'json') return;\n const cap = options.max_cost_usd !== null ? ` / ${format_usd(options.max_cost_usd)}` : '';\n line(\n paint(\n 'cost',\n `${GLYPH_COST} [iter ${String(iteration)}] [${phase}] phase: ${format_usd(phase_cost)} | run: ${format_usd(run_total)}${cap}`,\n color,\n ),\n );\n },\n info: (message) => {\n line(message);\n },\n warn: (message) => {\n line(paint('critic', `warning: ${message}`, color));\n },\n error: (message) => {\n if (silent) {\n // Errors still surface in json mode — stderr stays human, stdout machine.\n write(`error: ${message}\\n`);\n return;\n }\n line(paint('error', `error: ${message}`, color));\n },\n final_summary: (result) => {\n if (silent) return;\n line('');\n line(`run ${result.run_id}: ${result.status}`);\n line(\n `iterations: ${String(result.iterations_completed)} | verdict: ${result.final_verdict ?? 'n/a'}`,\n );\n line(\n paint(\n 'cost',\n `${GLYPH_COST} total: ${format_usd(result.total_cost_usd)} (builder ${format_usd(result.builder_cost_usd)}, critic ${format_usd(result.critic_cost_usd)})`,\n color,\n ),\n );\n line(\n `tokens: ${String(result.total_usage.input_tokens)} in / ${String(result.total_usage.output_tokens)} out`,\n );\n line(`state: ${result.run_state_dir}`);\n },\n };\n}\n\nfunction summarize_output(output: unknown): string {\n if (typeof output === 'string') return output;\n try {\n return JSON.stringify(output) ?? '';\n } catch {\n return String(output);\n }\n}\n","/**\n * `volley acp`: volley served to an editor over the Agent Client Protocol,\n * through fascicle's `serve_acp`. Each prompt in the editor's agent panel is\n * a fresh volley run, in place, on the folder the editor has open.\n *\n * serve_acp\n * └─ per session/new: acp_turn one step, whose id no model call shares\n * └─ per prompt: run_volley on session.cwd, its state under the state root\n * ├─ builder fascicle's workspace tools + finish, asking through session.approve\n * ├─ critic that set's three reads\n * └─ trajectory the turn's own logger, so the builder's text,\n * cards, and approval prompts reach the editor\n *\n * The task is the conversation so far, then the prompt, and the run's progress\n * events become the round lines, the check's card, the verdict thought, and\n * the summary that ends the turn (`./acp_progress.ts`). A run that fails ends\n * the turn with a summary saying so, rather than as an error, which would\n * leave it out of the session's history; a stopped turn still ends cancelled.\n *\n * Outside a container, unless the operator opted out, a person approving each\n * command takes the container's place: Auto isn't offered, so every builder\n * command and every check asks first in either mode that is. Neither sees the\n * keys the seats spend, and a session reaches the folder it opened on alone.\n *\n * The flags are checked once at startup, and every config error exits 5\n * before serving, so it shows in the editor's agent log once rather than\n * failing every prompt. Stdout carries the protocol alone: the run's renderer\n * writes to stderr, and `--json` is refused.\n */\nimport { tmpdir } from 'node:os';\nimport { step } from 'fascicle';\nimport type { RunContext, Step } from 'fascicle';\nimport type { AcpMode, AcpSession, AcpStreamRoute, AcpTurn, ServeAcpConfig } from 'fascicle/acp';\nimport {\n failure_event,\n follow_rounds,\n progress_updates,\n summary_event,\n turn_task,\n} from './acp_progress.js';\nimport { acp_seat_tools } from './acp_tools.js';\nimport { resolve_config, unguarded_builder } from './config.js';\nimport { run_volley } from './orchestrator.js';\nimport type { OrchestratorDeps } from './orchestrator.js';\nimport type { CheckGate } from './phases.js';\nimport { create_renderer } from './render/renderer.js';\nimport { build_run_summary } from './summary.js';\nimport { config_error } from './types.js';\nimport type { ResolvedConfig, RunResult, VolleyConfig } from './types.js';\n\ntype Env = Record<string, string | undefined>;\n\n/** `volley acp`'s flags as config: everything but the workspace and the task,\n * which each prompt supplies. */\ntype AcpFlags = Omit<VolleyConfig, 'prompt' | 'workspace' | 'criteria'>;\n\n/** `--max-iterations` under acp. A prompt is one short exchange, which the\n * user can follow with another, and `--max-cost-usd` caps what a prompt\n * spends. */\nexport const ACP_MAX_ITERATIONS = 3;\n\n/** The seat flags `volley acp` requires, by the config field each sets. The\n * CLI's defaults (`claude_cli` on `opus`) would refuse themselves here, and a\n * default hosted model would spend money on a model the editor's entry never\n * names. */\nconst REQUIRED_SEAT_FLAGS: ReadonlyArray<readonly [keyof AcpFlags, string]> = [\n ['builder_provider', '--builder-provider'],\n ['builder_model', '--builder-model'],\n ['critic_provider', '--critic-provider'],\n ['critic_model', '--critic-model'],\n];\n\n/** The run command's options `volley acp` declares only to refuse, by the\n * config field each sets, with the reason it gives. */\nconst REFUSED_FLAGS: ReadonlyArray<readonly [keyof AcpFlags, string, string]> = [\n ['worktree', '--worktree', 'a sibling worktree sits outside the project the editor has open'],\n [\n 'git_checkpoints',\n '--git',\n 'it commits to the open repo after every phase, which no permission prompt covers',\n ],\n ['json', '--json', 'stdout carries the protocol alone'],\n];\n\n/** What the startup check resolves in place of a prompt, which no session has\n * sent yet. */\nconst STAND_IN_TASK = 'volley acp: startup check';\n\n/** Unset, or set to nothing but whitespace. Any other value goes on to\n * `resolve_config`, which says what's wrong with it. */\nfunction is_blank(value: unknown): boolean {\n return value === undefined || (typeof value === 'string' && value.trim() === '');\n}\n\n/** A refusal or a missing seat flag, as one config error. */\nfunction refuse_unservable(raw: AcpFlags): void {\n for (const [field, flag, reason] of REFUSED_FLAGS) {\n if (raw[field] === true) throw config_error(`volley acp refuses ${flag}: ${reason}`);\n }\n const missing = REQUIRED_SEAT_FLAGS.filter(([field]) => is_blank(raw[field])).map(\n ([, flag]) => flag,\n );\n if (missing.length > 0) {\n throw config_error(`volley acp requires every seat flag, and these are missing: ${missing.join(', ')}`);\n }\n if (raw.builder_provider === 'claude_cli') {\n throw config_error(\n 'volley acp refuses a claude_cli builder: the Claude CLI runs its own tools under its own ' +\n \"permission model, so its edits would never reach the editor's prompts\",\n );\n }\n}\n\n/** The flags `volley acp` was started with, with acp's default filled in:\n * three rounds. Run state goes under the default root, outside the workspace,\n * unless `--state-dir` names one, as it does for any run. Each refusal, a\n * missing seat flag, and any other config error, an unwritable state root\n * among them, throws here, before serving: the whole config resolves once\n * against the system temp directory with a stand-in task, since no session has\n * named a workspace yet. */\nexport function acp_base_config(raw: AcpFlags, env: Env = process.env): AcpFlags {\n refuse_unservable(raw);\n const base: AcpFlags = {\n ...raw,\n max_iterations: raw.max_iterations ?? ACP_MAX_ITERATIONS,\n };\n resolve_config(\n { ...base, workspace: tmpdir(), prompt: STAND_IN_TASK, criteria: STAND_IN_TASK },\n { env, uncontained_builder: 'ask' },\n );\n return base;\n}\n\n/** One prompt's run config: the base flags resolved against the session's\n * workspace, with the turn as both the task and the criteria. Those two are\n * set after resolving, because resolving reads a value that starts with `@` as\n * a file to load, and text typed in the editor is never that. */\nfunction turn_config(base: AcpFlags, workspace: string, task: string, env: Env): ResolvedConfig {\n const resolved = resolve_config(\n { ...base, workspace, prompt: STAND_IN_TASK, criteria: STAND_IN_TASK },\n { env, uncontained_builder: 'ask' },\n );\n return { ...resolved, prompt: task, criteria: task };\n}\n\n/** Only the builder's text is the reply. The critic's calls stream raw verdict\n * JSON, and nothing else in the run streams text. */\nfunction stream_route(step_id: string): AcpStreamRoute {\n return step_id === 'builder' ? 'message' : 'none';\n}\n\n/** What one session's turns share: the flags, the environment each turn's\n * config reads, the session's workspace, both seats' tools, and how the check\n * runs. */\ntype TurnDeps = {\n base: AcpFlags;\n env: Env;\n workspace: string;\n seats: NonNullable<OrchestratorDeps['seats']>;\n check: CheckGate;\n};\n\n/** One prompt: a volley run on the session's workspace, its events flowing\n * into the turn's own trajectory, then its summary as the turn's last event.\n * A failure is summarized too, naming the round it reached, and the turn ends\n * normally, so the session's history keeps the request for a retry. A turn\n * whose own signal fired rethrows, and ends cancelled. Resolves to the run's\n * result, or null when it failed. */\nasync function run_turn(deps: TurnDeps, turn: AcpTurn, ctx: RunContext): Promise<RunResult | null> {\n const rounds = follow_rounds(ctx.trajectory);\n try {\n const config = turn_config(deps.base, deps.workspace, turn_task(turn), deps.env);\n const result = await run_volley(config, {\n renderer: create_renderer({\n mode: 'quiet',\n show_thinking: false,\n color: false,\n max_cost_usd: config.max_cost_usd,\n }),\n seats: deps.seats,\n check: deps.check,\n trajectory: rounds.sink,\n abort: ctx.abort,\n install_signal_handlers: false,\n });\n ctx.emit(summary_event(build_run_summary(config, result)));\n return result;\n } catch (err) {\n if (ctx.abort.aborted) throw err;\n ctx.emit(failure_event(err, rounds.round()));\n return null;\n }\n}\n\n/** The flow for one session: both seats' tools and the check's gate are\n * built once, from the session, and each prompt runs volley on the session's\n * `cwd` with them. */\nfunction session_flow(\n base: AcpFlags,\n env: Env,\n): (session: AcpSession) => Step<AcpTurn, RunResult | null> {\n return (session) => {\n const { builder, critic, check } = acp_seat_tools(session, { env });\n const deps: TurnDeps = { base, env, workspace: session.cwd, seats: { builder, critic }, check };\n return step('acp_turn', (turn: AcpTurn, ctx) => run_turn(deps, turn, ctx), {\n description: \"one volley run on the session's workspace, per prompt\",\n });\n };\n}\n\ntype AcpServeOptions = {\n /** Reported to the client as the agent's version. */\n version: string;\n /** Where each turn's config reads its environment; default: the process's. */\n env?: Env;\n};\n\n/** The modes a session offers outside a container with no opt-out, where\n * nothing but a person stands between a command and the host: Auto, which\n * runs every command unasked, is left out. */\nconst HOST_MODES: ReadonlyArray<AcpMode> = ['manual', 'accept_edits'];\n\n/** What `serve_acp` serves: volley, per session, starting each in Manual, on\n * the folder the session opened alone, since the check, the change list, and\n * the critic look nowhere else. The builder's streamed text and volley's own\n * lines make the whole reply, ending with the summary, so `to_text` adds\n * nothing. */\nexport function acp_serve_config(\n base: AcpFlags,\n options: AcpServeOptions,\n): ServeAcpConfig<AcpTurn, RunResult | null> {\n const env = options.env ?? process.env;\n return {\n name: 'volley',\n version: options.version,\n default_mode: 'manual',\n additional_directories: false,\n ...(unguarded_builder(base, env) ? { modes: HOST_MODES } : {}),\n flow: session_flow(base, env),\n to_input: (turn) => turn,\n stream: stream_route,\n to_updates: progress_updates,\n to_text: () => '',\n };\n}\n","/**\n * Exit codes and the mapping from fascicle's error taxonomy plus\n * volley's own tagged errors onto them.\n */\nimport { error_kind } from './types.js';\nimport type { PhaseError, RunStatus } from './types.js';\n\nexport const EXIT_SUCCESS = 0;\nexport const EXIT_BUDGET_EXHAUSTED = 2;\nexport const EXIT_BUILDER_ERROR = 3;\nexport const EXIT_CHECK_ERROR = 4;\nexport const EXIT_CONFIG_ERROR = 5;\nexport const EXIT_CRITIC_ERROR = 6;\nexport const EXIT_COST_CAP = 7;\n/** The builder edited the gate that judges it and `--fail-on-gate-edit` was set:\n * distinct from a failed check (4) and from a budget exhaustion (2), because\n * nothing failed — the run refused to count a pass it could not trust. */\nexport const EXIT_GATE_EDIT = 8;\nexport const EXIT_INTERRUPTED = 130;\n\nexport function exit_code_for_status(status: RunStatus): number {\n switch (status) {\n case 'success':\n return EXIT_SUCCESS;\n case 'budget_exhausted':\n // A critique that didn't pass exits as a run that didn't converge does.\n case 'rejected':\n return EXIT_BUDGET_EXHAUSTED;\n case 'cost_cap_reached':\n return EXIT_COST_CAP;\n case 'gate_edit_blocked':\n return EXIT_GATE_EDIT;\n case 'interrupted':\n return EXIT_INTERRUPTED;\n default:\n return EXIT_BUILDER_ERROR;\n }\n}\n\n/** Error kinds fascicle raises for provider-level failures. */\nconst PROVIDER_ERROR_KINDS = new Set([\n 'provider_error',\n 'provider_auth_error',\n 'provider_not_configured_error',\n 'provider_capability_error',\n 'claude_cli_error',\n 'rate_limit_error',\n 'engine_disposed_error',\n 'timeout_error',\n]);\n\nexport function exit_code_for_error(err: unknown): number {\n const kind = error_kind(err);\n if (kind === 'aborted_error') return EXIT_INTERRUPTED;\n if (kind === 'config_error' || kind === 'engine_config_error') {\n return EXIT_CONFIG_ERROR;\n }\n if (kind === 'check_error') return EXIT_CHECK_ERROR;\n if (kind === 'schema_validation_error') return EXIT_CRITIC_ERROR;\n if (kind === 'phase_error') {\n const phase = (err as PhaseError).phase;\n const cause_kind = error_kind((err as PhaseError).cause);\n if (cause_kind === 'aborted_error') return EXIT_INTERRUPTED;\n if (phase === 'critic') return EXIT_CRITIC_ERROR;\n if (phase === 'check') return EXIT_CHECK_ERROR;\n return EXIT_BUILDER_ERROR;\n }\n if (kind !== null && PROVIDER_ERROR_KINDS.has(kind)) {\n return EXIT_BUILDER_ERROR;\n }\n return EXIT_BUILDER_ERROR;\n}\n","/**\n * `volley matrix` (v0.4.1): sweep a set of builder×critic *model*\n * combinations serially over one otherwise-fixed config, then aggregate every\n * run's `comparison` block into a single table. A subcommand — not a bash\n * wrapper around `docker run` — so it reuses `resolve_config`, the forced\n * per-combo worktree reset, and the enriched summary writer instead of\n * reimplementing them.\n *\n * Execution is serial by design: the local providers share one GPU, so\n * parallel combos would thrash the Ollama model loader. Each combo forces\n * `--worktree --discard-worktree` for a clean per-combo reset: a sweep\n * wants verdicts, not effects, so every seat's work is thrown away with its\n * branch — never salvaged onto one, never squash-merged onto the operator's\n * branch.\n *\n * **A seat is measured over `repeat` attempts, not one.** A single run answers\n * \"did this pairing converge that time\", which is the only question n=1 can\n * answer honestly: local runs are stochastic, so one sample supports a *hard*\n * failure (`research/v3-comparison-finding.md` reproduced the qwen3.6 critic\n * death 2/2) and nothing else — not iterations-to-converge, not wall clock. With\n * `--repeat` the row reports a pass *rate* and averages over the attempts behind\n * it, and every attempt's own summary is kept.\n *\n * **A row says why a seat fell off**, not just that it did. `budget_exhausted`\n * is a status, not a diagnosis; the failing check slots, the criteria still\n * unmet, a cost cap, or a gate edit are. Each is read from the attempt's\n * `comparison` block and folded into one `reason`.\n *\n * Sweep-level exit semantics: an attempt that *runs* — even to a\n * non-success status — is a *result*, shown in the table; the sweep only\n * \"breaks\" (nonzero) when an attempt yields no recoverable summary at all.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { resolve_config } from './config.js';\nimport { run_volley } from './orchestrator.js';\nimport type { Renderer } from './render/renderer.js';\nimport { build_run_summary } from './summary.js';\nimport type { RunSummary } from './summary.js';\nimport { config_error } from './types.js';\nimport type { DegradeCause, ResolvedConfig, RunStatus, Verdict, VolleyConfig } from './types.js';\nimport { state_path } from './workspace.js';\n\n/** The sweep's nonzero exit: at least one attempt produced no summary at all.\n * Distinct from an attempt that merely did not converge — that is still a\n * result and the sweep exits 0. Kept matrix-local (not a phase exit code) so the\n * existing exit-code semantics are untouched. */\nexport const EXIT_MATRIX_INCOMPLETE = 1;\n\n/** How many times each seat runs when `--repeat` is not given. One attempt is\n * enough to smoke-test a pairing and is what a quick sweep wants; anything that\n * compares seats should raise it. */\nconst DEFAULT_REPEAT = 1;\n\n/** One builder×critic model pairing in the cross product. */\nexport type MatrixCombo = { builder: string; critic: string };\n\n/** One run of one seat: what the sweep reads back from that attempt's summary.\n * `status: 'broke'` means the attempt produced no summary at all — the only\n * outcome that fails the sweep. */\nexport type MatrixAttempt = {\n attempt: number;\n status: RunStatus | 'broke';\n converged: boolean;\n iterations_to_converge: number | null;\n wall_clock_ms: number | null;\n total_cost_usd: number | null;\n final_verdict: Verdict | null;\n /** The check slots failing on the last iteration that ran one. */\n failing_slots: string[];\n /** What the critic still judged unmet when the run stopped. */\n unmet_criteria: string[];\n gate_edits: string[];\n critic_degraded: boolean;\n /** Why this attempt's degraded verdicts degraded; empty when none did. */\n critic_degrade_causes: DegradeCause[];\n tool_calls: number;\n salvaged_tool_calls: number;\n error: string | null;\n /** Why this attempt did not converge, in a few words; null when it did. */\n reason: string | null;\n};\n\n/** One table row: a seat, aggregated over its attempts, with every attempt kept\n * for `--json` consumers that want the spread rather than the average. */\nexport type MatrixRow = {\n builder: string;\n critic: string;\n /** Attempts made, and how many converged: the row's headline. */\n runs: number;\n converged: number;\n /** Mean over *converged* attempts — averaging in a run that never converged\n * would report an iteration count that never happened. Null when none did. */\n mean_iterations: number | null;\n /** Mean over every attempt that reported a wall clock, converged or not: a\n * seat that burns twenty minutes before giving up costs you that either way. */\n mean_wall_clock_ms: number | null;\n mean_cost_usd: number | null;\n /** Salvaged tool calls over total tool calls across all attempts — a ratio of\n * totals, not a mean of ratios, so a busy attempt weighs more than a quiet one. */\n salvage_rate: number | null;\n /** True when *any* attempt's critic degraded to the tool-less rung. */\n critic_degraded: boolean;\n /** Every reason any attempt's critic degraded, each once. */\n critic_degrade_causes: DegradeCause[];\n /** Every gate path any attempt's builder edited (`src/changes.ts`). */\n gate_edits: string[];\n /** The most recent non-converged attempt's reason; null when all converged. */\n reason: string | null;\n attempts: MatrixAttempt[];\n};\n\nexport type MatrixOutcome = { rows: MatrixRow[]; ok: boolean };\n\n/** Runs one attempt at one seat and returns its enriched summary. Injected in\n * tests so the cross product, repeats, persistence, and table can be exercised\n * with stubbed runs. */\nexport type ComboRunner = (\n base: VolleyConfig,\n combo: MatrixCombo,\n renderer: Renderer,\n attempt: number,\n) => Promise<RunSummary>;\n\nexport type RunMatrixOptions = {\n base: VolleyConfig;\n builders: string[];\n critics: string[];\n matrix_dir: string;\n renderer: Renderer;\n repeat?: number;\n run_combo?: ComboRunner;\n};\n\n/** Split a `--builders`/`--critics` value into a trimmed, non-empty model\n * list. Empty or all-whitespace is a config error, refused before any spend. */\nexport function parse_model_list(value: string | undefined, flag: string): string[] {\n const items = (value ?? '')\n .split(',')\n .map((item) => item.trim())\n .filter((item) => item.length > 0);\n if (items.length === 0) {\n throw config_error(`${flag} must be a comma-separated list of at least one model`);\n }\n return items;\n}\n\n/** Validate `--repeat`: attempts per seat, a positive integer. Refused before\n * any spend, like every other cap. */\nexport function parse_repeat(value: number | string | undefined): number {\n if (value === undefined) return DEFAULT_REPEAT;\n const repeat = Number(value);\n if (!Number.isInteger(repeat) || repeat < 1) {\n throw config_error(`--repeat must be a positive integer; got: ${String(value)}`);\n }\n return repeat;\n}\n\n/** The config one seat runs under: the base task with this combo's models and a\n * forced throw-away worktree — `--worktree` isolates the seat's effects and\n * `--discard-worktree` throws them away at teardown, so a sweep of N seats leaves\n * neither N branches behind nor N squash commits on the operator's branch. */\nexport function combo_config(base: VolleyConfig, combo: MatrixCombo): VolleyConfig {\n return {\n ...base,\n builder_model: combo.builder,\n critic_model: combo.critic,\n worktree: true,\n discard_worktree: true,\n };\n}\n\n/** The default combo runner: resolve this seat's config, run the loop, and fold\n * on the comparison block.\n * If the run throws (an unsalvageable phase failure), recover the best-effort\n * `summary.json` the orchestrator wrote so the attempt is still a result;\n * rethrow only when nothing is recoverable — then the sweep breaks. */\nconst default_run_combo: ComboRunner = async (base, combo, renderer) => {\n const config = resolve_config(combo_config(base, combo));\n try {\n const result = await run_volley(config, { renderer });\n return build_run_summary(config, result);\n } catch (err) {\n const recovered = read_run_summary(config);\n if (recovered === null) throw err;\n return recovered;\n }\n};\n\n/** Read a run's `summary.json` from its state directory (a base config's\n * `state_dir` moves it there), or null if it is missing/unparseable — the\n * signal `default_run_combo` uses to tell a merely-errored attempt (summary on\n * disk) from a truly broken one (nothing to recover). */\nfunction read_run_summary(config: ResolvedConfig): RunSummary | null {\n const path = state_path(config, 'summary.json');\n if (!existsSync(path)) return null;\n try {\n return JSON.parse(readFileSync(path, 'utf8')) as RunSummary;\n } catch {\n return null;\n }\n}\n\n/** How much of a criterion or an error a `reason` carries before it is cut —\n * enough to recognise which one, short enough for a table cell. */\nconst REASON_MAX = 44;\n\nfunction clip(text: string): string {\n const flat = text.replaceAll(/\\s+/g, ' ').trim();\n return flat.length > REASON_MAX ? `${flat.slice(0, REASON_MAX - 1)}…` : flat;\n}\n\n/** The check slots failing on the last iteration that ran a check. */\nfunction last_failing_slots(summary: RunSummary): string[] {\n const ran = summary.comparison.check_trajectory.filter((point) => point.ran);\n return ran.at(-1)?.failing_slots ?? [];\n}\n\n/**\n * Why this attempt did not converge, in a few words — the column that turns a\n * sweep from \"which seats passed\" into \"where each one falls off\".\n *\n * Ordered by how *specific* the answer is: a halt names itself, a failing check\n * names its slots, and a run that was gated only by the critic names what it\n * still judged unmet. `budget_exhausted` with nothing else to say means the loop\n * ran out of iterations while the critic kept asking for changes it did not\n * enumerate — worth seeing as exactly that.\n */\nexport function failure_reason(summary: RunSummary): string | null {\n if (summary.status === 'success') return null;\n if (summary.status === 'cost_cap_reached') return 'cost cap';\n if (summary.status === 'interrupted') return 'interrupted';\n if (summary.status === 'gate_edit_blocked') {\n return clip(`gate edit: ${summary.comparison.gate_edits.join(', ')}`);\n }\n const failing = last_failing_slots(summary);\n if (failing.length > 0) return clip(`check: ${failing.join(', ')}`);\n const unmet = summary.comparison.unmet_criteria;\n if (unmet.length === 1) return clip(`unmet: ${unmet[0] ?? ''}`);\n if (unmet.length > 1) return clip(`unmet: ${String(unmet.length)} criteria`);\n return summary.status === 'error' ? 'run error' : String(summary.status);\n}\n\nfunction attempt_from_summary(attempt: number, summary: RunSummary): MatrixAttempt {\n const c = summary.comparison;\n return {\n attempt,\n status: summary.status,\n converged: summary.status === 'success',\n iterations_to_converge: c.iterations_to_converge,\n wall_clock_ms: c.wall_clock_ms,\n total_cost_usd: c.total_cost_usd,\n final_verdict: c.final_verdict,\n failing_slots: last_failing_slots(summary),\n unmet_criteria: c.unmet_criteria,\n gate_edits: c.gate_edits,\n critic_degraded: c.critic_degraded,\n critic_degrade_causes: c.critic_degrade_causes,\n tool_calls: c.local_salvage.tool_calls,\n salvaged_tool_calls: c.local_salvage.salvaged_tool_calls,\n error: null,\n reason: failure_reason(summary),\n };\n}\n\nfunction broke_attempt(attempt: number, message: string): MatrixAttempt {\n return {\n attempt,\n status: 'broke',\n converged: false,\n iterations_to_converge: null,\n wall_clock_ms: null,\n total_cost_usd: null,\n final_verdict: null,\n failing_slots: [],\n unmet_criteria: [],\n gate_edits: [],\n critic_degraded: false,\n critic_degrade_causes: [],\n tool_calls: 0,\n salvaged_tool_calls: 0,\n error: message,\n reason: clip(`broke: ${message}`),\n };\n}\n\nfunction mean(values: number[]): number | null {\n if (values.length === 0) return null;\n return values.reduce((total, value) => total + value, 0) / values.length;\n}\n\nfunction defined_numbers(values: Array<number | null>): number[] {\n return values.filter((value): value is number => value !== null);\n}\n\n/** Fold a seat's attempts into one row. Every aggregate names the population it\n * is over (see `MatrixRow`), because averaging the wrong set is how a sweep\n * reports a number nothing actually did. */\nfunction aggregate_row(combo: MatrixCombo, attempts: MatrixAttempt[]): MatrixRow {\n const converged = attempts.filter((attempt) => attempt.converged);\n const tool_calls = attempts.reduce((total, attempt) => total + attempt.tool_calls, 0);\n const salvaged = attempts.reduce((total, attempt) => total + attempt.salvaged_tool_calls, 0);\n const gate_edits = new Set(attempts.flatMap((attempt) => attempt.gate_edits));\n return {\n builder: combo.builder,\n critic: combo.critic,\n runs: attempts.length,\n converged: converged.length,\n mean_iterations: mean(defined_numbers(converged.map((a) => a.iterations_to_converge))),\n mean_wall_clock_ms: mean(defined_numbers(attempts.map((a) => a.wall_clock_ms))),\n mean_cost_usd: mean(defined_numbers(attempts.map((a) => a.total_cost_usd))),\n salvage_rate: tool_calls === 0 ? null : salvaged / tool_calls,\n critic_degraded: attempts.some((attempt) => attempt.critic_degraded),\n critic_degrade_causes: [\n ...new Set(attempts.flatMap((attempt) => attempt.critic_degrade_causes)),\n ],\n gate_edits: [...gate_edits].toSorted(),\n reason: attempts.findLast((attempt) => !attempt.converged)?.reason ?? null,\n attempts,\n };\n}\n\nfunction cross_product(builders: string[], critics: string[]): MatrixCombo[] {\n return builders.flatMap((builder) => critics.map((critic) => ({ builder, critic })));\n}\n\nfunction combo_dir(matrix_dir: string, combo: MatrixCombo): string {\n return join(matrix_dir, `${slug(combo.builder)}__${slug(combo.critic)}`);\n}\n\n/** Filesystem-safe slug for a model name in a `.volley-matrix/` path (model\n * ids carry `:` and `/`, e.g. `qwen3.6:latest`). */\nfunction slug(model: string): string {\n return model.replace(/[^a-zA-Z0-9._-]/g, '_');\n}\n\n/** One attempt's run summary, copied out of the run's own state into the\n * sweep, so the sweep keeps its evidence beside its table. Every attempt gets\n * its own `run-NN/` so a repeated seat keeps all of its evidence, not just the\n * last run's. */\nfunction persist_attempt(\n matrix_dir: string,\n combo: MatrixCombo,\n attempt: number,\n summary: RunSummary,\n): void {\n const dir = join(combo_dir(matrix_dir, combo), `run-${String(attempt).padStart(2, '0')}`);\n mkdirSync(dir, { recursive: true });\n writeFileSync(join(dir, 'summary.json'), `${JSON.stringify(summary, null, 2)}\\n`);\n}\n\n/** The whole sweep as one machine-readable document, written where the run state\n * is — a long ladder sweep is worth re-reading without re-running. */\nfunction persist_matrix(matrix_dir: string, rows: MatrixRow[]): string {\n mkdirSync(matrix_dir, { recursive: true });\n const path = join(matrix_dir, 'matrix.json');\n writeFileSync(path, `${JSON.stringify({ combos: rows }, null, 2)}\\n`);\n return path;\n}\n\n/** Run one seat `repeat` times, serially, keeping each attempt's run state. */\nasync function run_combo_attempts(\n options: Required<Pick<RunMatrixOptions, 'base' | 'matrix_dir' | 'renderer'>> & {\n combo: MatrixCombo;\n repeat: number;\n run_combo: ComboRunner;\n tag: string;\n },\n): Promise<{ attempts: MatrixAttempt[]; ok: boolean }> {\n const { combo, renderer, repeat, tag } = options;\n const attempts: MatrixAttempt[] = [];\n let ok = true;\n for (let attempt = 1; attempt <= repeat; attempt += 1) {\n const label = repeat === 1 ? tag : `${tag} run ${String(attempt)}/${String(repeat)}`;\n renderer.info(`${label}: builder=${combo.builder} critic=${combo.critic}`);\n try {\n const summary = await options.run_combo(options.base, combo, renderer, attempt);\n persist_attempt(options.matrix_dir, combo, attempt, summary);\n const result = attempt_from_summary(attempt, summary);\n attempts.push(result);\n renderer.info(`${label}: → ${result.status}${result.reason === null ? '' : ` (${result.reason})`}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n attempts.push(broke_attempt(attempt, message));\n ok = false;\n renderer.warn(`${label}: produced no summary: ${message}`);\n }\n }\n return { attempts, ok };\n}\n\n/** Run the builder×critic cross product serially — `repeat` attempts per seat —\n * persisting every attempt's summary and aggregating them into one table. */\nexport async function run_matrix(options: RunMatrixOptions): Promise<MatrixOutcome> {\n const { base, matrix_dir, renderer } = options;\n const run_combo = options.run_combo ?? default_run_combo;\n const repeat = options.repeat ?? DEFAULT_REPEAT;\n const combos = cross_product(options.builders, options.critics);\n renderer.info(\n `matrix: ${String(combos.length)} seat(s) × ${String(repeat)} run(s) = ` +\n `${String(combos.length * repeat)} run(s), serially`,\n );\n\n const rows: MatrixRow[] = [];\n let ok = true;\n let index = 0;\n for (const combo of combos) {\n index += 1;\n const outcome = await run_combo_attempts({\n base,\n matrix_dir,\n renderer,\n combo,\n repeat,\n run_combo,\n tag: `matrix [${String(index)}/${String(combos.length)}]`,\n });\n ok = ok && outcome.ok;\n rows.push(aggregate_row(combo, outcome.attempts));\n }\n\n renderer.info(render_matrix_table(rows));\n renderer.info(`matrix: wrote ${persist_matrix(matrix_dir, rows)}`);\n return { rows, ok };\n}\n\nconst MATRIX_COLUMNS = [\n 'builder',\n 'critic',\n 'pass',\n 'iters',\n 'wall',\n 'cost',\n 'salvage',\n 'flags',\n 'why',\n] as const;\n\nfunction format_wall(ms: number | null): string {\n return ms === null ? '—' : `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction format_rate(rate: number | null): string {\n return rate === null ? '—' : `${String(Math.round(rate * 100))}%`;\n}\n\nfunction format_cost(usd: number | null): string {\n return usd === null ? '—' : `$${usd.toFixed(2)}`;\n}\n\nfunction format_iterations(iterations: number | null): string {\n return iterations === null ? '—' : iterations.toFixed(1);\n}\n\n/** How the degraded flag names a cause in its cell. */\nconst DEGRADE_CAUSE_LABELS: Readonly<Record<DegradeCause, string>> = {\n stream_error: 'stream',\n step_exhaustion: 'steps',\n};\n\n/** The degraded flag with what caused it, `deg:stream`, `deg:steps`, or\n * `deg:stream+steps`, since a bare `deg` can't say whether the critic kept\n * dying or kept reading. */\nfunction degraded_flag(row: MatrixRow): string {\n const causes = row.critic_degrade_causes.map((cause) => DEGRADE_CAUSE_LABELS[cause]);\n return causes.length === 0 ? 'deg' : `deg:${causes.join('+')}`;\n}\n\n/** The two facts that qualify a pass rather than explain a failure, so they do\n * not have to compete with `why` for the same cell. */\nfunction format_flags(row: MatrixRow): string {\n const flags = [\n row.critic_degraded ? degraded_flag(row) : null,\n row.gate_edits.length > 0 ? 'gate' : null,\n ].filter((flag): flag is string => flag !== null);\n return flags.length === 0 ? '—' : flags.join(',');\n}\n\nfunction cell_values(row: MatrixRow): string[] {\n return [\n row.builder,\n row.critic,\n `${String(row.converged)}/${String(row.runs)}`,\n format_iterations(row.mean_iterations),\n format_wall(row.mean_wall_clock_ms),\n format_cost(row.mean_cost_usd),\n format_rate(row.salvage_rate),\n format_flags(row),\n row.reason ?? '—',\n ];\n}\n\n/** Render the aggregate table as a padded, self-aligning block (stderr).\n * Sourced entirely from the rows' `comparison`-derived fields. */\nexport function render_matrix_table(rows: MatrixRow[]): string {\n const header: string[] = [...MATRIX_COLUMNS];\n const body = rows.map(cell_values);\n const widths = header.map((title, col) =>\n Math.max(title.length, ...body.map((cells) => (cells[col] ?? '').length)),\n );\n const render_line = (cells: string[]): string =>\n cells.map((cell, col) => cell.padEnd(widths[col] ?? 0)).join(' ').trimEnd();\n const separator = widths.map((w) => '─'.repeat(w)).join(' ');\n return [render_line(header), separator, ...body.map(render_line)].join('\\n');\n}\n","/**\n * `--dry-run` preflight: prove a run can\n * proceed *before any model spend*. It always renders the resolved config and,\n * when checkride is the resolved check, runs `checkride doctor`. Under\n * `--worktree` it also predicts what a successful run will do with its effects\n * (`report_worktree_fate`) — integrate, salvage onto the run branch, or\n * discard — so no fate arrives as a surprise at teardown.\n *\n * For a containment-requiring tool-loop builder (local or `openrouter`) — run\n * from *inside* its container — it additionally checks the two things that\n * contained build needs: the toolchain is present and the worktree is\n * creatable. Any containment check failing exits 5 (`EXIT_CONFIG_ERROR`).\n *\n * Every seat on a URL-taking provider then gets its model endpoint probed: each\n * seat's own resolved base URL (`seat_base_url`, which crosses a loopback\n * authority to the gateway when `VOLLEY_MODEL_HOST` is set — engine.ts), one\n * probe when both seats share a server. An unreachable endpoint exits 5 too.\n *\n * The all-Claude path runs *none* of the containment checks or probes — it\n * never requires Docker or a model server — so they never contribute an exit 5\n * on that path.\n *\n * A `claude_cli` seat gets one read of `claude --version`, which only ever\n * warns: below the version that enforces the settings blocks keeping the seat's\n * file tools in the build root, the dry run says what goes unenforced.\n *\n * A *local critic* additionally gets the critic-seat canary: one tiny $0\n * generate through the real critic tool wiring, run\n * whatever the builder provider is. A degradable failure warns and predicts\n * `critic_degraded`; only a would-fail-even-degraded combo (endpoint down,\n * model missing) exits 5. The `claude_cli` and `openrouter` critic paths never\n * run it: a canary that costs nothing on a local model costs money there.\n *\n * The probes are injectable so the exit-code contract is unit-testable without\n * a daemon, a git repo, or a live model endpoint.\n */\nimport { spawnSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { capture_baseline } from './changes.js';\nimport {\n format_version,\n MIN_CLAUDE_READ_BLOCK,\n MIN_CLAUDE_WRITE_BLOCK,\n parse_claude_version,\n uses_claude_cli,\n version_below,\n} from './claude_cli_permissions.js';\nimport { detect_containment } from './containment.js';\nimport { critic_canary } from './critic/run.js';\nimport { command_env, create_volley_engine, seat_base_url, takes_seat_url } from './engine.js';\nimport type { Engine } from './engine.js';\nimport { EXIT_CONFIG_ERROR, EXIT_SUCCESS } from './exit_codes.js';\nimport type { Renderer } from './render/renderer.js';\nimport type { BuilderProvider, CriticProvider, ResolvedConfig } from './types.js';\nimport { run_state_dir } from './workspace.js';\nimport { build_root, report_worktree_fate } from './worktree.js';\n\n/** Executables the in-container builder shells out to (checkride/pnpm invoke\n * node; git drives the worktree). Their presence proves the sandbox image\n * carries the toolchain (Dockerfile). */\nconst REQUIRED_TOOLCHAIN: ReadonlyArray<string> = ['node', 'pnpm', 'git'];\n\n/** A short cap on the endpoint probe so a wrong/unreachable host fails fast\n * rather than hanging the preflight before the loop even starts. */\nconst ENDPOINT_PROBE_TIMEOUT_MS = 3000;\n\nconst CLAUDE_VERSION_TIMEOUT_MS = 10_000;\n\n/** Builders that drive their model through volley's own tool loop, local or\n * hosted, so the containment preflight applies. `claude_cli` never does. */\nexport function is_tool_loop_builder(\n provider: BuilderProvider,\n): provider is 'ollama' | 'lmstudio' | 'openrouter' {\n return provider !== 'claude_cli';\n}\n\n/** Critics that run a local model through volley's own tool wiring, so the\n * critic-seat canary applies. `claude_cli` never does: that path is\n * proven and its calls cost real money. Nor does `openrouter`, whose calls cost\n * money too. */\nexport function is_local_critic(\n provider: CriticProvider,\n): provider is 'ollama' | 'lmstudio' {\n return provider === 'ollama' || provider === 'lmstudio';\n}\n\n/** One model server a seat (or both seats) will reach, and who reaches it. */\ntype SeatEndpoint = { seats: string; url: string };\n\n/** The model endpoint each seat on a URL-taking provider will hit, resolved by\n * the same `seat_base_url` the run uses, so the preflight probes exactly what\n * the run will hit. Two seats on one server are merged into one endpoint, so\n * a shared server is probed once. */\nfunction seat_endpoints(\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n): SeatEndpoint[] {\n const builder = takes_seat_url(config.builder_provider)\n ? seat_base_url(config.builder_provider, config.builder_url, env)\n : null;\n const critic = takes_seat_url(config.critic_provider)\n ? seat_base_url(config.critic_provider, config.critic_url, env)\n : null;\n if (builder !== null && builder === critic) {\n return [{ seats: 'builder and critic', url: builder }];\n }\n return [\n ...(builder === null ? [] : [{ seats: 'builder', url: builder }]),\n ...(critic === null ? [] : [{ seats: 'critic', url: critic }]),\n ];\n}\n\n/** Probe each seat's model endpoint before any spend. False, after naming the\n * seat and the URL, when one is unreachable. */\nasync function probe_seat_endpoints(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined>,\n reachable: (url: string) => Promise<boolean>,\n): Promise<boolean> {\n for (const { seats, url } of seat_endpoints(config, env)) {\n if (!(await reachable(url))) {\n renderer.error(`preflight: ${seats} model endpoint unreachable: ${url}`);\n return false;\n }\n renderer.info(`${seats} model endpoint: reachable (${url})`);\n }\n return true;\n}\n\n/** Which required executables are not runnable on the current PATH. */\nfunction toolchain_missing(tools: ReadonlyArray<string> = REQUIRED_TOOLCHAIN): string[] {\n return tools.filter((tool) => {\n const result = spawnSync(tool, ['--version'], { env: command_env(process.env), stdio: 'ignore' });\n return result.error !== undefined || result.status !== 0;\n });\n}\n\n/** Non-destructive check that a git worktree could be created here: git runs and\n * `workspace` is a git work tree. Does not create anything (create/rotate is the\n * run's job — worktree.ts). */\nfunction worktree_creatable(workspace: string): { ok: boolean; detail: string } {\n const repo = resolve(workspace);\n const version = spawnSync('git', ['--version'], { env: command_env(process.env), stdio: 'ignore' });\n if (version.error !== undefined || version.status !== 0) {\n return { ok: false, detail: 'git is not available' };\n }\n if (!existsSync(resolve(repo, '.git'))) {\n return { ok: false, detail: `${repo} is not a git repository` };\n }\n const inside = spawnSync('git', ['-C', repo, 'rev-parse', '--is-inside-work-tree'], {\n env: command_env(process.env),\n encoding: 'utf8',\n });\n if (inside.status !== 0 || (inside.stdout ?? '').trim() !== 'true') {\n return { ok: false, detail: `${repo} is not a git work tree` };\n }\n return { ok: true, detail: repo };\n}\n\n/** What `claude --version` printed, from the binary the run will spawn, or\n * null when it didn't run. */\nfunction claude_version(env: Record<string, string | undefined>): string | null {\n const binary = env['VOLLEY_CLAUDE_BIN'];\n const result = spawnSync(\n binary !== undefined && binary.length > 0 ? binary : 'claude',\n ['--version'],\n { env: command_env(process.env), encoding: 'utf8', timeout: CLAUDE_VERSION_TIMEOUT_MS },\n );\n if (result.error !== undefined || result.status !== 0) return null;\n return result.stdout;\n}\n\n/** Name the Claude Code version a `claude_cli` seat runs on, and warn when it\n * is too old to enforce the blocks that keep the seat's file tools in the\n * build root. Never fails the dry run. */\nfunction report_claude_cli(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined>,\n probe: (env: Record<string, string | undefined>) => string | null,\n): void {\n if (!uses_claude_cli(config)) return;\n const printed = probe(env);\n const version = printed === null ? null : parse_claude_version(printed);\n if (version === null) {\n renderer.warn(\n 'claude: could not read the Claude Code version (`claude --version`), so whether it keeps ' +\n \"a claude_cli seat's file tools in the build root is unknown\",\n );\n return;\n }\n renderer.info(`claude: ${format_version(version)}`);\n if (version_below(version, MIN_CLAUDE_WRITE_BLOCK)) {\n renderer.warn(\n `claude: Claude Code ${format_version(version)} ignores the block on writes outside the build ` +\n `root (needs ${format_version(MIN_CLAUDE_WRITE_BLOCK)}). Edit(/**) still keeps a builder's ` +\n 'edits there under acceptEdits, but not under bypassPermissions.',\n );\n }\n if (version_below(version, MIN_CLAUDE_READ_BLOCK)) {\n renderer.warn(\n `claude: Claude Code ${format_version(version)} ignores the block on reads outside the build ` +\n `root (needs ${format_version(MIN_CLAUDE_READ_BLOCK)}).`,\n );\n }\n}\n\n/** Reachability probe: any HTTP response (even a 404) proves the TCP connect\n * landed; a thrown error (connection refused, DNS failure, timeout) means the\n * endpoint is unreachable. */\nasync function endpoint_reachable(\n url: string,\n timeout_ms: number = ENDPOINT_PROBE_TIMEOUT_MS,\n): Promise<boolean> {\n try {\n await fetch(url, { method: 'GET', signal: AbortSignal.timeout(timeout_ms) });\n return true;\n } catch {\n return false;\n }\n}\n\n/** Injectable probes so the exit-code contract is testable without a daemon,\n * git, or a live endpoint; each defaults to the real implementation above.\n * `canary_engine` fakes the *engine*, not the canary, so the tests exercise the\n * real two-rung classification in `critic_canary`. */\nexport type PreflightProbes = {\n toolchain_missing?: (tools?: ReadonlyArray<string>) => string[];\n worktree_creatable?: (workspace: string) => { ok: boolean; detail: string };\n endpoint_reachable?: (url: string) => Promise<boolean>;\n checkride_doctor?: (workspace: string) => boolean;\n claude_version?: (env: Record<string, string | undefined>) => string | null;\n canary_engine?: (\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n ) => Engine;\n};\n\n/** The canary drives the same engine construction the run itself uses, with the\n * critic role's provider wired in at the critic seat's URL; consulted only after\n * `is_local_critic` says the canary applies, so the claude_cli critic path never\n * builds an engine. */\nfunction default_canary_engine(\n config: ResolvedConfig,\n env: Record<string, string | undefined>,\n): Engine {\n return create_volley_engine({\n workspace: config.workspace,\n critic_provider: config.critic_provider,\n critic_url: config.critic_url,\n env,\n });\n}\n\n/** A seat's info line: its model and provider, and the endpoint a seat on a\n * URL-taking provider will reach. */\nfunction seat_line(\n seat: 'builder' | 'critic',\n model: string,\n provider: BuilderProvider | CriticProvider,\n url: string | null,\n env: Record<string, string | undefined>,\n): string {\n const endpoint = takes_seat_url(provider)\n ? `, endpoint: ${seat_base_url(provider, url, env)}`\n : '';\n return `${seat} model: ${model} (provider: ${provider}${endpoint})`;\n}\n\n/**\n * What this run will do about a builder that edits its own gate, said before any\n * spend — the same predict-then-warn shape as the worktree fate and the\n * critic-seat canary.\n *\n * The warning that earns its place here: `--fail-on-gate-edit` outside a git\n * repository is a refusal that cannot fire. Change detection needs a baseline to\n * diff against, so a non-git workspace silently reports nothing — and an\n * operator who asked for the refusal should learn that now, not from a summary\n * whose `gate_edits` is empty for the wrong reason.\n */\nfunction report_gate_posture(config: ResolvedConfig, renderer: Renderer): void {\n const root = build_root(config.workspace, config.worktree);\n const detectable = capture_baseline(root) !== null || existsSync(join(root, '.git'));\n if (config.fail_on_gate_edit && !detectable) {\n renderer.warn(\n '--fail-on-gate-edit is set, but the build root is not a git repository, so there is no ' +\n 'baseline to diff against and gate edits cannot be detected. The flag will not fire: ' +\n 'run against a git workspace to get the refusal you asked for.',\n );\n return;\n }\n if (config.gate_paths.length === 0) {\n const edits = config.mode === 'critique' ? 'changes' : 'builder edits';\n renderer.info(`gate: no gate paths configured; ${edits} to tests and check config are not flagged.`);\n return;\n }\n renderer.info(\n `gate: watching ${String(config.gate_paths.length)} path pattern(s)` +\n (config.fail_on_gate_edit\n ? ' — a builder edit to any of them halts the run (--fail-on-gate-edit, exit 8).'\n : ' — edits are reported to the critic and recorded in the summary, not refused.'),\n );\n}\n\nfunction run_checkride_doctor(workspace: string): boolean {\n const doctor = spawnSync('pnpm', ['exec', 'checkride', 'doctor'], {\n cwd: workspace,\n env: command_env(process.env),\n stdio: ['ignore', 'ignore', 'inherit'],\n });\n return doctor.error === undefined && doctor.status === 0;\n}\n\n/**\n * Run the preflight and return its exit code (`EXIT_SUCCESS` or, on any failure,\n * `EXIT_CONFIG_ERROR` = 5). `env` supplies the endpoint crossing (`VOLLEY_MODEL_HOST`)\n * and matches what the run itself will read.\n */\nexport async function preflight(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined>,\n probes: PreflightProbes = {},\n): Promise<number> {\n const tool_loop_builder = is_tool_loop_builder(config.builder_provider);\n\n renderer.info(`dry run: config valid (run ${config.run_id})`);\n renderer.info(`workspace: ${config.workspace}`);\n // Each run gets its own directory under the root; a dry run creates none.\n renderer.info(\n config.state_dir === null ? `state: ${run_state_dir(config)}` : `state root: ${config.state_dir}`,\n );\n renderer.info(`check: ${config.check} (resolved: ${config.check_resolved})`);\n if (config.mode === 'critique') {\n renderer.info('builder: none (a critique checks and critiques the change once)');\n } else {\n renderer.info(\n seat_line('builder', config.builder_model, config.builder_provider, config.builder_url, env),\n );\n renderer.info(`builder max steps: ${config.builder_max_steps}`);\n renderer.info(`builder tool calls per turn: ${config.builder_max_tool_calls}`);\n renderer.info(\n `builder output tokens per turn: ${config.builder_max_output_tokens ?? \"the provider's limit\"}`,\n );\n renderer.info(\n `builder history trim: ${config.builder_trim_history === null ? 'off' : `above ${String(config.builder_trim_history)} estimated tokens`}`,\n );\n }\n if (tool_loop_builder) {\n const contained = detect_containment(env);\n renderer.info(\n contained\n ? 'containment: inside the sandbox container (VOLLEY_CONTAINED)'\n : 'containment: uncontained on the host (--allow-unsandboxed-builder)',\n );\n renderer.info(`sandbox image: ${config.sandbox_image}`);\n }\n renderer.info(\n `critic: ${config.critic_preset}${config.critic_prompt_path !== null ? ` (${config.critic_prompt_path})` : ''}`,\n );\n renderer.info(\n seat_line('critic', config.critic_model, config.critic_provider, config.critic_url, env),\n );\n // What a successful run does with its effects, predicted here for any\n // builder provider — the worktree's fate is not a containment concern, and\n // `--worktree` without `--git` must not quietly end in a discarded build.\n report_worktree_fate(config, renderer);\n report_gate_posture(config, renderer);\n report_claude_cli(config, renderer, env, probes.claude_version ?? claude_version);\n\n if (config.check_resolved === 'checkride') {\n const doctor = probes.checkride_doctor ?? run_checkride_doctor;\n if (!doctor(config.workspace)) {\n renderer.error('checkride doctor failed; fix the workspace check pipeline before running');\n return EXIT_CONFIG_ERROR;\n }\n renderer.info('checkride doctor: ok');\n }\n\n // Containment preflight — tool-loop builder only, so the all-Claude path\n // never reaches an exit 5 from here.\n if (tool_loop_builder) {\n const missing = (probes.toolchain_missing ?? toolchain_missing)(REQUIRED_TOOLCHAIN);\n if (missing.length > 0) {\n renderer.error(`preflight: missing toolchain in the sandbox: ${missing.join(', ')}`);\n return EXIT_CONFIG_ERROR;\n }\n renderer.info(`toolchain: ${REQUIRED_TOOLCHAIN.join(', ')} present`);\n\n if (config.worktree) {\n const worktree = (probes.worktree_creatable ?? worktree_creatable)(config.workspace);\n if (!worktree.ok) {\n renderer.error(`preflight: worktree not creatable: ${worktree.detail}`);\n return EXIT_CONFIG_ERROR;\n }\n renderer.info(`worktree: creatable (${worktree.detail})`);\n }\n }\n\n // Each URL-taking seat's own model endpoint, whatever the other seat runs on,\n // so a critic on a second machine is checked as surely as the builder's\n // server. The all-Claude path has no endpoint to probe.\n const reachable = probes.endpoint_reachable ?? endpoint_reachable;\n if (!(await probe_seat_endpoints(config, renderer, env, reachable))) {\n return EXIT_CONFIG_ERROR;\n }\n\n // Critic-seat canary — local critic only, whatever the\n // builder provider is, so a claude_cli-builder + local-critic run still gets\n // its doomed-combo warning before any builder spend. A degradable death warns\n // and predicts `critic_degraded` (refusing it would contradict the fallback\n // ladder); only a would-fail-even-degraded combo exits 5, named model×seat.\n if (is_local_critic(config.critic_provider)) {\n const engine = (probes.canary_engine ?? default_canary_engine)(config, env);\n const seat = `model '${config.critic_model}' in the critic seat (provider: ${config.critic_provider})`;\n try {\n const canary = await critic_canary(engine, config, env);\n if (canary.outcome === 'failed') {\n renderer.error(`preflight: critic canary failed — ${seat}: ${canary.detail}`);\n return EXIT_CONFIG_ERROR;\n }\n if (canary.outcome === 'degraded') {\n renderer.warn(\n `critic canary: ${seat} died on the tool-bearing call (${canary.detail}) ` +\n 'but survived tool-less; a real run will likely degrade to the ' +\n 'tool-less fallback and be marked critic_degraded',\n );\n } else {\n renderer.info(`critic canary: ok (${seat} answered through the real tool wiring)`);\n }\n } finally {\n await engine.dispose();\n }\n }\n\n return EXIT_SUCCESS;\n}\n","#!/usr/bin/env node\n/**\n * CLI entry point: cac argv parsing, dispatch, exit-code mapping.\n * Human progress goes to stderr; stdout carries machine output only.\n */\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { cac } from 'cac';\nimport type { Command } from 'cac';\nimport { serve_acp } from 'fascicle/acp';\nimport { ACP_MAX_ITERATIONS, acp_base_config, acp_serve_config } from './acp.js';\nimport {\n DEFAULT_CHECK,\n DEFAULT_SANDBOX_IMAGE,\n load_config_file,\n resolve_config,\n} from './config.js';\nimport { resolve_baseline } from './changes.js';\nimport { uses_claude_cli } from './claude_cli_permissions.js';\nimport { exit_code_for_error, exit_code_for_status, EXIT_SUCCESS } from './exit_codes.js';\nimport { find_run_state, load_resume_state } from './iteration.js';\nimport { EXIT_MATRIX_INCOMPLETE, parse_model_list, parse_repeat, run_matrix } from './matrix.js';\nimport { run_critique, run_volley } from './orchestrator.js';\nimport { preflight } from './preflight.js';\nimport { colors_enabled, shown } from './render/format.js';\nimport { create_renderer } from './render/renderer.js';\nimport type { Renderer, RenderMode } from './render/renderer.js';\nimport { config_error, error_kind } from './types.js';\nimport type {\n BuilderPermissionMode,\n BuilderProvider,\n CriticProvider,\n ResolvedConfig,\n RunResult,\n VolleyConfig,\n} from './types.js';\nimport { default_state_root, state_path } from './workspace.js';\n\n/** One help string for every command that takes a state root. */\nconst STATE_DIR_HELP =\n \"Keep each run's state under <path>/<run id>/ (default: $XDG_STATE_HOME/volley, else ~/.local/state/volley)\";\n\ntype CliFlags = {\n prompt?: string;\n workspace?: string;\n criteria?: string;\n check?: string;\n builderModel?: string;\n builderProvider?: string;\n builderUrl?: string;\n builderMaxSteps?: number;\n builderMaxToolCalls?: number;\n builderMaxOutputTokens?: number;\n builderTrimHistory?: number;\n allowUnsandboxedBuilder?: boolean;\n criticModel?: string;\n criticProvider?: string;\n criticUrl?: string;\n builderPermissionMode?: string;\n critic?: string;\n maxIterations?: number;\n maxCostUsd?: number;\n git?: boolean;\n worktree?: boolean;\n discardWorktree?: boolean;\n gatePaths?: string;\n failOnGateEdit?: boolean;\n sandboxImage?: string;\n stateDir?: string;\n /** A number when cac coerced a numeric-looking value (`0042` arrives as 42). */\n runId?: string | number;\n dryRun?: boolean;\n trustConfig?: boolean;\n config?: string;\n /** A number when cac coerced an all-digit revision, as it does `runId`. */\n baseline?: string | number;\n json?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n thinking?: boolean;\n};\n\ntype MatrixFlags = {\n config?: string;\n builders?: string;\n critics?: string;\n workspace?: string;\n repeat?: number;\n json?: boolean;\n verbose?: boolean;\n quiet?: boolean;\n};\n\n/**\n * volley's own version for `--version`, read from the manifest rather than\n * repeated here — a literal drifts silently, since `pnpm version` bumps only\n * `package.json` (this one sat at `0.2.0` through three releases).\n *\n * Walks up from this module to the nearest `package.json`, the same shape\n * `presets_dir()` uses to find its files: the manifest sits directly above both\n * `src/` (under tsx) and `dist/` (the built bin, and the published package), so\n * one walk serves every entry path. Never throws — an unreadable manifest\n * reports `unknown` rather than failing every command over a version string.\n */\nexport function package_version(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let depth = 0; depth < 6; depth += 1) {\n const manifest = join(dir, 'package.json');\n if (existsSync(manifest)) {\n try {\n const version = (JSON.parse(readFileSync(manifest, 'utf8')) as { version?: unknown })\n .version;\n if (typeof version === 'string') return version;\n } catch {\n // A torn or unreadable manifest is not worth failing a run over.\n }\n }\n dir = dirname(dir);\n }\n return 'unknown';\n}\n\n/** Split a comma-separated `--gate-paths` value into globs. An all-empty value\n * yields an empty list — \"nothing is the gate\", which turns the report off. */\nfunction parse_glob_list(value: string): string[] {\n return value\n .split(',')\n .map((glob) => glob.trim())\n .filter((glob) => glob.length > 0);\n}\n\nfunction render_mode(config: ResolvedConfig): RenderMode {\n if (config.json) return 'json';\n if (config.quiet) return 'quiet';\n if (config.verbose) return 'verbose';\n return 'default';\n}\n\n/** `run_id` names the run whose trajectory the verbose hint points at; a\n * sweep passes a placeholder, since each seat has an id of its own. */\nfunction make_renderer(config: ResolvedConfig, run_id: string = config.run_id): Renderer {\n return create_renderer({\n mode: render_mode(config),\n show_thinking: config.show_thinking,\n color: colors_enabled(),\n max_cost_usd: config.max_cost_usd,\n trajectory_path: state_path({ ...config, run_id }, 'trajectory.jsonl'),\n });\n}\n\n/** Only `VOLLEY_AUTH_MODE=api_key` hands the claude CLI a key: under `auto`\n * and `oauth` it gets none and stays on its own login, whatever is set. */\nexport function warn_api_key_meter(\n config: ResolvedConfig,\n renderer: Renderer,\n env: Record<string, string | undefined> = process.env,\n): void {\n if (uses_claude_cli(config) && env['VOLLEY_AUTH_MODE'] === 'api_key') {\n renderer.warn(\n 'VOLLEY_AUTH_MODE=api_key: the claude CLI bills this run to ANTHROPIC_API_KEY at API rates, not to a subscription. Know which meter you are on.',\n );\n }\n}\n\n/** What to try when a `claude_cli` seat on the subscription login can't\n * authenticate, which is how every such seat fails once `claude -p` runs bare by\n * default (volley#9). Null for any other error. */\nexport function claude_login_hint(\n err: unknown,\n env: Record<string, string | undefined> = process.env,\n): string | null {\n const auth_failure = [err, (err as { cause?: unknown } | null)?.cause].some(\n (e) =>\n error_kind(e) === 'provider_auth_error' && (e as { provider?: unknown }).provider === 'claude_cli',\n );\n const auth_mode = env['VOLLEY_AUTH_MODE'] ?? 'auto';\n if (!auth_failure || auth_mode === 'api_key') return null;\n return (\n `a claude_cli seat on the subscription login (VOLLEY_AUTH_MODE=${auth_mode}) could not ` +\n 'authenticate. If `claude auth login` does not fix it, a Claude Code release that runs ' +\n '`claude -p` bare by default would explain it (volley#9): set VOLLEY_AUTH_MODE=api_key with ' +\n 'ANTHROPIC_API_KEY to run on the API key meanwhile.'\n );\n}\n\n/** One loud warning when a tool-loop builder is about to run *uncontained* on\n * the host via the opt-out. Config resolution has already refused this\n * unless volley is contained or the opt-out is set, so reaching here with the\n * opt-out active means the operator accepted the uncontained risk. */\nexport function warn_unsandboxed_builder(config: ResolvedConfig, renderer: Renderer): void {\n if (config.builder_provider !== 'claude_cli' && config.allow_unsandboxed_builder) {\n renderer.warn(\n `UNSANDBOXED BUILDER: '${config.builder_provider}' runs volley's tool loop with a real bash ` +\n `(write + exec) directly on this machine in ${config.workspace} — no container isolation. ` +\n `Proceeding because --allow-unsandboxed-builder / VOLLEY_ALLOW_UNSANDBOXED_BUILDER is set; ` +\n `run volley inside its sandbox container for blast-radius containment instead.`,\n );\n }\n}\n\n/** The critic seat's options: its model, provider, and URL. `required` marks\n * the model and provider as having no default, as under `acp`. */\nfunction with_critic_options(command: Command, required = false): Command {\n const model_note = required ? ' (required)' : '';\n const provider_note = required ? 'required' : 'default: claude_cli';\n return command\n .option('--critic-model <model>', `Critic model${model_note}`)\n .option('--critic-provider <name>', `claude_cli | ollama | lmstudio | openrouter (${provider_note})`)\n .option('--critic-url <url>', \"Critic's model server base URL, ollama, lmstudio, or openrouter only (default: VOLLEY_OLLAMA_URL / VOLLEY_LMSTUDIO_URL / VOLLEY_OPENROUTER_URL)\");\n}\n\n/** The seat options, declared once for every command that runs seats: each\n * seat's model, provider, and URL, the tool-loop builder's step cap, and the\n * unsandboxed opt-out. `required` marks each seat's model and provider as\n * having no default, as under `acp`. */\nfunction with_seat_options(command: Command, required = false): Command {\n const model_note = required ? ' (required)' : '';\n const provider_note = required ? 'required' : 'default: claude_cli';\n return with_critic_options(\n command\n .option('--builder-model <model>', `Builder model${model_note}`)\n .option('--builder-provider <name>', `claude_cli | ollama | lmstudio | openrouter (${provider_note})`)\n .option('--builder-url <url>', \"Builder's model server base URL, ollama, lmstudio, or openrouter only (default: VOLLEY_OLLAMA_URL / VOLLEY_LMSTUDIO_URL / VOLLEY_OPENROUTER_URL)\")\n .option('--builder-max-steps <n>', 'Tool-loop builder step cap per iteration, any provider but claude_cli (default: 50)')\n .option('--builder-max-tool-calls <n>', 'Tool calls a tool-loop builder may make per turn, reads aside, any provider but claude_cli (default: 1)')\n .option('--builder-max-output-tokens <n>', \"Output tokens a tool-loop builder may generate per turn, reasoning included, any provider but claude_cli (default: 16384 on ollama and lmstudio, the provider's on openrouter)\")\n .option('--builder-trim-history <tokens>', \"Experimental: above this estimated request size, a tool-loop builder's turns send older tool results as one-line stubs, any provider but claude_cli (default: off)\")\n .option('--allow-unsandboxed-builder', 'Permit a builder other than claude_cli to run without a sandbox (real host bash + write)'),\n required,\n );\n}\n\n/** What a critique declares only so that it can refuse each by name, with\n * exit 5: cac would answer an undeclared one with a bare \"Unknown option\".\n * `resolve_config` refuses all but `--config`, which the command does. */\nconst CRITIQUE_REFUSED_OPTIONS = [\n '--builder-model <model>',\n '--builder-provider <name>',\n '--builder-url <url>',\n '--builder-max-steps <n>',\n '--builder-max-tool-calls <n>',\n '--builder-max-output-tokens <n>',\n '--builder-trim-history <tokens>',\n '--builder-permission-mode <mode>',\n '--allow-unsandboxed-builder',\n '--sandbox-image <tag>',\n '--max-iterations <n>',\n '--max-cost-usd <usd>',\n '--git',\n '--worktree',\n '--discard-worktree',\n '--fail-on-gate-edit',\n '--config <path>',\n];\n\nfunction merge_flags(base: VolleyConfig, flags: CliFlags): VolleyConfig {\n return {\n ...base,\n ...(flags.prompt !== undefined ? { prompt: flags.prompt } : {}),\n ...(flags.workspace !== undefined ? { workspace: flags.workspace } : {}),\n ...(flags.criteria !== undefined ? { criteria: flags.criteria } : {}),\n ...(flags.check !== undefined ? { check: flags.check } : {}),\n ...(flags.builderModel !== undefined ? { builder_model: flags.builderModel } : {}),\n ...(flags.builderProvider !== undefined\n ? { builder_provider: flags.builderProvider as BuilderProvider }\n : {}),\n ...(flags.builderUrl !== undefined ? { builder_url: flags.builderUrl } : {}),\n ...(flags.builderMaxSteps !== undefined\n ? { builder_max_steps: Number(flags.builderMaxSteps) }\n : {}),\n ...(flags.builderMaxToolCalls !== undefined\n ? { builder_max_tool_calls: Number(flags.builderMaxToolCalls) }\n : {}),\n ...(flags.builderMaxOutputTokens !== undefined\n ? { builder_max_output_tokens: Number(flags.builderMaxOutputTokens) }\n : {}),\n ...(flags.builderTrimHistory !== undefined\n ? { builder_trim_history: Number(flags.builderTrimHistory) }\n : {}),\n ...(flags.allowUnsandboxedBuilder === true ? { allow_unsandboxed_builder: true } : {}),\n ...(flags.criticModel !== undefined ? { critic_model: flags.criticModel } : {}),\n ...(flags.criticProvider !== undefined\n ? { critic_provider: flags.criticProvider as CriticProvider }\n : {}),\n ...(flags.criticUrl !== undefined ? { critic_url: flags.criticUrl } : {}),\n ...(flags.builderPermissionMode !== undefined\n ? { builder_permission_mode: flags.builderPermissionMode as BuilderPermissionMode }\n : {}),\n ...(flags.critic !== undefined ? { critic: flags.critic } : {}),\n ...(flags.maxIterations !== undefined ? { max_iterations: Number(flags.maxIterations) } : {}),\n ...(flags.maxCostUsd !== undefined ? { max_cost_usd: Number(flags.maxCostUsd) } : {}),\n ...(flags.git === true ? { git_checkpoints: true } : {}),\n ...(flags.worktree === true ? { worktree: true } : {}),\n ...(flags.discardWorktree === true ? { discard_worktree: true } : {}),\n ...(flags.gatePaths !== undefined ? { gate_paths: parse_glob_list(flags.gatePaths) } : {}),\n ...(flags.failOnGateEdit === true ? { fail_on_gate_edit: true } : {}),\n ...(flags.sandboxImage !== undefined ? { sandbox_image: flags.sandboxImage } : {}),\n ...(flags.stateDir !== undefined ? { state_dir: flags.stateDir } : {}),\n ...(flags.dryRun === true ? { dry_run: true } : {}),\n ...(flags.json === true ? { json: true } : {}),\n ...(flags.verbose === true ? { verbose: true } : {}),\n ...(flags.quiet === true ? { quiet: true } : {}),\n ...(flags.thinking === false ? { show_thinking: false } : {}),\n };\n}\n\n/** What a resume is about to run on a config this machine didn't sign, said\n * once before it runs, so `--trust-config` is never a blind yes. Every value\n * came from that config, so each is quoted with its control characters\n * escaped, and can't redraw the line it's warned on. */\nfunction warn_trusted_config(config: ResolvedConfig, renderer: Renderer): void {\n renderer.warn(\n `resuming on a config volley on this machine didn't sign (--trust-config): check ` +\n `${shown(config.check)} (resolved: ${config.check_resolved}), builder ` +\n `${config.builder_provider} ${shown(config.builder_model)} (${config.builder_permission_mode}), ` +\n `critic ${config.critic_provider} ${shown(config.critic_model)}, workspace ${shown(config.workspace)}`,\n );\n}\n\n/** A flag's value as typed. cac reads an all-digit value as a number, which\n * drops leading zeros, so a coerced id or revision would silently name another\n * run or commit: refused rather than guessed at. */\nfunction not_a_bare_number(name: string, value: string | number | undefined): string | undefined {\n if (typeof value === 'number') {\n throw config_error(`${name} must not be a bare number (read as ${String(value)})`);\n }\n return value;\n}\n\nfunction emit_result(config: ResolvedConfig, result: RunResult, renderer: Renderer): number {\n renderer.final_summary(result);\n if (config.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n }\n return exit_code_for_status(result.status);\n}\n\nfunction report_error(err: unknown): number {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`volley: ${message}\\n`);\n if (error_kind(err) === 'phase_error') {\n const cause = (err as { cause?: unknown }).cause;\n if (cause instanceof Error && cause.message !== message) {\n process.stderr.write(` cause: ${cause.message}\\n`);\n }\n }\n const hint = claude_login_hint(err);\n if (hint !== null) process.stderr.write(` hint: ${hint}\\n`);\n return exit_code_for_error(err);\n}\n\nasync function main(argv: string[]): Promise<number> {\n const cli = cac('volley');\n\n let exit_code = EXIT_SUCCESS;\n\n const run_command = cli\n .command('', 'Run the builder/critic loop')\n .option('--prompt <prompt>', 'Task prompt (string or @file)')\n .option('--workspace <path>', 'Workspace directory (must exist and be writable)')\n .option('--criteria <criteria>', 'Acceptance criteria (string or @file)')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`);\n with_seat_options(run_command)\n .option('--builder-permission-mode <mode>', 'acceptEdits | bypassPermissions')\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--max-iterations <n>', 'Iteration cap')\n .option('--max-cost-usd <usd>', 'Hard USD ceiling, enforced in the loop guard')\n .option('--git', 'Auto-commit after each phase (workspace must be a git repo)')\n .option('--worktree', 'Isolate the builder run in a per-run git worktree (workspace must be a git repo)')\n .option('--discard-worktree', \"Throw a --worktree run's effects away at teardown instead of keeping them on the run branch\")\n .option('--gate-paths <globs>', 'Comma-separated globs naming the gate (tests, fixtures, check config); replaces the defaults')\n .option('--fail-on-gate-edit', 'Halt the run if the builder edits a gate path (exit 8) instead of reporting it')\n .option('--sandbox-image <tag>', `Container image for the local-builder sandbox (default: ${DEFAULT_SANDBOX_IMAGE})`)\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--run-id <id>', \"The run's id, naming its volley/<id> branch (default: a fresh UUID)\")\n .option('--dry-run', 'Validate config (and checkride doctor) without running')\n .option('--config <path>', 'TypeScript config file exporting a VolleyConfig')\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs (truncated at 4000 chars)')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks (still recorded in the trajectory)')\n .action(async (flags: CliFlags) => {\n const base = flags.config !== undefined ? await load_config_file(flags.config) : ({} as VolleyConfig);\n const merged = merge_flags(base, flags);\n const run_id = not_a_bare_number('--run-id', flags.runId);\n const config = resolve_config(merged, run_id !== undefined ? { run_id } : {});\n const renderer = make_renderer(config);\n warn_api_key_meter(config, renderer);\n warn_unsandboxed_builder(config, renderer);\n if (merged.dry_run === true) {\n exit_code = await preflight(config, renderer, process.env);\n return;\n }\n const result = await run_volley(config, { renderer });\n exit_code = emit_result(config, result, renderer);\n });\n\n cli\n .command('resume <run_id>', 'Resume a run from its last completed iteration')\n .option('--workspace <path>', \"Where a run an older volley started keeps its .volley/ state\", {\n default: '.',\n })\n .option('--state-dir <path>', 'State root the run was started under (default: $XDG_STATE_HOME/volley, else ~/.local/state/volley)')\n .option('--trust-config', \"Resume a config volley on this machine didn't sign: another machine's, an older volley's, or one you edited. Read it first\")\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks')\n .action(async (run_id: string, flags: CliFlags) => {\n // cac refuses any option this command doesn't declare, so what's left\n // once the lookup flags are taken out is the output flags alone.\n const { workspace = '.', stateDir, trustConfig, ...output } = flags;\n // The run is looked for under the root named here, else the default, and\n // where it's found wins over the recorded root, so a moved root resumes\n // where it now is. A run an older volley kept in .volley/ resumes there.\n const root = stateDir === undefined ? default_state_root(process.env) : resolve(stateDir);\n const state_dir = find_run_state(workspace, run_id, root);\n const resume = load_resume_state(workspace, run_id, state_dir, {\n trust_config: trustConfig === true,\n });\n const merged = merge_flags(resume.raw_config, output);\n const config = resolve_config(merged, {\n run_id: resume.run_id,\n started_at: resume.started_at,\n state_dir,\n });\n if (resume.iterations_completed >= config.max_iterations) {\n throw config_error(\n `run already completed ${String(resume.iterations_completed)} of ${String(config.max_iterations)} iterations`,\n );\n }\n const renderer = make_renderer(config);\n warn_api_key_meter(config, renderer);\n warn_unsandboxed_builder(config, renderer);\n if (resume.config_signed === false) warn_trusted_config(config, renderer);\n renderer.info(\n `resuming run ${run_id} at iteration ${String(resume.iterations_completed + 1)}`,\n );\n const result = await run_volley(config, { renderer }, resume.state);\n exit_code = emit_result(config, result, renderer);\n });\n\n const critique_command = cli\n .command('critique', 'Check and critique a change already made, once, with no builder')\n .option('--workspace <path>', 'The repository whose change is reviewed', { default: '.' })\n .option('--baseline <rev>', 'Review everything that differs from this revision, committed or not (default: HEAD)')\n .option('--criteria <criteria>', 'Acceptance criteria (string or @file)')\n .option('--prompt <prompt>', 'The task the change answers, recorded with the run; the critic judges against --criteria')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`);\n with_critic_options(critique_command)\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--gate-paths <globs>', 'Comma-separated globs naming the gate (tests, fixtures, check config); replaces the defaults')\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--run-id <id>', \"The run's id, naming its state directory (default: a fresh UUID)\")\n .option('--dry-run', 'Validate config and the baseline, run checkride doctor, and probe the critic seat, then exit')\n .option('--json', 'Machine mode: final summary JSON on stdout, no streaming')\n .option('--verbose', 'Show full tool inputs/outputs (truncated at 4000 chars)')\n .option('--quiet', 'Only phase transitions, cost updates, and the final summary')\n .option('--no-thinking', 'Hide reasoning chunks (still recorded in the trajectory)');\n for (const refused of CRITIQUE_REFUSED_OPTIONS) {\n critique_command.option(refused, 'Refused: a critique runs no builder and no loop');\n }\n critique_command.action(async (flags: CliFlags) => {\n if (flags.config !== undefined) {\n throw config_error(\n \"volley critique refuses --config: a run's config file sets a builder; pass the critique's settings as flags\",\n );\n }\n const run_id = not_a_bare_number('--run-id', flags.runId);\n const baseline = not_a_bare_number('--baseline', flags.baseline);\n const merged = merge_flags({} as VolleyConfig, flags);\n const config = resolve_config(merged, {\n mode: 'critique',\n ...(run_id !== undefined ? { run_id } : {}),\n });\n const renderer = make_renderer(config);\n warn_api_key_meter(config, renderer);\n if (merged.dry_run === true) {\n // A revision that isn't a commit fails the dry run as it would the critique.\n const sha = resolve_baseline(config.workspace, baseline);\n renderer.info(`baseline: ${sha ?? 'none (not a git repository, or no commit yet)'}`);\n exit_code = await preflight(config, renderer, process.env);\n return;\n }\n const result = await run_critique(config, {\n renderer,\n ...(baseline !== undefined ? { baseline } : {}),\n });\n exit_code = emit_result(config, result, renderer);\n });\n\n cli\n .command('matrix', 'Sweep builder×critic model combos serially over one config')\n .option('--config <path>', 'Base VolleyConfig (TS/JS): the task, workspace, providers, and caps held fixed')\n .option('--builders <models>', 'Comma-separated builder models to sweep')\n .option('--critics <models>', 'Comma-separated critic models to sweep')\n .option('--workspace <path>', 'Override the base config workspace')\n .option('--repeat <n>', 'Attempts per seat (default: 1); a pass rate needs more than one')\n .option('--json', 'Machine mode: aggregate JSON on stdout, no table')\n .option('--verbose', 'Show full builder/critic streams per combo')\n .option('--quiet', 'Per-combo phase transitions and the final table only')\n .action(async (flags: MatrixFlags) => {\n if (flags.config === undefined) {\n throw config_error('volley matrix requires --config <path> (the base task to sweep)');\n }\n const builders = parse_model_list(flags.builders, '--builders');\n const critics = parse_model_list(flags.critics, '--critics');\n const repeat = parse_repeat(flags.repeat);\n const base = await load_config_file(flags.config);\n const merged = merge_flags(base, {\n ...(flags.workspace !== undefined ? { workspace: flags.workspace } : {}),\n ...(flags.json === true ? { json: true } : {}),\n ...(flags.verbose === true ? { verbose: true } : {}),\n ...(flags.quiet === true ? { quiet: true } : {}),\n });\n // Resolve once with the forced throw-away worktree to validate the\n // git repo, providers, and task up front — before any combo spends — and to\n // build the renderer and locate the workspace-level `.volley-matrix/`\n // output. Matches what `default_run_combo` resolves per seat.\n const base_config = resolve_config({ ...merged, worktree: true, discard_worktree: true });\n const renderer = make_renderer(base_config, '<run id>');\n warn_api_key_meter(base_config, renderer);\n warn_unsandboxed_builder(base_config, renderer);\n const outcome = await run_matrix({\n base: merged,\n builders,\n critics,\n matrix_dir: join(base_config.workspace, '.volley-matrix'),\n renderer,\n repeat,\n });\n if (base_config.json) {\n process.stdout.write(`${JSON.stringify({ combos: outcome.rows }, null, 2)}\\n`);\n }\n exit_code = outcome.ok ? EXIT_SUCCESS : EXIT_MATRIX_INCOMPLETE;\n });\n\n // `--worktree`, `--git`, and `--json` are declared only so they can be\n // refused with a reason; cac would answer an undeclared one with a bare\n // \"Unknown option\".\n const acp_command = cli.command('acp', 'Serve volley to an editor as an ACP agent over stdio');\n with_seat_options(acp_command, true)\n .option('--critic <critic>', 'reviewer | optimizer | researcher | path to prompt file')\n .option('--check <check>', `auto | none | shell command (default: ${DEFAULT_CHECK})`)\n .option('--max-iterations <n>', `Iteration cap per prompt (default: ${String(ACP_MAX_ITERATIONS)})`)\n .option('--max-cost-usd <usd>', 'Hard USD ceiling per prompt, enforced in the loop guard')\n .option('--state-dir <path>', STATE_DIR_HELP)\n .option('--worktree', 'Refused: a sibling worktree sits outside the project the editor has open')\n .option('--git', 'Refused: phase commits would bypass the permission prompts')\n .option('--json', 'Refused: stdout carries the protocol')\n .action(async (flags: CliFlags) => {\n const base = acp_base_config(merge_flags({} as VolleyConfig, flags));\n await serve_acp(acp_serve_config(base, { version: package_version() }));\n });\n\n cli.help();\n cli.version(package_version());\n\n try {\n cli.parse(argv, { run: false });\n await cli.runMatchedCommand();\n } catch (err) {\n return report_error(err);\n }\n return exit_code;\n}\n\n// Guard the entry so importing this module (e.g. from tests, to exercise the\n// exported warn helpers) does not run the CLI. `import.meta.main` is true only\n// when this file is the process entry point (symlink-safe; Node ≥ 24).\nif (import.meta.main) {\n const code = await main(process.argv);\n process.exitCode = code;\n}\n"],"mappings":"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"}