@warble/claude-agent-sdk 0.6.0 → 0.8.0
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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/error.ts","../src/codegen.ts","../src/ir.ts","../src/models.ts","../src/route.ts","../src/targets.ts","../src/options.ts","../src/resolve.ts","../src/guardrails.ts","../src/localClient.ts","../src/hybridTool.ts","../src/render.ts","../src/run.ts","../src/conditional.ts","../src/events.ts","../src/dispatch.ts","../src/manifest.ts","../src/model_catalog.ts","../src/session.ts"],"sourcesContent":["/**\n * Dispatch-time error — the TS analogue of the Rust back-end's `DispatchError`.\n *\n * Every loud-fail in this back-end (unknown IR version, unsupported enum \"wall-hit\", capability\n * `fail`, undefined tier) throws a `DispatchError`; the CLI turns it into a non-zero exit + message.\n */\nexport class DispatchError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DispatchError\";\n }\n}\n","/**\n * Codegen (`emit`) — freeze a prepared dispatch into an importable TS agent module.\n *\n * The IR→options mapping is resolved at emit time and the resulting `query({options})` is written as\n * source, plus a thin `run()` per component. Analogue of the file target emitting `.md` — here it is\n * `.ts` a user drops into their own codebase. Two modes:\n * - **thin (default)** — imports the runtime helpers (guardrail / trace / render) from\n * `@warble/claude-agent-sdk`; small and always in sync with the library.\n * - **standalone** — inlines a minimal read-only guard + trace + render shell, so the only imports\n * are `@anthropic-ai/claude-agent-sdk` and Node built-ins (the `warble` *binary* is still used\n * for render — that is the renderer-reuse contract, not a TS dependency).\n */\nimport type { PreparedDispatch } from \"./dispatch.js\";\nimport type { DispatchMeta } from \"./options.js\";\nimport { DispatchError } from \"./error.js\";\n\nexport interface EmitOptions {\n standalone?: boolean;\n}\n\n/** Emitted per-component metadata (the subset the guard/trace/render need at runtime). */\ninterface EmittedMeta {\n target: string;\n verb: string;\n model: string;\n split: boolean;\n readOnly: boolean;\n render: DispatchMeta[\"render\"];\n /** +Setup: threaded to `makeReadOnlyGuard` so the emitted module gets the same Read-side\n * `PreToolUse` dotenv-deny hook as run.ts. `null` for every non-setup component. See the\n * standalone-mode wall-hit in `emitAgentModule` below for why this is fail-closed, not silently\n * dropped, when `--standalone` is combined with a setup-scoped component. */\n setupScope: string | null;\n}\n\nfunction ident(verb: string): string {\n const base = verb.replace(/[^A-Za-z0-9_$]/g, \"_\");\n return /^[0-9]/.test(base) ? `_${base}` : base;\n}\n\nfunction json(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nconst RUN_RESULT_TYPE =\n \"{ finalText: string; trace: Trace; htmlPath: string | null; denials: Denial[]; \" +\n \"renderDegraded: { reason: string } | null }\";\n\n/** The shared body of a component's `run()` (identical in both modes; only imports differ). */\nfunction runBody(fn: string): string {\n return ` const cwd = ${fn}_options.cwd ?? process.cwd();\n const gate = ${fn}_meta.render;\n const writeScope = gate.kind === \"realize\" && gate.flavor === \"prompt\" ? gate.scope : null;\n const { canUseTool, denials, hooks } = makeReadOnlyGuard({\n readOnly: ${fn}_meta.readOnly,\n writeScope,\n cwd,\n setupScope: ${fn}_meta.setupScope,\n });\n\n // Read never reaches \\`canUseTool\\` for an in-cwd path in the real SDK (see guardrails.ts in the\n // warble repo); this hook is the live enforcement point for the +Setup dotenv-read gate's Read\n // side. Mirrors run.ts's wiring exactly — merge, don't clobber, any hooks already on the options.\n const messages: SDKMessage[] = [];\n for await (const m of query({\n prompt: question,\n options: {\n ...${fn}_options,\n canUseTool,\n hooks: { ...${fn}_options.hooks, PreToolUse: [...(${fn}_options.hooks?.PreToolUse ?? []), ...hooks] },\n },\n })) {\n messages.push(m);\n }\n\n const result = messages.find((m): m is Extract<SDKMessage, { type: \"result\" }> => m.type === \"result\");\n if (!result || result.subtype !== \"success\") {\n throw new Error(\\`agent run failed: \\${result ? result.subtype : \"no result message\"}\\`);\n }\n const finalText = result.result;\n const trace = aggregateTrace(\n messages,\n { target: ${fn}_meta.target, verb: ${fn}_meta.verb, model: ${fn}_meta.model, split: ${fn}_meta.split },\n denials,\n );\n\n let htmlPath: string | null = null;\n let renderDegraded: { reason: string } | null = null;\n if (gate.kind === \"realize\" && gate.flavor === \"programmatic\" && opts.outDir) {\n const out = join(opts.outDir, \"dashboard.html\");\n try {\n renderEnvelope(finalText, out, { warbleBin: opts.warbleBin ?? \"warble\", ...(opts.title ? { title: opts.title } : {}) });\n htmlPath = out;\n } catch (err) {\n // best-effort render_contract: degrade to the agent's own text instead of failing the whole\n // run (capability-model.md — only safety-critical/required capabilities never silently\n // degrade). \\`onFailure\\` absent/\"fail\" preserves the prior hard-fail behavior exactly.\n if (gate.onFailure !== \"degrade\") throw err;\n renderDegraded = { reason: err instanceof Error ? err.message : String(err) };\n }\n }\n return { finalText, trace, htmlPath, denials, renderDegraded };`;\n}\n\nfunction componentBlock(fn: string, verb: string, options: unknown, meta: EmittedMeta): string {\n return `// ---- component: ${verb} ----\nconst ${fn}_options = ${json(options)} satisfies Options;\nconst ${fn}_meta: EmittedMeta = ${json(meta)};\n\n/** Run the \\`${verb}\\` agent against the live Agent SDK loop. */\nexport async function ${fn}(question: string, opts: RunOptions = {}): Promise<RunResult> {\n${runBody(fn)}\n}`;\n}\n\nconst THIN_IMPORTS = `import { join } from \"node:path\";\nimport { query, type Options, type SDKMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport {\n makeReadOnlyGuard,\n aggregateTrace,\n renderEnvelope,\n type Trace,\n type Denial,\n} from \"@warble/claude-agent-sdk\";`;\n\nconst STANDALONE_IMPORTS = `import { join, sep } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { query, type Options, type SDKMessage } from \"@anthropic-ai/claude-agent-sdk\";`;\n\n/** Inlined runtime helpers for the standalone (eject) mode — no `@warble/*` dependency. */\nconst STANDALONE_HELPERS = `interface Denial { tool: string; reason: string; command?: string }\ninterface Trace {\n target: string; verb: string; model: string; split: boolean;\n run: { total_cost_usd: number; duration_ms: number; duration_api_ms: number; num_turns: number } | null;\n modelUsage: Record<string, unknown>;\n steps: { model: string; parent_tool_use_id: string | null; usage: unknown }[];\n denials: Denial[];\n}\n\nconst DESTRUCTIVE = /\\\\b(rm|sudo|dd|mkfs|shutdown|reboot|kill|chmod|chown|mv|cp)\\\\b/;\nconst REDIRECTION = /(^|[^>])>>?[^>]/;\n// Kept byte-identical to guardrails.ts's DOTENV_READER_COMMANDS/DOTENV_PATH pair (see that file's doc\n// comment for the incident this closes) — checked FIRST and unconditionally in the Bash branch below,\n// exactly like canonical, never gated behind any config field. tests/guard-drift.test.ts asserts this\n// inlined guard stays behaviorally equivalent to guardrails.ts on the surface standalone mode actually\n// supports (setupScope always null here — see the wall-hit above).\nconst DOTENV_READER_COMMANDS = /\\\\b(cat|head|tail|less|more|od|xxd|strings|grep|awk|sed)\\\\b/;\nconst DOTENV_PATH = /(^|[\\\\s\"'\\\\/=])\\\\.env(\\\\.[\\\\w.-]+)?(?=$|[\\\\s\"'\\\\/])/;\n\nfunction referencesDotenvPath(text: string): boolean {\n return DOTENV_PATH.test(text);\n}\n\nfunction makeReadOnlyGuard(cfg: {\n readOnly: boolean;\n writeScope: string | null;\n cwd: string;\n mutation?: { mustDryRun: boolean; approvalRequired: boolean };\n // \\`emitAgentModule\\` wall-hits before generating any component code if a setup-scoped component is\n // combined with --standalone (see codegen.ts), so this is always null here in practice — the field\n // only exists so this inlined guard's call signature matches the thin-mode \\`makeReadOnlyGuard\\`\n // import that runBody() (shared between both modes) calls. This guard's Bash branch DOES carry the\n // unconditional dotenv-read denylist (see DOTENV_READER_COMMANDS/DOTENV_PATH above) — that applies to\n // every component, not just +Setup ones, so it stays in sync here. What it deliberately does NOT\n // carry is any setupScope-aware widening (Bash beyond \\`wren\\`, Write/Edit scoped to a project root, a\n // Read-side PreToolUse hook) — the wall-hit above refuses --standalone for a setup-scoped component\n // rather than hand-syncing that logic and risking exactly the copy-drift this fix exists to close.\n // tests/guard-drift.test.ts is the tripwire: it fails if this copy and guardrails.ts::makeReadOnlyGuard\n // diverge on the setupScope == null surface, or if guardrails.ts grows new reachable behavior on that\n // surface that this copy doesn't (yet) have.\n setupScope?: string | null;\n}) {\n const denials: Denial[] = [];\n const hooks: never[] = [];\n const canUseTool = async (toolName: string, input: Record<string, unknown>) => {\n if (toolName === \"Read\" || toolName === \"Task\" || toolName === \"TodoWrite\") {\n return { behavior: \"allow\" as const, updatedInput: input };\n }\n if (toolName === \"Bash\") {\n const command = typeof input.command === \"string\" ? input.command : \"\";\n // Dotenv-read pair: checked FIRST and unconditionally, before DESTRUCTIVE/REDIRECTION and the\n // wren-only check below — mirrors guardrails.ts::makeReadOnlyGuard exactly (see that file's\n // comment; standalone mode never has setupScope set, but the same compound-command bypass\n // guardrails.ts closes here applies to every component, not just +Setup ones).\n if (DOTENV_READER_COMMANDS.test(command) && referencesDotenvPath(command)) {\n const reason =\n \"reading a dotenv file's contents is blocked by the read_only_execution guardrail; the \" +\n \"setup credential design writes an empty .env template and is never meant to read it back.\";\n denials.push({ tool: \"Bash\", reason, command });\n return { behavior: \"deny\" as const, message: reason };\n }\n if (DESTRUCTIVE.test(command) || REDIRECTION.test(command)) {\n const reason =\n \"destructive or file-writing bash is blocked by the read_only_execution guardrail; \" +\n \"all data access must go through the read-only \\`wren\\` CLI.\";\n denials.push({ tool: \"Bash\", reason, command });\n return { behavior: \"deny\" as const, message: reason };\n }\n if (command.trim().split(/\\\\s+/)[0] !== \"wren\") {\n const reason =\n \"only \\`wren\\` CLI invocations are permitted (data access goes through the semantic \" +\n \"layer); this command is blocked by the read_only_execution guardrail.\";\n denials.push({ tool: \"Bash\", reason, command });\n return { behavior: \"deny\" as const, message: reason };\n }\n return { behavior: \"allow\" as const, updatedInput: input };\n }\n if (toolName === \"Write\" || toolName === \"Edit\") {\n if (cfg.mutation) {\n const gate = cfg.mutation.approvalRequired ? \"human approval\" : \"the must_dry_run gate\";\n const reason = \\`\\${toolName} is the gated apply of a mutating component and requires \\${gate} to clear first; that approval is borrowed from the SDK embedder's own canUseTool/approval channel, which this guard does not provide, so it denies by default (fail-closed).\\`;\n denials.push({ tool: toolName, reason });\n return { behavior: \"deny\" as const, message: reason };\n }\n if (cfg.writeScope) {\n const target = typeof input.file_path === \"string\" ? input.file_path : \"\";\n const abs = join(cfg.cwd, target);\n // Path-boundary-safe containment (mirrors guardrails.ts::withinScope): an exact match or a\n // real separator boundary — never a bare prefix, which would admit a sibling like models-export/.\n const scopeAbs = join(cfg.cwd, cfg.writeScope);\n if (abs === scopeAbs || abs.startsWith(scopeAbs.endsWith(sep) ? scopeAbs : scopeAbs + sep)) return { behavior: \"allow\" as const, updatedInput: input };\n const reason = \\`write to '\\${target}' is outside the permitted artifact scope '\\${cfg.writeScope}'.\\`;\n denials.push({ tool: toolName, reason, command: target });\n return { behavior: \"deny\" as const, message: reason };\n }\n const reason =\n \\`\\${toolName} is blocked: this component is read-only (programmatic render flavor keeps the \\` +\n \\`agent from writing files; the dispatcher renders the dashboard from your envelope).\\`;\n denials.push({ tool: toolName, reason });\n return { behavior: \"deny\" as const, message: reason };\n }\n const reason = \\`tool '\\${toolName}' is not permitted for this component.\\`;\n denials.push({ tool: toolName, reason });\n return { behavior: \"deny\" as const, message: reason };\n };\n return { canUseTool, denials, hooks };\n}\n\nfunction aggregateTrace(\n messages: readonly SDKMessage[],\n meta: { target: string; verb: string; model: string; split: boolean },\n denials: Denial[],\n): Trace {\n const steps = messages\n .filter((m): m is Extract<SDKMessage, { type: \"assistant\" }> => m.type === \"assistant\")\n .map((m) => ({ model: m.message.model, parent_tool_use_id: m.parent_tool_use_id, usage: m.message.usage }));\n const result = messages.find((m): m is Extract<SDKMessage, { type: \"result\" }> => m.type === \"result\");\n const run = result === undefined ? null : {\n total_cost_usd: result.total_cost_usd, duration_ms: result.duration_ms,\n duration_api_ms: result.duration_api_ms, num_turns: result.num_turns,\n };\n return {\n target: meta.target, verb: meta.verb, model: meta.model, split: meta.split, run,\n modelUsage: (result?.modelUsage ?? {}) as Record<string, unknown>, steps, denials,\n };\n}\n\nfunction renderEnvelope(finalText: string, outPath: string, opts: { warbleBin: string; title?: string }): void {\n const dir = mkdtempSync(join(tmpdir(), \"warble-emit-\"));\n const envelopePath = join(dir, \"envelope.txt\");\n writeFileSync(envelopePath, finalText, \"utf8\");\n const args = [\"render\", envelopePath, \"--out\", outPath];\n if (opts.title) args.push(\"--title\", opts.title);\n const proc = spawnSync(opts.warbleBin, args, { encoding: \"utf8\" });\n if (proc.error) {\n const err = proc.error as NodeJS.ErrnoException;\n const base = \\`failed to run '\\${opts.warbleBin} render': \\${err.message}\\`;\n if (err.code === \"ENOENT\") {\n throw new Error(\n \\`\\${base}\\\\nThe 'warble' binary was not found. Install it with 'cargo install warble-cli' \\` +\n \\`(requires a Rust toolchain; installs from crates.io), or set the 'warbleBin' option \\` +\n \\`(CLI: --warble-bin <path>) to point at an existing 'warble' binary.\\`,\n );\n }\n throw new Error(\\`\\${base} (set the 'warbleBin' option, or pass --warble-bin <path> on the CLI, to point at a different binary)\\`);\n }\n if (proc.status !== 0) throw new Error(\\`warble render exited \\${proc.status}: \\${proc.stderr?.trim() ?? \"\"}\\`);\n}`;\n\nconst PREAMBLE_TYPES = `export interface RunOptions { outDir?: string; warbleBin?: string; title?: string }\nexport type RunResult = ${RUN_RESULT_TYPE};\n\ninterface EmittedMeta {\n target: string; verb: string; model: string; split: boolean; readOnly: boolean;\n render: {\n kind: \"realize\" | \"degrade\" | \"none\"; scope: string | null; flavor: \"programmatic\" | \"prompt\" | null;\n onFailure?: \"degrade\" | \"fail\";\n };\n setupScope: string | null;\n}`;\n\n/**\n * Emit a TS agent module (as source text) for a prepared dispatch. Each component becomes an exported\n * async `run()` function that drives the SDK loop with the resolved, frozen options.\n */\nexport function emitAgentModule(prepared: PreparedDispatch, opts: EmitOptions = {}): string {\n const standalone = opts.standalone ?? false;\n\n const header = [\n \"// Generated by `warble-agent-sdk emit` — do not edit by hand.\",\n `// Target: ${prepared.target}. Regenerate from the IR instead of editing.`,\n standalone\n ? \"// Mode: standalone (runtime helpers inlined; only @anthropic-ai/claude-agent-sdk + the `warble` binary needed).\"\n : \"// Mode: thin (imports runtime helpers from @warble/claude-agent-sdk).\",\n ].join(\"\\n\");\n\n // Standalone (eject) mode has no counterpart to run.ts's PreToolUse hook wiring: its inlined guard\n // does not (and, per the review, should not be hand-synced to) replicate the +Setup Read-side\n // dotenv PreToolUse hook or any other setupScope-aware widening. Rather than silently ship a\n // setup-scoped agent with zero dotenv protection on the Read side, wall-hit at emit time — loud and\n // specific, same convention as options.ts's `unsupported()`. tests/guard-drift.test.ts is the\n // tripwire that keeps this inlined guard behaviorally in sync with guardrails.ts on the surface\n // standalone mode DOES support (setupScope == null).\n if (standalone) {\n const setupScoped = prepared.components.filter((c) => c.plan.meta.setupScope != null);\n if (setupScoped.length > 0) {\n const verbs = setupScoped.map((c) => c.node.verb).join(\", \");\n throw new DispatchError(\n `emit --standalone does not support setup-scoped component(s) [${verbs}] (wall-hit): the ` +\n \"inlined standalone guard has no dotenv-read Read hook and no setupScope-aware Bash/Write \" +\n \"widening, so a standalone-ejected setup agent would have zero protection against the \" +\n \"dotenv-read gap that guardrails.ts's PreToolUse hook closes for the thin (default) mode. \" +\n \"Emit without --standalone for these component(s), or omit them from this IR.\",\n );\n }\n }\n\n const blocks = prepared.components.map((c) => {\n const fn = ident(c.node.verb);\n const meta: EmittedMeta = {\n target: c.plan.meta.target,\n verb: c.plan.meta.verb,\n model: c.plan.meta.model,\n split: c.plan.meta.split,\n readOnly: c.plan.meta.readOnly,\n render: c.plan.meta.render,\n setupScope: c.plan.meta.setupScope,\n };\n return componentBlock(fn, c.node.verb, c.plan.options, meta);\n });\n\n return [\n header,\n \"\",\n standalone ? STANDALONE_IMPORTS : THIN_IMPORTS,\n \"\",\n PREAMBLE_TYPES,\n ...(standalone ? [\"\", STANDALONE_HELPERS] : []),\n \"\",\n ...blocks,\n \"\",\n ].join(\"\\n\");\n}\n","/**\n * Typed view of the Warble IR (`warble_ir_version` 0.6) that this back-end consumes.\n *\n * Mirrors `docs/spec/ir-schema.md` field-for-field — the SAME contract the Rust `claude-code-cli`\n * back-end reads (`dispatcher/claude-code-cli/src/ir.rs`). The IR JSON is the language-neutral seam:\n * this module depends on the schema doc, not on the front-end's Rust types, and never links the Rust\n * core. That a TypeScript runtime consumes the identical `ir.json` a Rust front-end emits is exactly\n * what this back-end exists to prove.\n *\n * Enum values not yet realized by this target are rejected at dispatch time (a \"wall-hit\"), not\n * here: parsing accepts every schema-valid value so the loud-fail names the *capability*, not a\n * deserialization error.\n */\nimport { DispatchError } from \"./error.js\";\n\n/** `realization_kind` — how a component is realized. */\nexport type RealizationKind = \"skill\" | \"tool\" | \"gated-tool\";\n\n/** Component family. */\nexport type ComponentType =\n | \"analytical\"\n | \"assertive\"\n | \"mutating\"\n | \"constitutive\"\n | \"orchestrating\";\n\n/** `trigger.kind`. */\nexport type TriggerKind = \"one_shot\" | \"scheduled\" | \"event\";\n\n/** `effect.outcome.kind`. */\nexport type OutcomeKind = \"none\" | \"assertion\" | \"mutation\" | \"dispatch\";\n\nexport const REALIZATION_KINDS: readonly RealizationKind[] = [\"skill\", \"tool\", \"gated-tool\"];\nexport const COMPONENT_TYPES: readonly ComponentType[] = [\n \"analytical\",\n \"assertive\",\n \"mutating\",\n \"constitutive\",\n \"orchestrating\",\n];\nexport const TRIGGER_KINDS: readonly TriggerKind[] = [\"one_shot\", \"scheduled\", \"event\"];\nexport const OUTCOME_KINDS: readonly OutcomeKind[] = [\"none\", \"assertion\", \"mutation\", \"dispatch\"];\n\nexport interface ContextBinding {\n project: string;\n binding_mode: string;\n /**\n * Fine-grained resolved binding (IR v0.3): metrics/dimensions/grains + lineage summary the\n * front-end learned from the bound semantic layer. Carried through and tolerated; this back-end\n * does not yet consume it (it drives off the coarse project path).\n */\n resolved?: unknown;\n}\n\n/**\n * The IR's profile-level `config` block. Empty since IR `0.6` removed `tier_policy` (an inert\n * field no back-end read); kept as a type so future profile-level config is an additive change.\n */\nexport type IrConfig = Record<string, never>;\n\n/**\n * A per-step LLM call. `tier` is an **open string** (standard core: `strong`/`cheap`; custom names\n * allowed) resolved to a concrete model at dispatch by the model config. The v0.2 named I/O contract\n * (`consumes`/`produces`) + per-step `prompt` make a step realizable in isolation; an in-loop runtime\n * like this one carries context itself and does not need them for single-session delegation.\n */\nexport interface LlmCall {\n name: string;\n tier: string;\n consumes: string[];\n produces: string | null;\n prompt: string;\n conditional: boolean;\n /**\n * The closed-vocabulary guard deciding whether a `conditional` step runs (IR v0.3+; see\n * `docs/spec/ir-schema.md`). Realized by the hybrid-staged executor (`run.ts`, `conditional.ts`):\n * an `on_failure` guard whose target is the adjacent producing step folds that step into a bounded\n * repair turn; every other guard shape is a deterministic run/skip decision. The single/sdk-split\n * paths ride the SDK's own in-loop `query()`, where Claude judges the condition emergently from the\n * prompt text instead.\n */\n when: WhenGuard | null;\n}\n\n/**\n * A closed-vocabulary guard on a conditional `llm_call`: `guard` is one of `on_failure` /\n * `on_flag` / `on_missing`, `target` is the guard-specific argument. See `docs/spec/ir-schema.md`.\n */\nexport interface WhenGuard {\n guard: string;\n target: string;\n}\n\nexport interface Guardrail {\n name: string;\n locked: boolean;\n scope: string | null;\n threshold?: unknown;\n}\n\n/** A context precondition a component requires to hold before it runs (e.g. `has_metric`). */\nexport interface Precondition {\n predicate: string;\n args?: Record<string, unknown>;\n}\n\n/**\n * A component parameter, either bound at dispatch time (`bind`, with an optional `default`) or\n * sourced from context (`source`). Exactly one of `bind`/`source` is expected per the schema.\n */\nexport interface ParamSpec {\n name: string;\n bind?: string;\n source?: string;\n default?: unknown;\n}\n\n/** An authored evaluation spec: which eval template to run and which metrics it scores. */\nexport interface EvalSpec {\n template_ref: string;\n metrics: string[];\n}\n\nexport interface Trigger {\n kind: TriggerKind;\n}\n\n/** A typed render block: a type plus its field-name → field-type schema (echoed verbatim). */\nexport interface RenderBlock {\n type: string;\n fields: Record<string, string>;\n}\n\nexport interface Outcome {\n kind: OutcomeKind;\n verdict_type?: string;\n emits?: string[];\n target?: string;\n change_type?: string;\n routable_scope?: unknown;\n}\n\nexport interface Effect {\n render_blocks: RenderBlock[];\n outcome: Outcome;\n}\n\n/** One evaluated `context_precondition` and its outcome (IR v0.3: structured, was a string list). */\nexport interface PreconditionCheck {\n predicate: string;\n outcome: string;\n}\n\nexport interface PreconditionResult {\n status: string;\n checks: PreconditionCheck[];\n}\n\nexport interface ComponentNode {\n id: string;\n verb: string;\n type: ComponentType;\n realization_kind: RealizationKind;\n context_binding: ContextBinding;\n precondition_result: PreconditionResult;\n prompt_fragment: string;\n llm_calls: LlmCall[];\n guardrails: Guardrail[];\n trigger: Trigger;\n required_capabilities: string[];\n borrowed_actions: string[];\n eval_ref: string;\n effect: Effect;\n context_requirements: string[];\n context_precondition: Precondition[];\n params: ParamSpec[];\n eval: EvalSpec | null;\n /** Optional free-form framing shared by every step of this component (see `docs/spec/ir-schema.md`). */\n brief?: string;\n}\n\nexport interface WarbleIr {\n warble_ir_version: string;\n profile: string;\n context_binding: ContextBinding;\n config: IrConfig;\n components: ComponentNode[];\n}\n\n/**\n * IR versions this back-end understands. Older versions (0.1, 0.2) are no longer accepted now that\n * the front-end only emits 0.3 — see the compatibility matrix in `docs/spec/ir-schema.md`. An\n * unrecognized version is a loud-fail rather than a silent best-effort read.\n */\nexport const SUPPORTED_IR_VERSIONS: readonly string[] = [\"0.6\"];\n\n/**\n * The one version gate every IR-consuming entry point in this package must call before doing\n * anything else with an IR — not just {@link parseIr}'s string-input path. `prepareDispatch`\n * (`dispatch.ts`) accepts an already-parsed `WarbleIr` object as well as a raw JSON string; an\n * object handed in directly (e.g. `JSON.parse(raw)` widened to `WarbleIr` by the caller, or an IR\n * built programmatically) never passes through `parseIr`, so `parseIr` alone cannot be the only\n * place this is checked. Call this on `ir.warble_ir_version` from every such entry point.\n */\nexport function assertSupportedIrVersion(version: string): void {\n if (!SUPPORTED_IR_VERSIONS.includes(version)) {\n throw new DispatchError(\n `unsupported warble_ir_version '${version}' (this back-end understands: ${SUPPORTED_IR_VERSIONS.join(\", \")})`,\n );\n }\n}\n\n// --- minimal runtime validation (the seam has no compile-time guarantee across the JSON boundary) --\n//\n// We validate presence + type of the load-bearing fields and enum membership only. We do NOT re-run\n// the front-end's compile-time checks (bind-required, locked-guardrail override, precondition) —\n// the IR is already resolved; those are the compiler's responsibility.\n\ntype Json = Record<string, unknown>;\n\nfunction isObject(value: unknown): value is Json {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction fail(message: string): never {\n throw new DispatchError(`invalid IR: ${message}`);\n}\n\nfunction requireObject(value: unknown, at: string): Json {\n if (!isObject(value)) fail(`${at} must be an object`);\n return value;\n}\n\nfunction requireString(obj: Json, key: string, at: string): string {\n const value = obj[key];\n if (typeof value !== \"string\") fail(`${at}.${key} must be a string`);\n return value;\n}\n\nfunction requireBool(obj: Json, key: string, at: string): boolean {\n const value = obj[key];\n if (typeof value !== \"boolean\") fail(`${at}.${key} must be a boolean`);\n return value;\n}\n\nfunction optString(obj: Json, key: string): string | null {\n const value = obj[key];\n if (value === undefined || value === null) return null;\n if (typeof value !== \"string\") fail(`${key} must be a string when present`);\n return value;\n}\n\n/** Like {@link optString}, but returns `undefined` (not `null`) when absent — for `?:` fields. */\nfunction optStringU(obj: Json, key: string): string | undefined {\n const value = obj[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") fail(`${key} must be a string when present`);\n return value;\n}\n\n/** Array of strings defaulting to `undefined` (not `[]`) when absent — for `?:` array fields. */\nfunction optStringArrayU(obj: Json, key: string, at: string): string[] | undefined {\n if (obj[key] === undefined || obj[key] === null) return undefined;\n return requireArray(obj, key, at).map((v, i) => {\n if (typeof v !== \"string\") fail(`${at}.${key}[${i}] must be a string`);\n return v;\n });\n}\n\n/** Boolean defaulting to `false` when the key is absent (matches serde `#[serde(default)]`). */\nfunction boolWithDefault(obj: Json, key: string, at: string): boolean {\n const value = obj[key];\n if (value === undefined) return false;\n if (typeof value !== \"boolean\") fail(`${at}.${key} must be a boolean when present`);\n return value;\n}\n\nfunction requireArray(obj: Json, key: string, at: string): unknown[] {\n const value = obj[key];\n if (!Array.isArray(value)) fail(`${at}.${key} must be an array`);\n return value;\n}\n\n/** Array of strings, defaulting to `[]` when the key is absent (matches serde `#[serde(default)]`). */\nfunction stringArray(obj: Json, key: string, at: string): string[] {\n if (obj[key] === undefined) return [];\n return requireArray(obj, key, at).map((v, i) => {\n if (typeof v !== \"string\") fail(`${at}.${key}[${i}] must be a string`);\n return v;\n });\n}\n\nfunction requireEnum<T extends string>(\n obj: Json,\n key: string,\n at: string,\n allowed: readonly T[],\n): T {\n const value = requireString(obj, key, at);\n if (!(allowed as readonly string[]).includes(value)) {\n fail(`${at}.${key} '${value}' is not one of: ${allowed.join(\", \")}`);\n }\n return value as T;\n}\n\nfunction parseContextBinding(value: unknown, at: string): ContextBinding {\n const obj = requireObject(value, at);\n return {\n project: requireString(obj, \"project\", at),\n binding_mode: requireString(obj, \"binding_mode\", at),\n // v0.3 fine-grained resolved binding; carried opaquely (not consumed by this back-end).\n resolved: obj[\"resolved\"],\n };\n}\n\nfunction parseChecks(obj: Json, at: string): PreconditionCheck[] {\n if (obj[\"checks\"] === undefined) return [];\n return requireArray(obj, \"checks\", at).map((c, i) => {\n const check = requireObject(c, `${at}.checks[${i}]`);\n return {\n predicate: requireString(check, \"predicate\", `${at}.checks[${i}]`),\n outcome: requireString(check, \"outcome\", `${at}.checks[${i}]`),\n };\n });\n}\n\nfunction parseWhenGuard(value: unknown, at: string): WhenGuard {\n const obj = requireObject(value, at);\n return {\n guard: requireString(obj, \"guard\", at),\n target: requireString(obj, \"target\", at),\n };\n}\n\nfunction parseLlmCall(value: unknown, at: string): LlmCall {\n const obj = requireObject(value, at);\n const whenRaw = obj[\"when\"];\n return {\n name: requireString(obj, \"name\", at),\n tier: requireString(obj, \"tier\", at),\n consumes: stringArray(obj, \"consumes\", at),\n produces: optString(obj, \"produces\"),\n prompt: requireString(obj, \"prompt\", at),\n conditional: boolWithDefault(obj, \"conditional\", at),\n when:\n whenRaw === undefined || whenRaw === null ? null : parseWhenGuard(whenRaw, `${at}.when`),\n };\n}\n\nfunction parseGuardrail(value: unknown, at: string): Guardrail {\n const obj = requireObject(value, at);\n return {\n name: requireString(obj, \"name\", at),\n locked: requireBool(obj, \"locked\", at),\n scope: optString(obj, \"scope\"),\n threshold: obj[\"threshold\"],\n };\n}\n\nfunction parsePrecondition(value: unknown, at: string): Precondition {\n const obj = requireObject(value, at);\n const argsRaw = obj[\"args\"];\n const args =\n argsRaw === undefined || argsRaw === null\n ? undefined\n : (requireObject(argsRaw, `${at}.args`) as Record<string, unknown>);\n return { predicate: requireString(obj, \"predicate\", at), args };\n}\n\nfunction parseParamSpec(value: unknown, at: string): ParamSpec {\n const obj = requireObject(value, at);\n return {\n name: requireString(obj, \"name\", at),\n bind: optStringU(obj, \"bind\"),\n source: optStringU(obj, \"source\"),\n default: obj[\"default\"],\n };\n}\n\nfunction parseEvalSpec(value: unknown, at: string): EvalSpec {\n const obj = requireObject(value, at);\n return {\n template_ref: requireString(obj, \"template_ref\", at),\n metrics: stringArray(obj, \"metrics\", at),\n };\n}\n\n/** Array of {@link Precondition}s, defaulting to `[]` when the key is absent. */\nfunction preconditionArray(obj: Json, key: string, at: string): Precondition[] {\n if (obj[key] === undefined) return [];\n return requireArray(obj, key, at).map((v, i) => parsePrecondition(v, `${at}.${key}[${i}]`));\n}\n\n/** Array of {@link ParamSpec}s, defaulting to `[]` when the key is absent. */\nfunction paramArray(obj: Json, key: string, at: string): ParamSpec[] {\n if (obj[key] === undefined) return [];\n return requireArray(obj, key, at).map((v, i) => parseParamSpec(v, `${at}.${key}[${i}]`));\n}\n\nfunction parseRenderBlock(value: unknown, at: string): RenderBlock {\n const obj = requireObject(value, at);\n const fieldsRaw = obj[\"fields\"];\n const fields: Record<string, string> = {};\n if (fieldsRaw !== undefined) {\n const fieldsObj = requireObject(fieldsRaw, `${at}.fields`);\n for (const [k, v] of Object.entries(fieldsObj)) {\n if (typeof v !== \"string\") fail(`${at}.fields.${k} must be a string`);\n fields[k] = v;\n }\n }\n return { type: requireString(obj, \"type\", at), fields };\n}\n\nfunction parseOutcome(value: unknown, at: string): Outcome {\n const obj = requireObject(value, at);\n return {\n kind: requireEnum(obj, \"kind\", at, OUTCOME_KINDS),\n verdict_type: optStringU(obj, \"verdict_type\"),\n emits: optStringArrayU(obj, \"emits\", at),\n target: optStringU(obj, \"target\"),\n change_type: optStringU(obj, \"change_type\"),\n routable_scope: obj[\"routable_scope\"],\n };\n}\n\nfunction parseEffect(value: unknown, at: string): Effect {\n const obj = requireObject(value, at);\n const blocks =\n obj[\"render_blocks\"] === undefined\n ? []\n : requireArray(obj, \"render_blocks\", at).map((b, i) =>\n parseRenderBlock(b, `${at}.render_blocks[${i}]`),\n );\n return {\n render_blocks: blocks,\n outcome: parseOutcome(obj[\"outcome\"], `${at}.outcome`),\n };\n}\n\nfunction parseComponent(value: unknown, at: string): ComponentNode {\n const obj = requireObject(value, at);\n const precondition = requireObject(obj[\"precondition_result\"], `${at}.precondition_result`);\n const trigger = requireObject(obj[\"trigger\"], `${at}.trigger`);\n return {\n id: requireString(obj, \"id\", at),\n verb: requireString(obj, \"verb\", at),\n type: requireEnum(obj, \"type\", at, COMPONENT_TYPES),\n realization_kind: requireEnum(obj, \"realization_kind\", at, REALIZATION_KINDS),\n context_binding: parseContextBinding(obj[\"context_binding\"], `${at}.context_binding`),\n precondition_result: {\n status: requireString(precondition, \"status\", `${at}.precondition_result`),\n checks: parseChecks(precondition, `${at}.precondition_result`),\n },\n prompt_fragment: requireString(obj, \"prompt_fragment\", at),\n llm_calls: requireArray(obj, \"llm_calls\", at).map((c, i) =>\n parseLlmCall(c, `${at}.llm_calls[${i}]`),\n ),\n guardrails: requireArray(obj, \"guardrails\", at).map((g, i) =>\n parseGuardrail(g, `${at}.guardrails[${i}]`),\n ),\n trigger: { kind: requireEnum(trigger, \"kind\", `${at}.trigger`, TRIGGER_KINDS) },\n required_capabilities: stringArray(obj, \"required_capabilities\", at),\n borrowed_actions: stringArray(obj, \"borrowed_actions\", at),\n eval_ref: requireString(obj, \"eval_ref\", at),\n effect: parseEffect(obj[\"effect\"], `${at}.effect`),\n context_requirements: stringArray(obj, \"context_requirements\", at),\n context_precondition: preconditionArray(obj, \"context_precondition\", at),\n params: paramArray(obj, \"params\", at),\n eval:\n obj[\"eval\"] === undefined || obj[\"eval\"] === null\n ? null\n : parseEvalSpec(obj[\"eval\"], `${at}.eval`),\n brief: optStringU(obj, \"brief\"),\n };\n}\n\n/**\n * Parse + validate a Warble IR JSON document. Throws a {@link DispatchError} (loud-fail) on an\n * unsupported version, a missing/mistyped load-bearing field, or an out-of-vocabulary enum value.\n */\nexport function parseIr(json: string): WarbleIr {\n let root: unknown;\n try {\n root = JSON.parse(json);\n } catch (e) {\n fail(`not valid JSON: ${(e as Error).message}`);\n }\n const obj = requireObject(root, \"<root>\");\n\n const version = requireString(obj, \"warble_ir_version\", \"<root>\");\n assertSupportedIrVersion(version);\n\n const configRaw = obj[\"config\"];\n const config: IrConfig = {};\n if (configRaw !== undefined) {\n requireObject(configRaw, \"config\");\n }\n\n return {\n warble_ir_version: version,\n profile: requireString(obj, \"profile\", \"<root>\"),\n context_binding: parseContextBinding(obj[\"context_binding\"], \"context_binding\"),\n config,\n components: requireArray(obj, \"components\", \"<root>\").map((c, i) =>\n parseComponent(c, `components[${i}]`),\n ),\n };\n}\n\n/** Distinct tier names across a node's `llm_calls`, order-preserving. */\nexport function distinctTiers(calls: readonly LlmCall[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const call of calls) {\n if (!seen.has(call.tier)) {\n seen.add(call.tier);\n out.push(call.tier);\n }\n }\n return out;\n}\n","/**\n * Tier → concrete model binding, resolved at **dispatch** (the runtime-injected mapping).\n *\n * TS sibling of the Rust file target's `models.rs`, and deliberately the same concept + the same\n * `--models-config` YAML format: a tier travels in the IR as a name\n * (`strong`/`cheap`, or custom); which model it becomes is decided here, not in the IR, so the same\n * compiled IR runs against different models (the axis the eval loop ablates). A tier with no mapping\n * is a loud-fail.\n *\n * For the Agent SDK target a tier maps to a **model alias/id** passed to `query({ options.model })`\n * (top-level, free-form). The per-step-tier `agents[].model` field is a restricted alias union\n * (`sonnet|opus|haiku|inherit`) — see SDK-NOTES.md; the standard core tiers map onto it, custom\n * tiers on that path do not (handled in run.ts).\n *\n * **This is one of two implementations of the single, versioned binding spec** documented in\n * `docs/spec/binding-spec.md` (the authoritative source; the Rust sibling is\n * `dispatcher/claude-code-cli/src/models.rs`). `BINDING_SPEC_VERSION` must match the version\n * declared in that doc and in the Rust file — bump all three together.\n */\nimport { parse as parseYaml } from \"yaml\";\nimport { DispatchError } from \"./error.js\";\nimport type { LlmCall, WarbleIr } from \"./ir.js\";\n\nconst STRONG_TIER = \"strong\";\nconst CHEAP_TIER = \"cheap\";\n/** Reserved dispatch-role tier for the per-step-tier driver's routing loop (never authored). */\nconst ORCHESTRATOR_TIER = \"orchestrator\";\n\n/** The binding spec version this module implements — see `docs/spec/binding-spec.md`, the\n * authoritative, versioned source both back-ends conform to (kept in lockstep to avoid the IR's\n * own version-drift history). */\nexport const BINDING_SPEC_VERSION = \"1.0\";\n\n/** Well-known provider name: rides the Claude runtime (the default when `provider` is absent). */\nexport const ANTHROPIC_PROVIDER = \"anthropic\";\n/** Well-known provider name: an OpenAI-compatible endpoint (e.g. ollama's `/v1`); requires `endpoint`. */\nexport const OPENAI_COMPAT_PROVIDER = \"openai_compat\";\n\n/**\n * Which provider serves a tier's model — an **open string**, opaque to warble (mirrors how the IR\n * treats `tier`; see `docs/spec/binding-spec.md`). Two well-known values get behavior baked into\n * `TierBinding` parsing below (`ANTHROPIC_PROVIDER`, the default; `OPENAI_COMPAT_PROVIDER`, which\n * requires `endpoint`), but warble does **not** validate this field against a fixed provider list —\n * any other string is a valid, warble-unrecognized provider that passes through unchanged.\n * Rejecting a genuinely unsupported provider is the consuming harness/back-end's job (its\n * per-provider adapter registry), never warble's — warble stays opaque pass-through.\n */\nexport type Provider = string;\n\n/**\n * A tier's full runtime binding: which `provider` serves it, at what `endpoint` (OpenAI-compat only),\n * running which `model`. The shorthand YAML form `tier: <model>` is `{ provider: 'anthropic',\n * endpoint: null, model }` — so existing configs (and every all-cloud path) are byte-for-byte\n * unchanged. Per-step provider routing reads `provider`/`endpoint`; `require()` reads `model`.\n */\nexport interface TierBinding {\n provider: Provider;\n endpoint: string | null;\n model: string;\n}\n\nfunction anthropicBinding(model: string): TierBinding {\n return { provider: ANTHROPIC_PROVIDER, endpoint: null, model };\n}\n\n/**\n * An ordered tier→binding map. Declaration order is priority: earlier tiers are \"stronger\" — used to\n * pick the single model when a multi-tier component collapses to one call.\n */\nexport class ModelConfig {\n /** `[tier name, binding]` in declaration order (earliest = strongest). */\n private readonly tiers: ReadonlyArray<readonly [string, TierBinding]>;\n\n private constructor(tiers: ReadonlyArray<readonly [string, TierBinding]>) {\n this.tiers = tiers;\n }\n\n /** The Agent SDK defaults, matching the file target: strong→opus, cheap→haiku, orchestrator→sonnet. */\n static default(): ModelConfig {\n return new ModelConfig([\n [STRONG_TIER, anthropicBinding(\"opus\")],\n [CHEAP_TIER, anthropicBinding(\"haiku\")],\n [ORCHESTRATOR_TIER, anthropicBinding(\"sonnet\")],\n ]);\n }\n\n /**\n * Build from the inline `--strong/--cheap/--orchestrator` flags. Inline flags are always\n * Anthropic-provider aliases — provider/endpoint routing is `--models-config` only, so a non-alias\n * inline flag still loud-fails on the SDK split path (unchanged behavior).\n */\n static fromFlags(strong: string, cheap: string, orchestrator: string): ModelConfig {\n return new ModelConfig([\n [STRONG_TIER, anthropicBinding(strong)],\n [CHEAP_TIER, anthropicBinding(cheap)],\n [ORCHESTRATOR_TIER, anthropicBinding(orchestrator)],\n ]);\n }\n\n /**\n * Parse a `--models-config` YAML document — the same shape the file target accepts. A tier value is\n * EITHER a bare model-alias string (Anthropic shorthand) OR a `{ provider, endpoint?, model }` map:\n *\n * ```yaml\n * tiers:\n * strong: opus # shorthand ⇒ provider: anthropic\n * cheap: # structured binding (docs/spec/capability-model.md §7.2)\n * provider: openai_compat\n * endpoint: http://localhost:11434/v1\n * model: qwen2.5\n * orchestrator: sonnet # reserved: the per-step-tier driver\n * ```\n */\n static fromYaml(text: string): ModelConfig {\n let doc: unknown;\n try {\n doc = parseYaml(text);\n } catch (e) {\n throw new DispatchError(`invalid models config: ${(e as Error).message}`);\n }\n if (typeof doc !== \"object\" || doc === null) {\n throw new DispatchError(\"invalid models config: expected a mapping with a `tiers:` key\");\n }\n const tiersRaw = (doc as Record<string, unknown>)[\"tiers\"];\n if (typeof tiersRaw !== \"object\" || tiersRaw === null || Array.isArray(tiersRaw)) {\n throw new DispatchError(\"models config: `tiers` must be a mapping\");\n }\n const tiers: Array<[string, TierBinding]> = [];\n for (const [name, value] of Object.entries(tiersRaw)) {\n tiers.push([name, parseTierValue(name, value)]);\n }\n if (tiers.length === 0) {\n throw new DispatchError(\"models config: `tiers` must not be empty\");\n }\n return new ModelConfig(tiers);\n }\n\n private bindingFor(tier: string): TierBinding | undefined {\n return this.tiers.find(([name]) => name === tier)?.[1];\n }\n\n /** Priority rank of a tier (declaration order); unknown tiers rank last. */\n private rank(tier: string): number {\n const idx = this.tiers.findIndex(([name]) => name === tier);\n return idx === -1 ? Number.MAX_SAFE_INTEGER : idx;\n }\n\n private tierNames(): string {\n return this.tiers.map(([name]) => name).join(\", \");\n }\n\n /** The model a tier maps to, or a loud-fail naming the undefined tier. */\n require(tier: string): string {\n return this.binding(tier).model;\n }\n\n /**\n * The full `{provider, endpoint, model}` binding a tier maps to (see docs/spec/capability-model.md\n * §7.2), or a loud-fail.\n * The per-step provider router (route.ts) reads this to send a step cloud-vs-local.\n */\n binding(tier: string): TierBinding {\n const b = this.bindingFor(tier);\n if (b === undefined) {\n throw new DispatchError(\n `tier '${tier}' has no model binding — define it in --models-config or via ` +\n `--strong/--cheap (known tiers: ${this.tierNames()})`,\n );\n }\n return b;\n }\n\n /** The model for the reserved `orchestrator` tier, or a loud-fail if a config omitted it. */\n orchestrator(): string {\n return this.require(ORCHESTRATOR_TIER);\n }\n\n /** The model for a single collapsed call: the strongest (lowest-rank) tier among the calls. */\n collapsedModel(calls: readonly LlmCall[]): string {\n if (calls.length === 0) {\n throw new DispatchError(\"component has no llm_calls; cannot select a model\");\n }\n let strongest = calls[0]!;\n for (const call of calls) {\n if (this.rank(call.tier) < this.rank(strongest.tier)) strongest = call;\n }\n return this.require(strongest.tier);\n }\n\n /** Validate every step tier in the IR maps to a model (front-loaded so dispatch is infallible). */\n validate(ir: WarbleIr): void {\n const checked = new Set<string>();\n for (const node of ir.components) {\n for (const call of node.llm_calls) {\n if (!checked.has(call.tier)) {\n checked.add(call.tier);\n this.require(call.tier);\n }\n }\n }\n }\n}\n\n/** A tier value: a bare model-alias string (Anthropic shorthand) or a `{provider, endpoint?, model}` map. */\nfunction parseTierValue(name: string, value: unknown): TierBinding {\n if (typeof value === \"string\") {\n return anthropicBinding(value);\n }\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new DispatchError(\n `models config: tier '${name}' must be a model-alias string or a {provider, endpoint?, model} map`,\n );\n }\n const map = value as Record<string, unknown>;\n const model = map[\"model\"];\n if (typeof model !== \"string\") {\n throw new DispatchError(`models config: tier '${name}' map is missing a string \\`model\\``);\n }\n // `provider` is an open string (opaque pass-through) — any value parses; only the two\n // well-known names get special handling (default / endpoint requirement) below.\n const providerRaw = map[\"provider\"];\n let provider: Provider = ANTHROPIC_PROVIDER;\n if (providerRaw !== undefined) {\n if (typeof providerRaw !== \"string\") {\n throw new DispatchError(`models config: tier '${name}' has a non-string \\`provider\\``);\n }\n provider = providerRaw;\n }\n const endpointRaw = map[\"endpoint\"];\n const endpoint = typeof endpointRaw === \"string\" ? endpointRaw : null;\n if (provider === OPENAI_COMPAT_PROVIDER && endpoint === null) {\n throw new DispatchError(\n `models config: tier '${name}' uses provider openai_compat but has no \\`endpoint\\``,\n );\n }\n return { provider, endpoint, model };\n}\n","/**\n * Per-step provider routing — the hybrid-LLM core (see docs/spec/capability-model.md §7.2).\n *\n * The IR only knows *tiers*; the `--models-config` binding (models.ts) resolves each tier to a\n * `{ provider, endpoint, model }`. When every step's provider is `anthropic`, the existing single\n * `query()` loop (options.ts: single / sdk-split path) realizes the component and this module changes\n * nothing. When ANY step binds to a non-Anthropic provider (e.g. ollama over OpenAI-compat), that step\n * CANNOT ride the SDK `agents[].model` mechanism — that field is a restricted `sonnet|opus|haiku|inherit`\n * alias union and loud-fails on anything else (SDK-NOTES.md #1). So the back-end must drive the steps\n * itself: run each step as an isolated invocation on its own provider and marshal state between them via\n * the IR's `consumes`/`produces` contract. That staged executor is the \"hybrid-staged\" mode.\n *\n * This module is PURE (no SDK, no network): it resolves the per-step bindings, decides the routing\n * mode, and builds the marshaling messages. The actual per-step execution (a `query()` for cloud\n * steps, an OpenAI-compat call for local steps) lives in run.ts. Keeping the decision pure is what\n * lets the whole hybrid contract be unit-tested offline, with no ollama and no Claude subscription.\n *\n * Invariant: none of this is in the IR, the components, or the profile — hybrid is entirely\n * a layer-3 binding + back-end realization concern. The same compiled IR runs all-cloud or hybrid; only\n * the injected `--models-config` differs.\n */\nimport type { LlmCall, ComponentNode, WhenGuard } from \"./ir.js\";\nimport type { ModelConfig, Provider } from \"./models.js\";\n\n/** A step with its tier resolved to a concrete `{provider, endpoint, model}` binding + its IO contract. */\nexport interface StagedStep {\n name: string;\n tier: string;\n provider: Provider;\n endpoint: string | null;\n model: string;\n consumes: string[];\n produces: string | null;\n prompt: string;\n conditional: boolean;\n /** The closed-vocabulary guard deciding run/skip/repair for a `conditional` step; `null` when\n * `conditional` is false. Realized by run.ts's staged executor (see conditional.ts). */\n when: WhenGuard | null;\n}\n\n/**\n * How a component's steps are realized:\n * - `single` — one tier (or a tier collapse), one Anthropic `query()`. Existing path.\n * - `sdk-split` — >1 Anthropic tier, per-step subagents in one `query()` via `agents`. Existing path.\n * - `hybrid-staged` — ≥1 non-Anthropic provider; the back-end drives steps itself, one isolated\n * invocation per step, marshaling `produces`→`consumes`.\n */\nexport type RoutingMode = \"single\" | \"sdk-split\" | \"hybrid-staged\";\n\nexport interface RoutingPlan {\n mode: RoutingMode;\n /** Per-step resolved bindings (order = IR order). */\n steps: StagedStep[];\n /** Distinct providers across the steps, order-preserving. */\n providers: Provider[];\n}\n\n/** Resolve every `llm_call`'s tier to a concrete binding, preserving IR order. Pure. */\nexport function resolveStagedSteps(node: ComponentNode, models: ModelConfig): StagedStep[] {\n return node.llm_calls.map((call: LlmCall) => {\n const binding = models.binding(call.tier);\n return {\n name: call.name,\n tier: call.tier,\n provider: binding.provider,\n endpoint: binding.endpoint,\n model: binding.model,\n consumes: call.consumes,\n produces: call.produces,\n prompt: call.prompt,\n conditional: call.conditional,\n when: call.when,\n };\n });\n}\n\n/** Distinct providers across resolved steps, order-preserving. */\nexport function distinctProviders(steps: readonly StagedStep[]): Provider[] {\n const seen = new Set<Provider>();\n const out: Provider[] = [];\n for (const s of steps) {\n if (!seen.has(s.provider)) {\n seen.add(s.provider);\n out.push(s.provider);\n }\n }\n return out;\n}\n\n/** True when any step binds to a non-Anthropic provider — the trigger for the hybrid-staged path. */\nexport function usesLocalProvider(steps: readonly StagedStep[]): boolean {\n return steps.some((s) => s.provider !== \"anthropic\");\n}\n\n/**\n * Decide the routing mode for a component under a binding. `anthropicSplit` is the existing\n * per-step-tier split decision (owned by options.ts, passed in to keep a single source of truth):\n * it only applies when every provider is Anthropic.\n */\nexport function planProviderRouting(\n node: ComponentNode,\n models: ModelConfig,\n anthropicSplit: boolean,\n): RoutingPlan {\n const steps = resolveStagedSteps(node, models);\n const providers = distinctProviders(steps);\n let mode: RoutingMode;\n if (usesLocalProvider(steps)) {\n mode = \"hybrid-staged\";\n } else if (anthropicSplit) {\n mode = \"sdk-split\";\n } else {\n mode = \"single\";\n }\n return { mode, steps, providers };\n}\n\n/** A chat message for an isolated per-step invocation (both providers speak this shape). */\nexport interface StepMessage {\n role: \"system\" | \"user\";\n content: string;\n}\n\n/**\n * Build the messages for one staged step: the step's own prompt as the system message, and the user\n * message = the question plus each consumed slot's value marshaled in by name (the `produces`→`consumes`\n * hand-off). This is the same isolated-invocation contract the IR already carries for the file target's\n * subagents (ir.ts `consumes`/`produces`), generalized here across providers.\n */\nexport function buildStepMessages(\n step: StagedStep,\n question: string,\n slots: Readonly<Record<string, string>>,\n): StepMessage[] {\n const parts: string[] = [`Question: ${question}`];\n for (const slot of step.consumes) {\n const value = slots[slot];\n parts.push(\n value === undefined\n ? `\\n[input '${slot}' was not produced by an earlier step]`\n : `\\nInput '${slot}':\\n${value}`,\n );\n }\n return [\n { role: \"system\", content: step.prompt },\n { role: \"user\", content: parts.join(\"\\n\") },\n ];\n}\n","/**\n * Target capability profiles — the declarative side of the capability model\n * (`docs/spec/capability-model.md`), owned by THIS back-end in TypeScript.\n *\n * A runtime target is `engine × mode`. This back-end declares one target, `claude-agent-sdk:local`:\n * the local `@anthropic-ai/claude-agent-sdk` `query()` loop (subscription login, compute on the\n * user's machine). The shared thing across back-ends is the IR + the capability-model\n * *semantics* (native / realize-via / degrade / fail, criticality, provided_by); the profile *data*\n * is target-specific and each back-end writes its own. So this file is the TS sibling of\n * the Rust file target's `targets.rs`, not a shared table.\n *\n * How `local` differs from the Rust file target's `claude-code:headless` (the point of the second\n * back-end):\n * - `llm:per_step_tier` native (in-loop per-call model) ← headless: realize-via(subagents)\n * - `structured_output_capture` native (message stream) ← headless: native(stream-json)\n * - `render_contract` realize-via(warble-render) ← headless: realize-via(html-file)\n * The rest match headless, including the safety-critical loud-fails (human_approval, blast_radius).\n */\n\n/** One of the four resolution outcomes a capability can take on a target. */\nexport type CapabilityOutcome = \"native\" | \"realize-via\" | \"degrade\" | \"fail\";\n\n/** Who supplies a resolved capability. */\nexport type ProvidedBy = \"runtime\" | \"warble\" | \"none\";\n\n/**\n * safety-critical capabilities must never silently degrade — unsupported means the resolution pass\n * aborts. required/best-effort may degrade with a warning recorded in the report.\n */\nexport type Criticality = \"safety-critical\" | \"required\" | \"best-effort\";\n\nexport interface CapabilityEntry {\n outcome: CapabilityOutcome;\n via: string | null;\n provided_by: ProvidedBy;\n criticality: Criticality;\n note: string | null;\n}\n\nexport type CapabilityProfile = Record<string, CapabilityEntry>;\n\n/** The one target this back-end declares (engine × mode). */\nexport type TargetId = \"claude-agent-sdk:local\";\n\nexport const DEFAULT_TARGET: TargetId = \"claude-agent-sdk:local\";\n\nconst KNOWN_TARGETS: readonly TargetId[] = [\"claude-agent-sdk:local\"];\n\nexport function isKnownTarget(value: string): value is TargetId {\n return (KNOWN_TARGETS as readonly string[]).includes(value);\n}\n\nexport function knownTargetNames(): readonly string[] {\n return KNOWN_TARGETS;\n}\n\nfunction entry(\n outcome: CapabilityOutcome,\n via: string | null,\n provided_by: ProvidedBy,\n criticality: Criticality,\n note: string | null,\n): CapabilityEntry {\n return { outcome, via, provided_by, criticality, note };\n}\n\n/** Capability profile for `claude-agent-sdk:local`. */\nexport function localProfile(): CapabilityProfile {\n return {\n \"sql_execution:read_only\": entry(\"native\", \"bash-wren\", \"runtime\", \"required\", null),\n genbi_build: entry(\"native\", \"bash-wren\", \"runtime\", \"required\", null),\n // Reading the semantic model's structure (models/metrics/lineage) is borrowed from the `wren`\n // CLI (`wren context show`), same mechanism as sql_execution/genbi_build — realize-via bash-wren.\n // Matches the file target's headless/interactive profiles (not a differentiator across back-ends).\n semantic_introspection: entry(\"realize-via\", \"bash-wren\", \"runtime\", \"required\", null),\n // Reading bound-project raw material is natively available through the SDK's cwd-scoped Read\n // tool. This does not grant Bash, network access, or writes; the read_only_execution guardrail\n // still confines every filesystem access to the resolved project root.\n raw_material_read: entry(\"native\", \"sdk-read\", \"runtime\", \"required\", null),\n // +Constitutive: reading the semantic model's structure to propose a context edit (models/\n // metrics/knowledge) — realized the same way as semantic_introspection, via the `wren` CLI.\n // Matches the file target (not a differentiator across back-ends).\n schema_introspection: entry(\"realize-via\", \"bash-wren\", \"runtime\", \"required\", null),\n // genbi-setup: onboarding a NEW wren project (no pre-bound context yet). Realized the same way as\n // the other `wren`-CLI-backed capabilities — bash-setup covers `wren` onboarding/context-build\n // commands plus (under setup_execution's broadened Bash) connector CLIs like `dlt`. `required`,\n // not safety-critical: unlike human_approval, a target without it should just wall-hit the\n // specific setup component, not gate every other capability.\n source_connect: entry(\"realize-via\", \"bash-setup\", \"runtime\", \"required\", null),\n context_build: entry(\"realize-via\", \"bash-setup\", \"runtime\", \"required\", null),\n \"llm:strong\": entry(\"native\", null, \"runtime\", \"required\", null),\n \"llm:cheap\": entry(\"native\", null, \"runtime\", \"required\", null),\n // The differentiator vs the file target: the SDK varies the model per call in-loop, so per-step\n // tier is NATIVE here — no static subagent files, no isolated-invocation marshaling required.\n \"llm:per_step_tier\": entry(\"native\", \"in-loop-model\", \"runtime\", \"required\", null),\n // Per-step PROVIDER routing (cloud+local mixed in one run) — the hybrid capability, distinct from\n // per_step_tier (same-provider model selection). Warble realizes it two ways (WARBLE_HYBRID_MODE):\n // `staged-executor` (the back-end drives the steps) or `in-process-mcp` (an orchestrator query()\n // calls a dispatch_step tool). provided_by warble because Warble supplies the executor/tool; the\n // model runtimes (Claude SDK loop, ollama) are borrowed.\n \"llm:per_step_provider\": entry(\n \"realize-via\",\n \"staged-executor|in-process-mcp\",\n \"warble\",\n \"required\",\n null,\n ),\n // Reuse the Warble reference renderer (shell out to `warble render`) — realize-via, same\n // deterministic HTML the file target produces.\n render_contract: entry(\"realize-via\", \"warble-render\", \"runtime\", \"best-effort\", null),\n // Captured directly from the query() message stream (usage/cost per step) — no --output-format\n // plumbing needed; it is inherent to the in-loop runtime.\n structured_output_capture: entry(\"native\", \"message-stream\", \"runtime\", \"required\", null),\n // MVP is read-only, so no component requires approval; keep it a safety-critical loud-fail so a\n // future mutating component targeting this profile fails loudly rather than running unapproved.\n human_approval: entry(\n \"fail\",\n null,\n \"none\",\n \"safety-critical\",\n \"no approval channel wired for the programmatic local run in MVP\",\n ),\n write_authz: entry(\"realize-via\", \"fs\", \"runtime\", \"safety-critical\", null),\n artifact_write: entry(\"realize-via\", \"fs\", \"runtime\", \"safety-critical\", null),\n // +Assertive borrows the scheduling / event / notify transports from the runtime (OS cron,\n // pub/sub, MCP). The IR names the capability + criticality only; the mechanism is legalized here,\n // never in the IR (capability-model §6/§7). A target with no mechanism wired keeps these `fail`.\n scheduler: entry(\"realize-via\", \"os-cron\", \"runtime\", \"required\", null),\n event_bus: entry(\"realize-via\", \"pub-sub\", \"runtime\", \"required\", null),\n notify_channel: entry(\"realize-via\", \"mcp-notify\", \"runtime\", \"required\", null),\n blast_radius: entry(\n \"fail\",\n null,\n \"warble\",\n \"safety-critical\",\n \"requires fine_grained_binding\",\n ),\n // +Mutating borrows checkpoint/rollback from version control (git), the same mechanism the\n // workspace conventions already require before a mutating apply. This single SDK target has no\n // human/approval channel wired (see human_approval/blast_radius above), so a mutating component\n // that also requires those still correctly loud-fails here — version_control alone does not\n // authorize the apply.\n version_control: entry(\"realize-via\", \"git\", \"runtime\", \"required\", null),\n };\n}\n\n/** Resolve a target id to its capability profile, or `null` if unknown. */\nexport function profileFor(targetId: string): CapabilityProfile | null {\n return isKnownTarget(targetId) ? localProfile() : null;\n}\n","/**\n * IR enum → `query({options})` mapping — the core of this back-end, the TS analogue of the\n * file target's `emit.rs`. Keyed on the **three orthogonal IR enums** (`realization_kind`,\n * `effect.outcome.kind`, `trigger.kind`), never on a component's id/verb: adding another component\n * of an existing type changes 0 lines here. Enum values this target does not yet\n * realize fail loudly (\"wall-hit\"), mirroring `emit.rs::unsupported`.\n *\n * This module is pure/data: it builds the serializable `query()` options + a metadata report. The\n * live callbacks — `canUseTool` runtime enforcement — are attached by `run.ts` from `guardrails.ts`,\n * so the mapping stays testable offline.\n */\nimport type { AgentDefinition, Options, PermissionMode } from \"@anthropic-ai/claude-agent-sdk\";\n\nimport { DispatchError } from \"./error.js\";\nimport { distinctTiers, type ComponentNode, type Guardrail, type RenderBlock } from \"./ir.js\";\nimport { ModelConfig, type Provider } from \"./models.js\";\nimport type { ResolutionReport } from \"./resolve.js\";\nimport { planProviderRouting, type RoutingMode, type StagedStep } from \"./route.js\";\nimport { profileFor, type Criticality } from \"./targets.js\";\n\nconst PER_STEP_PROVIDER_CAPABILITY = \"llm:per_step_provider\";\n// --- render flavor (docs/spec/ir-schema.md §v0.3 §4) --------------------------------------------\n\nexport type RenderFlavor = \"programmatic\" | \"prompt\";\nexport const DEFAULT_RENDER_FLAVOR: RenderFlavor = \"programmatic\";\n\nexport function parseRenderFlavor(value: string): RenderFlavor {\n if (value === \"programmatic\" || value === \"prompt\") return value;\n throw new DispatchError(\n `unknown --render-flavor '${value}' (expected: programmatic, prompt)`,\n );\n}\n\n// --- constants (mirrors emit.rs) ----------------------------------------------------------------\n\n// Capabilities realized by the `wren` CLI — any of them grants the Bash tool. semantic_introspection\n// (via `wren context show`) belongs here alongside sql_execution/genbi_build (mirrors emit.rs).\n// +Constitutive: schema_introspection (proposing a context edit) is realized the same way, so it\n// grants Bash too.\nconst DATA_ACCESS_CAPABILITIES = [\n \"sql_execution:read_only\",\n \"genbi_build\",\n \"semantic_introspection\",\n \"schema_introspection\",\n // +Setup (genbi-setup): source_connect/context_build are realized via Bash (the `wren` CLI plus,\n // under the setup_execution guardrail below, connector CLIs like `dlt`), so they grant Bash too.\n \"source_connect\",\n \"context_build\",\n];\nconst READ_ONLY_GUARDRAIL_NAME = \"read_only_execution\";\nconst ARTIFACT_WRITE_GUARDRAIL_NAME = \"artifact_write\";\n// The 5th enforcement point (genbi-setup): onboarding a NEW project has no pre-bound context to\n// gate reads against, and its writes are project-scaffolding, not a render artifact or a gated MDL\n// mutation — so it gets its own name-keyed guardrail rather than overloading read_only_execution or\n// artifact_write. Matched by `.name` via `findGuardrail`, exactly like the other four.\nconst SETUP_GUARDRAIL_NAME = \"setup_execution\";\nconst RENDER_CONTRACT_CAPABILITY = \"render_contract\";\nconst DEFAULT_ARTIFACT_SCOPE = \".\";\n/** Bash rule patterns denied outright (defense in depth; canUseTool is the semantic gate). */\nexport const DESTRUCTIVE_BASH_DENY = [\"Bash(rm:*)\", \"Bash(sudo:*)\", \"Bash(dd:*)\"];\nconst DEFAULT_MAX_TURNS = 40;\n\nfunction unsupported(field: string, value: string): DispatchError {\n return new DispatchError(\n `${field} '${value}' is not supported by the claude-agent-sdk:local target (wall-hit)`,\n );\n}\n\n// --- handler support checks (documented extension points; loud-fail today) ----------------------\n\n/** `realization_kind`: `skill` (MVP) + `tool` (+Assertive; independently-invoked monitor) + `gated-tool`\n * (+Mutating; a tool behind a hard approval gate — dry-run/blast-radius/human-approval/rollback). */\nfunction realizationSupported(node: ComponentNode): boolean {\n return (\n node.realization_kind === \"skill\" ||\n node.realization_kind === \"tool\" ||\n node.realization_kind === \"gated-tool\"\n );\n}\n\n/** `trigger.kind`: `one_shot` (MVP) + `scheduled` (+Assertive; cadence borrowed from the runtime\n * scheduler). `event` (activation by an inbound event) is not yet a realized handler and loud-fails\n * here, even though the `event_bus` transport it would borrow is now realize-via. */\nfunction triggerSupported(node: ComponentNode): boolean {\n return node.trigger.kind === \"one_shot\" || node.trigger.kind === \"scheduled\";\n}\n\n/** `effect.outcome.kind`: `none` (render-only, MVP) + `assertion` (+Assertive: read-only verdict +\n * emitted signal) + `mutation` (+Mutating: gated dry-run/apply). `dispatch` still loud-fails\n * (+Orchestrating). */\nfunction outcomeSupported(node: ComponentNode): boolean {\n return (\n node.effect.outcome.kind === \"none\" ||\n node.effect.outcome.kind === \"assertion\" ||\n node.effect.outcome.kind === \"mutation\"\n );\n}\n\n/** Whether this component's outcome is an `assertion` — keyed on the outcome enum, never id/verb. */\nfunction isAssertion(node: ComponentNode): boolean {\n return node.effect.outcome.kind === \"assertion\";\n}\n\n/** Whether this component's outcome is a `mutation` (+Mutating) — keyed on the outcome enum, never\n * id/verb. */\nexport function isMutation(node: ComponentNode): boolean {\n return node.effect.outcome.kind === \"mutation\";\n}\n\n// --- helpers ------------------------------------------------------------------------------------\n\nfunction hasDataAccess(caps: readonly string[]): boolean {\n return caps.some((c) => DATA_ACCESS_CAPABILITIES.includes(c));\n}\n\nfunction isReadOnly(guardrails: readonly Guardrail[]): boolean {\n return guardrails.some((g) => g.name === READ_ONLY_GUARDRAIL_NAME);\n}\n\n/** True when this component carries the `setup_execution` guardrail (genbi-setup's onboarding\n * flavor) — matched by name, same as every other enforcement point. */\nfunction isSetup(guardrails: readonly Guardrail[]): boolean {\n return guardrails.some((g) => g.name === SETUP_GUARDRAIL_NAME);\n}\n\nfunction findGuardrail(guardrails: readonly Guardrail[], name: string): Guardrail | undefined {\n return guardrails.find((g) => g.name === name);\n}\n\n/** The project root a setup component may write into (`Write`/`Edit` + broadened Bash), or `null`\n * when the component does not declare `setup_execution`. Defaults to `.`, mirroring\n * `DEFAULT_ARTIFACT_SCOPE`. */\nfunction computeSetupScope(guardrails: readonly Guardrail[]): string | null {\n const g = findGuardrail(guardrails, SETUP_GUARDRAIL_NAME);\n if (!g) return null;\n return g.scope ?? DEFAULT_ARTIFACT_SCOPE;\n}\n\n/**\n * Per-step-tier split: a component whose steps span >1 tier. Realized in-loop via SDK `agents`.\n * Realization-independent (see `resolve.ts::impliedCapabilities`) — driven purely by IR shape\n * (>1 distinct step tier), never by `realization_kind` nor by whether the component happens to\n * also *declare* `llm:per_step_tier` itself: that declaration is shape-implied, not authored, so\n * requiring it redundantly would reintroduce the same silent-collapse failure for a tool/gated-tool\n * component that never bothered to self-declare a capability the compiler already derives for it.\n */\nexport function shouldSplitPerStepTier(node: ComponentNode): boolean {\n return distinctTiers(node.llm_calls).length > 1;\n}\n\n// --- render gate --------------------------------------------------------------------------------\n\nexport type GateKind = \"realize\" | \"degrade\" | \"none\";\n\n/**\n * How a RUNTIME render failure (`warble render` exiting non-zero, after the gate already resolved to\n * `realize`) should be handled — distinct from `GateKind`'s `\"degrade\"`, which is a DESIGN-TIME\n * capability degrade (no artifact-write surface at all, so no render is even attempted). Derived from\n * the resolved `render_contract` capability's criticality: `best-effort` → `\"degrade\"` (fall back to\n * the agent's own text, per the capability model's \"best-effort may degrade\" rule); `required` /\n * `safety-critical` → `\"fail\"` (never silently degrade).\n */\nexport type GateFailureMode = \"degrade\" | \"fail\";\n\nexport interface RenderGate {\n kind: GateKind;\n scope: string | null;\n flavor: RenderFlavor | null;\n /** Only meaningful when `kind === \"realize\"` (a runtime render call actually happens). Optional so\n * the facet stays additive: a consumer that doesn't know about it sees `undefined` and must default\n * to today's hard-fail behavior, never assume degrade. */\n onFailure?: GateFailureMode;\n}\n\n/** best-effort degrades on a runtime render failure; required/safety-critical never silently degrade. */\nfunction onFailureFor(criticality: Criticality): GateFailureMode {\n return criticality === \"best-effort\" ? \"degrade\" : \"fail\";\n}\n\n/**\n * The render gate resolves to `realize` only when `render_contract` is `realize-via` on the target\n * AND an `artifact_write` guardrail is declared AND there are render blocks — same shape as the file\n * target. `structured_output_capture` is native here, so the requested flavor is honored as-is.\n */\nfunction resolveRenderGate(\n node: ComponentNode,\n report: ResolutionReport,\n flavor: RenderFlavor,\n): RenderGate {\n const artifactWrite = findGuardrail(node.guardrails, ARTIFACT_WRITE_GUARDRAIL_NAME);\n if (!artifactWrite || node.effect.render_blocks.length === 0) {\n return { kind: \"none\", scope: null, flavor: null };\n }\n const renderEntry = report.find((r) => r.capability === RENDER_CONTRACT_CAPABILITY);\n switch (renderEntry?.outcome) {\n case \"realize-via\":\n return {\n kind: \"realize\",\n scope: artifactWrite.scope ?? DEFAULT_ARTIFACT_SCOPE,\n flavor,\n onFailure: onFailureFor(renderEntry.criticality),\n };\n case \"degrade\":\n return { kind: \"degrade\", scope: null, flavor: null };\n default:\n return { kind: \"none\", scope: null, flavor: null };\n }\n}\n\n/** Only the prompt flavor needs the agent to write the file itself; programmatic keeps it read-only. */\nfunction gateGrantsWrite(gate: RenderGate): boolean {\n return gate.kind === \"realize\" && gate.flavor === \"prompt\";\n}\n\n// --- tools --------------------------------------------------------------------------------------\n\nexport interface ToolPlan {\n /** Base built-in tool set made available to the agent (`tools` option). */\n tools: string[];\n /** Auto-allowed without a permission check. */\n allowedTools: string[];\n /** Hard-removed (defense in depth). */\n disallowedTools: string[];\n}\n\n/**\n * Read-only enforcement, layer 1 (static). `Read` is auto-allowed; `Bash` is available but NOT\n * auto-allowed, so every bash call is routed to `canUseTool` (layer 2, guardrails.ts) for a semantic\n * decision — the file target's allow/deny *strings* can't do that. `Write`/`Edit` are excluded from\n * the base set entirely on the read-only path.\n */\nfunction buildTools(node: ComponentNode, gate: RenderGate): ToolPlan {\n const dataAccess = hasDataAccess(node.required_capabilities);\n const readOnly = isReadOnly(node.guardrails);\n const setup = isSetup(node.guardrails);\n const grantsWrite = gateGrantsWrite(gate);\n const mutating = !readOnly;\n\n const tools = [\"Read\"];\n if (dataAccess) tools.push(\"Bash\");\n if (mutating) tools.push(\"Edit\");\n if (mutating || grantsWrite) tools.push(\"Write\");\n\n const allowedTools = [\"Read\"];\n // Setup components are not read-only (they scaffold a project), so the destructive/redirection\n // Bash denylist would otherwise be dropped along with the read-only floor — keep it explicitly:\n // setup broadens Bash beyond `wren` (canUseTool, guardrails.ts) but never past this denylist.\n const disallowedTools = readOnly || setup ? [...DESTRUCTIVE_BASH_DENY] : [];\n\n return { tools, allowedTools, disallowedTools };\n}\n\n// --- render section text (ports emit.rs) --------------------------------------------------------\n\nconst ENVELOPE_EXAMPLE = `\\`\\`\\`json\n{\n \"blocks\": [\n { \"type\": \"kpi_card\", \"label\": \"Total revenue\", \"value\": 1672.4, \"unit\": \"USD\" },\n { \"type\": \"table\", \"columns\": [\"status\", \"orders\"], \"rows\": [[\"completed\", 67], [\"shipped\", 32]] },\n { \"type\": \"chart\", \"chart_type\": \"bar\", \"x\": \"status\", \"series\": [\"orders\"],\n \"rows\": [[\"completed\", 67], [\"shipped\", 32]] },\n { \"type\": \"definition\", \"sql\": \"SELECT status, count(*) AS orders FROM orders GROUP BY status\",\n \"source_tables\": [\"orders\"], \"filters\": [] }\n ],\n \"verified\": true,\n \"summary\": \"One or two sentences of prose (optional).\"\n}\n\\`\\`\\``;\n\n/**\n * Shared verify + definition contract text (G2 hard line + G3 shallow card) — the exact-word twin of\n * `emit.rs::VERIFY_DEFINITION_CONTRACT`, so both back-ends instruct the agent identically and the one\n * reference renderer (`warble render`) turns the same envelope into identical bytes.\n */\nconst VERIFY_DEFINITION_CONTRACT =\n \"Before you answer you MUST verify (per-answer verify, required): actually execute the query \" +\n \"through `wren`, then validate the result set is legitimate (non-empty where a value is expected, \" +\n \"types/units sane, grain matches the question). If it is not, repair the query and re-run; if it \" +\n \"still cannot be validated, REFUSE — say so plainly and do not fabricate a number. Set the \" +\n 'envelope\\'s top-level `\"verified\": true` ONLY when a query ran and its result set passed ' +\n \"validation. Always include one `definition` block — the shallow \\\"how this was computed\\\" card: \" +\n \"the exact `sql` you ran, the `source_tables` it read, and the `filters` you applied. This is \" +\n \"run-level provenance only; do not invent unit/owner/formal-metric lineage (that is Phase 2).\";\n\nfunction formatRenderBlock(block: RenderBlock): string {\n const fields = Object.entries(block.fields)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return `- \\`${block.type}\\`: { ${fields} }`;\n}\n\nfunction buildProgrammaticRenderSection(node: ComponentNode): string {\n return [\n \"## Render output\",\n \"\",\n \"Block contract (produce data matching these shapes, not prose):\",\n \"\",\n ...node.effect.render_blocks.map(formatRenderBlock),\n \"\",\n \"Do NOT write any files and do NOT format the answer as prose or markdown. After gathering the \" +\n \"data via `wren`, your FINAL message must be a SINGLE JSON object — the render envelope — and \" +\n \"nothing else: a `blocks` array of instances conforming to the contract above, plus an \" +\n \"optional `summary` string. A downstream renderer turns this envelope into the dashboard \" +\n \"deterministically; you stay read-only.\",\n \"\",\n VERIFY_DEFINITION_CONTRACT,\n \"\",\n \"Envelope shape:\",\n \"\",\n ENVELOPE_EXAMPLE,\n ].join(\"\\n\");\n}\n\nfunction buildPromptRenderSection(node: ComponentNode, gate: RenderGate): string {\n const scope = gate.scope ?? DEFAULT_ARTIFACT_SCOPE;\n return [\n \"## Render output\",\n \"\",\n \"Block contract (produce data matching these shapes, not prose):\",\n \"\",\n ...node.effect.render_blocks.map(formatRenderBlock),\n \"\",\n `After gathering the data via \\`wren\\`, write a SINGLE self-contained \\`dashboard.html\\` file ` +\n `into the artifact-write scope directory (\\`${scope}\\`), rendering the blocks above: KPI ` +\n `cards, an HTML table, and a simple chart (inline SVG or a CDN-loaded chart library — no ` +\n `build step). Also render a \\`✓ Verified\\` pill next to the title and a \"how this was ` +\n `computed\" definition panel (the SQL you ran, source tables, filters). End your reply ` +\n `stating the path of the file you wrote.`,\n \"\",\n VERIFY_DEFINITION_CONTRACT,\n ].join(\"\\n\");\n}\n\nfunction buildRenderSection(node: ComponentNode, gate: RenderGate): string | null {\n switch (gate.kind) {\n case \"realize\":\n return gate.flavor === \"prompt\"\n ? buildPromptRenderSection(node, gate)\n : buildProgrammaticRenderSection(node);\n case \"degrade\":\n return [\n \"## Render output\",\n \"\",\n \"This target has no artifact-write surface for render output: render the results as a \" +\n \"markdown table plus a short prose summary instead. Do not write any files.\",\n ].join(\"\\n\");\n case \"none\":\n return null;\n }\n}\n\n// --- assertion outcome section (+Assertive) — the TS twin of emit.rs::build_assertion_section ----\n\nconst VERDICT_ENVELOPE_EXAMPLE = `\\`\\`\\`json\n{\n \"blocks\": [\n { \"type\": \"status\", \"state\": \"stale\", \"label\": \"orders freshness\",\n \"detail\": \"max(order_date) is 51h old; expected within 24h\", \"severity\": \"critical\" }\n ],\n \"verdict\": { \"type\": \"freshness_verdict\", \"fresh\": false, \"observed_lag_hours\": 51, \"expected_cadence\": \"24h\" },\n \"emitted\": [\"freshness_breach\"],\n \"verified\": true\n}\n\\`\\`\\``;\n\n/**\n * The assertion output contract (+Assertive) — structural twin of the programmatic render section.\n * The agent stays fully read-only and emits a single `{ blocks, verdict, emitted }` envelope; the\n * dispatcher's `warble render` turns the `status` block into HTML. The core assert is deterministic\n * SQL (`max(timestamp)` vs cadence); the LLM only classifies severity when stale (`assess_severity`,\n * conditional). `verdict_type`/`emits` come straight from `effect.outcome` — the assertion arm the IR\n * spine already carries.\n */\nfunction buildAssertionSection(node: ComponentNode): string {\n const outcome = node.effect.outcome;\n const verdictType = outcome.verdict_type ?? \"verdict\";\n const emits = outcome.emits ?? [];\n const actions =\n node.borrowed_actions.length > 0\n ? node.borrowed_actions.map((a) => `\\`${a}\\``).join(\", \")\n : \"a runtime notify channel\";\n const emitsLine =\n emits.length === 0\n ? \"This assertion emits no signals.\"\n : `On breach, list the emitted signal name(s) in the envelope's \\`emitted\\` array: ` +\n `[${emits.map((e) => `\\`${e}\\``).join(\", \")}]. The runtime routes those signals to the ` +\n `borrowed on-breach actions (${actions}) over the notify channel — Warble declares the ` +\n `wiring (signal ↔ action); the transport (Slack / Jira / MCP) is borrowed, not owned by ` +\n `this agent.`;\n\n return [\n \"## Assertion output\",\n \"\",\n `This is an **assertive** component (outcome: assertion, verdict_type \\`${verdictType}\\`). Its ` +\n `core is a DETERMINISTIC check, not a judgment call: run the freshness assert through \\`wren\\` ` +\n `— \\`SELECT max(<timestamp column>)\\` on the bound model — and compare the observed lag ` +\n `against the expected cadence (\\`expected_cadence\\` param, or the MDL's declared cadence). ` +\n `Fresh iff the newest row is within the cadence; stale otherwise. Do NOT ask an LLM to decide ` +\n `fresh-vs-stale — that is a SQL comparison and must be reproducible.`,\n \"\",\n \"Only when the data is STALE do you use judgment, via the `assess_severity` step, to classify \" +\n \"how bad it is (e.g. warn vs critical) from the lag magnitude and history. When fresh, there \" +\n \"is no severity to assess.\",\n \"\",\n \"Verdict block contract (produce data matching these shapes, not prose):\",\n \"\",\n ...node.effect.render_blocks.map(formatRenderBlock),\n \"\",\n \"Stay strictly read-only: only `SELECT` through `wren`, never write to the warehouse and never \" +\n \"write any files. Your FINAL message MUST be a SINGLE JSON object — the verdict envelope — and \" +\n \"nothing else: a `blocks` array (the `status` block above), a `verdict` object \" +\n '(`{ type, fresh, ... }`), and, on breach, an `emitted` array. A downstream renderer turns the ' +\n '`status` block into HTML deterministically; you stay read-only. Set the top-level ' +\n '`\"verified\": true` only when the assert query actually ran and its result was validated.',\n \"\",\n emitsLine,\n \"\",\n \"Envelope shape:\",\n \"\",\n VERDICT_ENVELOPE_EXAMPLE,\n ].join(\"\\n\");\n}\n\n// --- mutation outcome section (+Mutating) — the TS twin of buildAssertionSection ----------------\n\nconst MUTATION_DIFF_ENVELOPE_EXAMPLE = `\\`\\`\\`json\n{\n \"blocks\": [\n { \"type\": \"diff\", \"target\": \"models/orders.yml\", \"change_type\": \"update\",\n \"diff\": \"--- a/models/orders.yml\\\\n+++ b/models/orders.yml\\\\n@@ -3,1 +3,1 @@\\\\n- grain: order_id\\\\n+ grain: order_id, order_date\" }\n ],\n \"blast_radius\": { \"downstream_nodes\": [\"metric:total_revenue\"], \"protected_hit\": false },\n \"applied\": false,\n \"verified\": true\n}\n\\`\\`\\``;\n\n// +Constitutive: same envelope shape as the data-mutation twin above, minus the `blast_radius` field\n// — a context-write is gated by scope authorization, not a downstream-lineage impact computation.\nconst CONTEXT_MUTATION_DIFF_ENVELOPE_EXAMPLE = `\\`\\`\\`json\n{\n \"blocks\": [\n { \"type\": \"diff\", \"target\": \"models/orders.yml\", \"change_type\": \"mdl_bootstrap\",\n \"diff\": \"--- a/models/orders.yml\\\\n+++ b/models/orders.yml\\\\n@@ -3,1 +3,1 @@\\\\n- grain: order_id\\\\n+ grain: order_id, order_date\" }\n ],\n \"applied\": false,\n \"verified\": true\n}\n\\`\\`\\``;\n\n/**\n * +Constitutive twin of {@link buildMutationSection} for `outcome.target === \"context\"`. Reuses the\n * same two-phase gated-tool lifecycle (never a new outcome/trigger/realization arm); phase 2 is a\n * scoped context-write authorization gate (guardrail `context_write_authz`) instead of a blast-radius\n * computation — the write must resolve to a path inside the guardrail's `scope`, or it is denied\n * outright, regardless of how small the change is. This function must never mention the word \"blast\"\n * — even a negation/contrast (\"not a blast-radius computation\") still contains the literal substring,\n * which back-end tests treat as leaking the wrong gate into the wrong scope.\n */\nfunction buildContextMutationSection(node: ComponentNode): string {\n const outcome = node.effect.outcome;\n const target = outcome.target ?? \"the bound node\";\n const changeType = outcome.change_type ?? \"update\";\n const contextGuardrail = findGuardrail(node.guardrails, \"context_write_authz\");\n const scope = contextGuardrail?.scope ?? DEFAULT_ARTIFACT_SCOPE;\n\n return [\n \"## Mutation output\",\n \"\",\n `This is a **constitutive** component (outcome: mutation, target \\`${target}\\`, change_type ` +\n `\\`${changeType}\\`). It runs the same two-phase gated lifecycle as any mutating component, ` +\n \"never a direct write:\",\n \"\",\n \"1. **Dry-run first (must_dry_run).** Propose the edit as a DIFF only — do not apply it. Your \" +\n \"first-phase FINAL message must be a single JSON envelope carrying a `diff` block (the exact \" +\n \"unified diff you intend to apply) and `\\\"applied\\\": false`. Never write to the target file \" +\n \"in this phase.\",\n \"\",\n `2. **Context-write gate (context_write_authz, locked, scope \\`${scope}\\`).** This is a scoped ` +\n \"PATH-AUTHORIZATION check, NOT a downstream-lineage impact computation — the proposed write \" +\n `must resolve to a path inside the \\`${scope}\\` scope (the models/metrics/knowledge structure ` +\n \"this component owns) or it is denied outright. Writing outside this scope is never permitted, \" +\n \"however small the change.\",\n \"\",\n \"3. **Human approval (human_approval, locked).** Applying the diff is gated on explicit approval \" +\n \"delivered over the runtime's approval channel. On a target with no human/approval channel \" +\n \"wired, this component cannot run past the dry-run phase — that is the honest capability edge, \" +\n \"not a bug to route around.\",\n \"\",\n \"4. **Apply + rollback (rollback_available).** Only apply after approval clears. A git \" +\n \"checkpoint is taken first so the apply can be rolled back; rollback is BORROWED from version \" +\n \"control, not owned by this agent. After applying, set `\\\"applied\\\": true` in your final \" +\n \"envelope.\",\n \"\",\n \"Diff block contract (produce data matching this shape, not prose):\",\n \"\",\n ...node.effect.render_blocks.map(formatRenderBlock),\n \"\",\n \"Your FINAL message at each phase MUST be a SINGLE JSON object — the mutation envelope — and \" +\n \"nothing else: a `blocks` array (the `diff` block above) and \\\"applied\\\" (`false` on the \" +\n \"dry-run, `true` only after a real apply). Set the top-level \\\"verified\\\": true only when the \" +\n \"diff was actually computed against the live target (never fabricated).\",\n \"\",\n \"Envelope shape:\",\n \"\",\n CONTEXT_MUTATION_DIFF_ENVELOPE_EXAMPLE,\n ].join(\"\\n\");\n}\n\n/**\n * The mutation outcome contract (+Mutating) — structural twin of {@link buildAssertionSection}. A\n * gated-tool component's lifecycle is two-phase: PROPOSE a diff, then (only after the runtime's\n * approval gate clears) APPLY it. `target`/`change_type` come straight from `effect.outcome` — the\n * mutation arm the IR spine already carries. The guardrails named below (`must_dry_run`,\n * `blast_radius_limit`, `human_approval`, `rollback_available`) are keyed on guardrail *name*, never\n * on this component's id/verb.\n *\n * +Constitutive reuses this SAME function/arm: `outcome.target === \"context\"` early-returns to\n * {@link buildContextMutationSection}, which swaps phase 2 (blast-radius gate) for a scoped\n * context-write authorization gate. Every other target value (a data path, or none) keeps the\n * blast-radius lifecycle below unchanged.\n */\nexport function buildMutationSection(node: ComponentNode): string {\n const outcome = node.effect.outcome;\n if (outcome.target === \"context\") {\n return buildContextMutationSection(node);\n }\n const target = outcome.target ?? \"the bound node\";\n const changeType = outcome.change_type ?? \"update\";\n\n return [\n \"## Mutation output\",\n \"\",\n `This is a **mutating** component (outcome: mutation, target \\`${target}\\`, change_type ` +\n `\\`${changeType}\\`). It runs a two-phase gated lifecycle, never a direct write:`,\n \"\",\n \"1. **Dry-run first (must_dry_run).** Propose the edit as a DIFF only — do not apply it. Your \" +\n \"first-phase FINAL message must be a single JSON envelope carrying a `diff` block (the exact \" +\n \"unified diff you intend to apply) and `\\\"applied\\\": false`. Never write to the target file \" +\n \"or the warehouse in this phase.\",\n \"\",\n \"2. **Blast-radius gate (blast_radius_limit).** The downstream impact of the edited node is \" +\n \"computed from Warble's `blast_radius` over the MDL lineage graph, not by you. An empty \" +\n \"radius auto-allows; exceeding the guardrail's threshold escalates to human approval; \" +\n \"touching a protected asset blocks outright. Report the affected downstream nodes you are \" +\n \"aware of in the envelope's `blast_radius` field, but the gate decision itself is made by the \" +\n \"runtime, not by your judgment.\",\n \"\",\n \"3. **Human approval (human_approval, locked).** Applying the diff is gated on explicit approval \" +\n \"delivered over the runtime's approval channel. On a target with no human/approval channel \" +\n \"wired, this component cannot run past the dry-run phase — that is the honest capability edge, \" +\n \"not a bug to route around.\",\n \"\",\n \"4. **Apply + rollback (rollback_available).** Only apply after approval clears. A git \" +\n \"checkpoint is taken first so the apply can be rolled back; rollback is BORROWED from version \" +\n \"control, not owned by this agent. After applying, set `\\\"applied\\\": true` in your final \" +\n \"envelope.\",\n \"\",\n \"Diff block contract (produce data matching this shape, not prose):\",\n \"\",\n ...node.effect.render_blocks.map(formatRenderBlock),\n \"\",\n \"Your FINAL message at each phase MUST be a SINGLE JSON object — the mutation envelope — and \" +\n \"nothing else: a `blocks` array (the `diff` block above), a `blast_radius` object, and \" +\n '`\"applied\"` (`false` on the dry-run, `true` only after a real apply). Set the top-level ' +\n '`\"verified\": true` only when the diff was actually computed against the live target (never ' +\n \"fabricated).\",\n \"\",\n \"Envelope shape:\",\n \"\",\n MUTATION_DIFF_ENVELOPE_EXAMPLE,\n ].join(\"\\n\");\n}\n\nfunction buildPreamble(cwd: string): string {\n return [\n `You are bound to the wren project at \\`${cwd}\\` (your working directory).`,\n \"All data access MUST go through the `wren` CLI (e.g. `wren --sql ...`, `wren cube list`, \" +\n \"`wren genbi build ...`) — never raw SQL clients, never filesystem tricks against the \" +\n \"underlying warehouse.\",\n ].join(\"\\n\");\n}\n\n// --- per-step-tier split (in-loop via `agents`) --------------------------------------------------\n\n/** The SDK's `agents[].model` is a restricted alias union; narrow a resolved model onto it. */\nfunction toAgentModel(model: string): \"sonnet\" | \"opus\" | \"haiku\" | \"inherit\" {\n if (model === \"sonnet\" || model === \"opus\" || model === \"haiku\" || model === \"inherit\") {\n return model;\n }\n throw new DispatchError(\n `per-step-tier realization on claude-agent-sdk:local requires each tier's model to be one of ` +\n `sonnet|opus|haiku|inherit (SDK agents[].model is a restricted alias union), but got '${model}'. ` +\n `Use those aliases in --models-config, or the single-tier collapse path.`,\n );\n}\n\nfunction subagentName(verb: string, callName: string): string {\n return `${verb}__${callName}`;\n}\n\nfunction buildDriverBody(node: ComponentNode): string {\n const producers = new Map<string, string>();\n for (const call of node.llm_calls) {\n if (call.produces) producers.set(call.produces, call.name);\n }\n const steps = node.llm_calls.map((call, i) => {\n const parts = [\n `Run the \\`${subagentName(node.verb, call.name)}\\` subagent (step \\`${call.name}\\`) via the Task tool.`,\n ];\n if (call.consumes.length > 0) {\n const sources = call.consumes\n .map((slot) => {\n const producer = producers.get(slot);\n return producer ? `\\`${slot}\\` (the \\`${producer}\\` subagent's output)` : `\\`${slot}\\``;\n })\n .join(\", \");\n parts.push(`Pass it ${sources} as input.`);\n }\n if (call.produces) parts.push(`Take its output as \\`${call.produces}\\` for the steps after it.`);\n return `${i + 1}. ${parts.join(\" \")}`;\n });\n\n return [\n `You orchestrate the \\`${node.verb}\\` steps by delegating each one to its dedicated subagent via ` +\n `the Task tool, in order. Do not perform a step's work yourself — each step's tier-appropriate ` +\n `subagent does it.`,\n \"\",\n \"Steps, in order:\",\n \"\",\n ...steps,\n \"\",\n \"Marshal each subagent's declared output into the next subagent's declared input exactly as \" +\n \"named above; do not invent or rename slots.\",\n ].join(\"\\n\");\n}\n\nfunction buildAgents(\n node: ComponentNode,\n gate: RenderGate,\n models: ModelConfig,\n): Record<string, AgentDefinition> {\n const agents: Record<string, AgentDefinition> = {};\n // Subagents get the per-component read-only data tools (Read + Bash gated), never Write.\n const noGate: RenderGate = { kind: \"none\", scope: null, flavor: null };\n const subTools = buildTools(node, noGate);\n for (const call of node.llm_calls) {\n const ioNote = `\\n\\n(consumes [${call.consumes.join(\", \")}] / produces ${call.produces ?? \"(none)\"})`;\n const prompt = node.brief ? `${node.brief}\\n\\n${call.prompt}` : call.prompt;\n agents[subagentName(node.verb, call.name)] = {\n description: `'${call.name}' step of ${node.verb} (tier: ${call.tier}).`,\n prompt: prompt + ioNote,\n tools: subTools.tools,\n model: toAgentModel(models.require(call.tier)),\n };\n }\n return agents;\n}\n\n// --- the dispatch plan --------------------------------------------------------------------------\n\nexport interface DispatchMeta {\n verb: string;\n target: string;\n readOnly: boolean;\n split: boolean;\n render: RenderGate;\n /** True when the outcome is an `assertion`: the final message is a verdict envelope (status block). */\n assertion: boolean;\n /** True when the outcome is a `mutation`: the final message is a diff/apply envelope (gated). */\n mutation: boolean;\n model: string;\n /** Subagent tier→model, present only on the split path. */\n subagentModels: Record<string, string>;\n tierCollapseNote: string | null;\n /** How the steps are realized (hybrid-LLM spike): single | sdk-split | hybrid-staged. */\n mode: RoutingMode;\n /** Distinct providers across the steps (order-preserving). `[\"anthropic\"]` on the existing paths. */\n providers: Provider[];\n /** Per-step resolved bindings — populated on the `hybrid-staged` path (empty otherwise), so run.ts\n * can drive each step on its own provider and marshal `produces`→`consumes`. */\n stagedSteps: StagedStep[];\n /** The project root a `setup_execution` component may write into (genbi-setup's onboarding\n * flavor), or `null` for every other component. Threaded to `makeReadOnlyGuard` so Bash broadens\n * beyond `wren` and Write/Edit are scoped to this root, instead of denied outright. `null` on the\n * hybrid-staged path (out of scope — see buildHybridStagedPlan). */\n setupScope: string | null;\n}\n\nexport interface DispatchPlan {\n /** The user question (assembled prompt for `query()`). */\n prompt: string;\n /** Serializable `query()` options (canUseTool is attached later by run.ts). */\n options: Options;\n meta: DispatchMeta;\n}\n\nexport interface BuildConfig {\n target: string;\n flavor: RenderFlavor;\n models: ModelConfig;\n question: string;\n /** Absolute path to the bound wren project (resolved by the CLI). */\n cwd: string;\n maxTurns?: number;\n}\n\n/** Note recorded when >1 tier collapses onto a single model (only on the non-split path). */\nfunction tierCollapseNote(node: ComponentNode, model: string): string | null {\n const tiers = distinctTiers(node.llm_calls);\n if (tiers.length <= 1) return null;\n const steps = node.llm_calls.map((c) => `${c.name}=${c.tier}`).join(\", \");\n return `per-step tiers [${steps}] collapsed to single model '${model}'`;\n}\n\n/**\n * Build the `query({options})` for one resolved IR node. Loud-fails on any unsupported enum value\n * before producing anything (wall-hit), mirroring `emit.rs`.\n */\nexport function buildDispatchPlan(\n node: ComponentNode,\n report: ResolutionReport,\n cfg: BuildConfig,\n): DispatchPlan {\n if (!realizationSupported(node)) {\n throw unsupported(\"realization_kind\", node.realization_kind);\n }\n if (!triggerSupported(node)) {\n throw unsupported(\"trigger.kind\", node.trigger.kind);\n }\n if (!outcomeSupported(node)) {\n throw unsupported(\"outcome.kind\", node.effect.outcome.kind);\n }\n\n const gate = resolveRenderGate(node, report, cfg.flavor);\n const readOnly = isReadOnly(node.guardrails);\n const setupScope = computeSetupScope(node.guardrails);\n const permissionMode: PermissionMode = \"default\";\n const maxTurns = cfg.maxTurns ?? DEFAULT_MAX_TURNS;\n const renderSection = buildRenderSection(node, gate);\n const assertionSection = isAssertion(node) ? buildAssertionSection(node) : null;\n const mutationSection = isMutation(node) ? buildMutationSection(node) : null;\n const split = shouldSplitPerStepTier(node);\n // A `gated-tool` with divergent step tiers is a wall-hit here, not a split: `buildAgents` grants\n // every subagent the SAME node-wide guardrail tool set as `buildTools` would give one unsplit\n // mutating agent (Edit/Write when `mutating = !readOnly`) — it has no notion of \"this step, not\n // the whole component\" (mirrors `split.rs`'s `build_subagent_markdown` on the Rust `claude-code-\n // cli` target). Only the driver's system prompt carries the two-phase approval sequence\n // (`buildMutationSection`), so splitting would hand every subagent independent, ungated write\n // authority over the same guarded target — duplicating write access outside the driver's dry-run\n // -> blast-radius -> human-approval -> apply lifecycle. That is exactly the \"moves, duplicates, or\n // bypasses the approval gate\" case the per-step-tier contract requires refusing rather than forcing,\n // so this fails loudly before any `query()` options are built — instead of either silently\n // collapsing the tiers (the original bug) or unsafely splitting write authority across subagents.\n // `tool` and `skill` have no such approval boundary to protect and always split; only `gated-tool`\n // is refused. Checked ahead of `planProviderRouting` so neither the sdk-split nor the hybrid-staged\n // path can be reached with this component.\n if (node.realization_kind === \"gated-tool\" && split) {\n throw new DispatchError(\n `llm:per_step_tier: gated-tool component '${node.verb}' has divergent step tiers, but per-step ` +\n `splitting would grant every subagent the mutation guardrail's write/edit authority alongside ` +\n `the approval-gated driver, duplicating write access outside the two-phase approval lifecycle ` +\n `(dry-run diff -> blast-radius -> human approval -> apply) — refusing to dispatch rather than ` +\n `silently collapsing the tiers or unsafely splitting write authority. Realize this component as ` +\n `\\`tool\\` (no approval gate) or \\`skill\\` to enable per-step-tier splitting, or author it with a ` +\n `single tier to keep it a \\`gated-tool\\`.`,\n );\n }\n // Per-step provider routing: the anthropic split decision above only applies when\n // every step's provider is anthropic; a non-anthropic binding forces the hybrid-staged path.\n const routing = planProviderRouting(node, cfg.models, split);\n\n const base: Options = {\n cwd: cfg.cwd,\n permissionMode,\n maxTurns,\n // SDK isolation: do NOT load ambient ~/.claude or project .claude settings, so nothing outside\n // this plan can widen the tool allowlist. wren strict_mode is read by the wren CLI itself.\n // (settingSources omitted == isolation mode.)\n };\n\n if (routing.mode === \"hybrid-staged\") {\n return buildHybridStagedPlan(node, gate, cfg, base, readOnly, routing.providers, routing.steps);\n }\n\n if (split) {\n // Per-step tier realized IN-LOOP: a driver delegates to one tier-bound subagent per step via the\n // Task tool. `llm:per_step_tier` = native on this target (no static files).\n //\n // The SDK CLAMPS each subagent's `agents[].tools` to the tools enabled at the PARENT session\n // level (`tools` below) — a subagent can never receive a tool its parent session doesn't have,\n // regardless of what `buildAgents` declares for it. So for a data-access component, Bash MUST be\n // enabled here or the Task subagents can never run `wren` (found via a parity spike, 2026-07-15).\n // Delegation is enforced by the driver PROMPT (`buildDriverBody`, \"do not perform a step's work\n // yourself\") plus the `canUseTool` semantic gate (guardrails.ts) — NOT by withholding the tool:\n // `allowedTools` below deliberately excludes Bash, so every call still routes through that gate.\n const agents = buildAgents(node, gate, cfg.models);\n const driverTools = hasDataAccess(node.required_capabilities)\n ? [\"Task\", \"Read\", \"Bash\"]\n : [\"Task\", \"Read\"];\n if (gateGrantsWrite(gate)) driverTools.push(\"Write\");\n\n const driverPrompt = [\n buildPreamble(cfg.cwd),\n \"\",\n ...(node.brief ? [node.brief, \"\"] : []),\n buildDriverBody(node),\n ...(renderSection\n ? [\n \"\",\n \"You collect the subagents' output and produce the render output yourself \" +\n \"(the subagents never do).\",\n \"\",\n renderSection,\n ]\n : [\n \"\",\n // No render section (e.g. answer_query): the final step already produced the user-facing\n // structured answer — including its `verified` facet and shallow `definition` (G2/G3).\n // Pass it through verbatim; do NOT re-prose or drop those fields, or the ✓ Verified cue\n // and definition card are lost on the way out.\n \"Your FINAL message MUST be the terminal step's structured output verbatim — a single \" +\n \"JSON object with its `columns`/`rows` (or refusal) plus the `verified` boolean and \" +\n \"the shallow `definition` it emitted. Do not summarize it into prose or drop any field.\",\n ]),\n ...(assertionSection ? [\"\", assertionSection] : []),\n ...(mutationSection ? [\"\", mutationSection] : []),\n ].join(\"\\n\");\n\n const subagentModels: Record<string, string> = {};\n for (const call of node.llm_calls) {\n subagentModels[subagentName(node.verb, call.name)] = cfg.models.require(call.tier);\n }\n\n const options: Options = {\n ...base,\n model: cfg.models.orchestrator(),\n systemPrompt: driverPrompt,\n agents,\n tools: driverTools,\n allowedTools: [\"Read\", \"Task\"],\n disallowedTools: readOnly ? [...DESTRUCTIVE_BASH_DENY] : [],\n };\n\n return {\n prompt: cfg.question,\n options,\n meta: {\n verb: node.verb,\n target: cfg.target,\n readOnly,\n split: true,\n render: gate,\n assertion: isAssertion(node),\n mutation: isMutation(node),\n model: cfg.models.orchestrator(),\n subagentModels,\n tierCollapseNote: null,\n mode: \"sdk-split\",\n providers: [\"anthropic\"],\n stagedSteps: [],\n setupScope,\n },\n };\n }\n\n // Single-tier (collapse) path: one model, no subagents.\n const model = cfg.models.collapsedModel(node.llm_calls);\n const toolPlan = buildTools(node, gate);\n const systemPrompt = [\n buildPreamble(cfg.cwd),\n \"\",\n ...(node.brief ? [node.brief, \"\"] : []),\n node.prompt_fragment,\n ...(renderSection ? [\"\", renderSection] : []),\n ...(assertionSection ? [\"\", assertionSection] : []),\n ...(mutationSection ? [\"\", mutationSection] : []),\n ].join(\"\\n\");\n\n const options: Options = {\n ...base,\n model,\n systemPrompt,\n tools: toolPlan.tools,\n allowedTools: toolPlan.allowedTools,\n disallowedTools: toolPlan.disallowedTools,\n };\n\n return {\n prompt: cfg.question,\n options,\n meta: {\n verb: node.verb,\n target: cfg.target,\n readOnly,\n split: false,\n render: gate,\n assertion: isAssertion(node),\n mutation: isMutation(node),\n model,\n subagentModels: {},\n tierCollapseNote: tierCollapseNote(node, model),\n mode: \"single\",\n providers: [\"anthropic\"],\n stagedSteps: [],\n setupScope,\n },\n };\n}\n\n/**\n * Build the plan for the `hybrid-staged` path: ≥1 step binds to a non-Anthropic provider, so the\n * back-end drives the steps itself (run.ts) rather than a single `query()` — one isolated invocation per\n * step on its own provider, marshaling `produces`→`consumes`. We therefore build NO SDK `agents` (which\n * would loud-fail on a local model id via `toAgentModel`); the per-step bindings live in `meta.stagedSteps`.\n *\n * `options` carries the shared read-only data tool plan (cloud steps run with Read + gated Bash(wren);\n * local steps ignore tools) plus cwd/isolation, so run.ts can assemble each step's `query()`/local call.\n * Render is out of POC scope on this path: `answer_query` (the demo) is render-none and the terminal\n * step's structured output passes through; a realize/degrade render under hybrid loud-fails (documented\n * wall-hit) rather than silently dropping the dashboard.\n */\nfunction buildHybridStagedPlan(\n node: ComponentNode,\n gate: RenderGate,\n cfg: BuildConfig,\n base: Options,\n readOnly: boolean,\n providers: Provider[],\n steps: StagedStep[],\n): DispatchPlan {\n // Binding-time hybrid gate (llm:per_step_provider): a non-Anthropic provider in the binding is what\n // triggers this path, so the requirement is checked here (binding known), not as an IR-static\n // capability. Loud-fail if the target's profile does not realize it.\n const perStepProvider = profileFor(cfg.target)?.[PER_STEP_PROVIDER_CAPABILITY];\n if (!perStepProvider || perStepProvider.outcome === \"fail\") {\n throw new DispatchError(\n `${PER_STEP_PROVIDER_CAPABILITY}: fail on ${cfg.target} — the binding routes a step to a ` +\n `non-Anthropic provider (${providers.filter((p) => p !== \"anthropic\").join(\", \")}), but this ` +\n `target does not support per-step provider routing (hybrid). Use an all-cloud binding, or a ` +\n `target that realizes ${PER_STEP_PROVIDER_CAPABILITY}.`,\n );\n }\n if (gate.kind !== \"none\") {\n throw new DispatchError(\n `hybrid-staged provider routing does not yet realize a '${gate.kind}' render gate on ` +\n `${cfg.target} (wall-hit); the POC covers render-none components like answer_query. ` +\n `Bind this component all-cloud, or extend the staged executor's render handling.`,\n );\n }\n const toolPlan = buildTools(node, gate);\n // Driver model for the hybrid-tool realization (WARBLE_HYBRID_MODE=tool): the orchestrator tier if\n // defined, else the strongest step's model. Unused by the default staged executor (kept harmless).\n let driverModel: string;\n try {\n driverModel = cfg.models.orchestrator();\n } catch {\n driverModel = cfg.models.collapsedModel(node.llm_calls);\n }\n const options: Options = {\n ...base,\n model: driverModel,\n tools: toolPlan.tools,\n allowedTools: toolPlan.allowedTools,\n disallowedTools: toolPlan.disallowedTools,\n };\n return {\n // The staged executor assembles each step's prompt from `meta.stagedSteps`; the top-level prompt is\n // the raw question (marshaled per step by run.ts).\n prompt: cfg.question,\n options,\n meta: {\n verb: node.verb,\n target: cfg.target,\n readOnly,\n assertion: isAssertion(node),\n mutation: isMutation(node),\n split: false,\n render: gate,\n model: `hybrid-staged(${providers.join(\"+\")})`,\n subagentModels: {},\n tierCollapseNote: null,\n mode: \"hybrid-staged\",\n providers,\n stagedSteps: steps,\n // Hybrid+setup is out of scope (locked decision): a setup component's steps are not staged\n // across providers, so this path never sees setup_execution in practice; null is the safe,\n // explicit default rather than silently inheriting a scope this path doesn't enforce.\n setupScope: null,\n },\n };\n}\n","/**\n * The capability resolution pass — dispatch's \"capability linker\" (`docs/spec/capability-model.md`).\n *\n * TS sibling of the Rust file target's `resolve.rs`: same algorithm, same semantics. Given an IR\n * component node and a target's capability profile, resolve every capability the node requires\n * (declared + implied) into a report, or abort loudly naming the unsupported capability + target\n * (no silent degradation).\n */\nimport { DispatchError } from \"./error.js\";\nimport { distinctTiers, type ComponentNode } from \"./ir.js\";\nimport {\n isKnownTarget,\n knownTargetNames,\n localProfile,\n type CapabilityEntry,\n type CapabilityOutcome,\n type CapabilityProfile,\n type Criticality,\n type ProvidedBy,\n} from \"./targets.js\";\n\nexport interface ResolvedCapability {\n capability: string;\n outcome: CapabilityOutcome;\n provided_by: ProvidedBy;\n criticality: Criticality;\n note?: string;\n}\n\nexport type ResolutionReport = ResolvedCapability[];\n\n/**\n * Entry used for a capability absent from the target profile entirely — unknown means it cannot be\n * guaranteed, so it fails as safety-critical.\n */\nfunction unknownCapabilityEntry(): CapabilityEntry {\n return {\n outcome: \"fail\",\n via: null,\n provided_by: \"none\",\n criticality: \"safety-critical\",\n note: \"capability is not declared in the target's capability profile — unknown means it cannot be guaranteed\",\n };\n}\n\n/** Capabilities implied by IR shape beyond the node's declared `required_capabilities`. */\nfunction impliedCapabilities(node: ComponentNode): string[] {\n const implied: string[] = [];\n\n // Per-step tier is realization-independent: an authored tier is an unambiguous cost/behavior\n // declaration regardless of how the component connects to the LLM (skill/tool/gated-tool), so\n // divergent step tiers always imply `llm:per_step_tier` — never gated on `realization_kind`.\n // Silently ignoring an authored tier for `tool`/`gated-tool` is exactly the silent-collapse\n // failure the \"no silent degradation\" design principle exists to prevent.\n if (distinctTiers(node.llm_calls).length > 1) {\n implied.push(\"llm:per_step_tier\");\n }\n\n switch (node.trigger.kind) {\n case \"scheduled\":\n implied.push(\"scheduler\");\n break;\n case \"event\":\n implied.push(\"event_bus\");\n break;\n case \"one_shot\":\n break;\n }\n\n // Emitting a signal is the producer side of the event transport, symmetric to a `event` trigger\n // consuming one — both borrow `event_bus`. Shape-derived, never per-component. The notify_channel\n // for concrete on-breach actions is a *declared* capability, not implied here.\n if ((node.effect.outcome.emits?.length ?? 0) > 0) {\n implied.push(\"event_bus\");\n }\n\n if (node.effect.render_blocks.length > 0) {\n implied.push(\"render_contract\");\n }\n\n // A `mutation` outcome implies the write surface + the checkpoint/rollback mechanism it is\n // borrowed from — shape-derived from the outcome enum, analogous to `emits` ⇒ `event_bus`. Does\n // NOT imply human_approval/blast_radius: those are declared per-guardrail, not implied by shape.\n //\n // +Constitutive reuses this same arm: `outcome.target === \"context\"` needs the path-scoped\n // `context_write_authz` gate instead of `write_authz` (the two scopes — models/knowledge vs\n // data — must never cross). Every other target value (a data path, or none) keeps `write_authz`.\n if (node.effect.outcome.kind === \"mutation\") {\n implied.push(\"version_control\");\n if (node.effect.outcome.target === \"context\") {\n implied.push(\"context_write_authz\");\n } else {\n implied.push(\"write_authz\");\n }\n }\n\n return implied;\n}\n\n/** Union of declared + implied required capabilities, de-duplicated, order-preserving. */\nexport function collectRequiredCapabilities(node: ComponentNode): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const cap of [...node.required_capabilities, ...impliedCapabilities(node)]) {\n if (!seen.has(cap)) {\n seen.add(cap);\n out.push(cap);\n }\n }\n return out;\n}\n\n/**\n * Resolve every capability required by `node` against `profile`. Returns the report on success;\n * throws (loud-fail) naming the capability + target if any required capability resolves to `fail`.\n */\nexport function inspectCapabilities(\n node: ComponentNode,\n targetId: string,\n profile: CapabilityProfile,\n): ResolutionReport {\n const fallback = unknownCapabilityEntry();\n\n const report: ResolutionReport = collectRequiredCapabilities(node).map((capability) => {\n const e = profile[capability] ?? fallback;\n const resolved: ResolvedCapability = {\n capability,\n outcome: e.outcome,\n provided_by: e.provided_by,\n criticality: e.criticality,\n };\n if (e.note !== null) resolved.note = e.note;\n return resolved;\n });\n\n return report;\n}\n\n/** Preserve the execution wall: a failed capability may be displayed, never dispatched. */\nfunction assertNoFailedCapabilities(report: ResolutionReport, targetId: string, verb: string): void {\n const failed = report.find((r) => r.outcome === \"fail\");\n if (failed) {\n const reason = failed.note ?? \"unsupported on this target\";\n throw new DispatchError(\n `${failed.capability}: fail on ${targetId} (${reason}) — component '${verb}' cannot be dispatched`,\n );\n }\n}\n\nexport function resolveCapabilities(\n node: ComponentNode,\n targetId: string,\n profile: CapabilityProfile,\n): ResolutionReport {\n const report = inspectCapabilities(node, targetId, profile);\n assertNoFailedCapabilities(report, targetId, node.verb);\n return report;\n}\n\n/**\n * Resolve one node's required capabilities against `targetId`, erroring on any `fail` outcome\n * (no silent degradation). Callers must not dispatch when this throws.\n */\nexport function resolveNodeCapabilities(node: ComponentNode, targetId: string): ResolutionReport {\n if (!isKnownTarget(targetId)) {\n throw new DispatchError(\n `target '${targetId}' has no capability profile (known targets: ${knownTargetNames().join(\", \")})`,\n );\n }\n return resolveCapabilities(node, targetId, localProfile());\n}\n\n/**\n * Read-only inspection counterpart to `resolveNodeCapabilities`. It returns\n * the same report, including a failed entry, but does not legalize execution.\n * Only display-only callers may use this; dispatch/emit/chat retain the loud\n * failure above.\n */\nexport function inspectNodeCapabilities(node: ComponentNode, targetId: string): ResolutionReport {\n if (!isKnownTarget(targetId)) {\n throw new DispatchError(\n `target '${targetId}' has no capability profile (known targets: ${knownTargetNames().join(\", \")})`,\n );\n }\n return inspectCapabilities(node, targetId, localProfile());\n}\n","/**\n * Guardrail runtime enforcement — the differentiator over the file target.\n *\n * The file target can only emit static allow/deny *strings* in a settings file. Here the same\n * `read_only_execution` guardrail is enforced at RUNTIME via the SDK `canUseTool` callback: every\n * tool call is inspected as it happens and escapes are intercepted with a reason fed back to the\n * model. Two layers work together:\n * 1. static (options.ts): `Bash` is available but NOT auto-allowed, `Write`/`Edit` absent on the\n * read-only path, destructive bash patterns in `disallowedTools`;\n * 2. runtime (here): `canUseTool` allows only `wren` bash invocations (data access through the\n * semantic layer) and, on the prompt flavor, `Write` only inside the artifact scope.\n *\n * Data read-only itself is additionally enforced one layer down by wren `strict_mode` (its own\n * config), which is orthogonal to this artifact/escape gate.\n *\n * See docs/spec/enforcement-seam.md for the full enforcement model across both targets.\n */\nimport { resolve as resolvePath, sep as pathSep } from \"node:path\";\nimport type {\n CanUseTool,\n HookCallbackMatcher,\n PermissionResult,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\n/**\n * Whether the already-resolved absolute path `abs` lies within the resolved scope directory\n * `scopeAbs`. A plain `abs.startsWith(scopeAbs)` is WRONG at a directory boundary — it would admit a\n * sibling like `/p/models-export` for a scope of `/p/models`. Require an exact match or a real\n * path-separator boundary after the prefix. Shared by the context_write_authz and writeScope checks.\n */\nfunction withinScope(abs: string, scopeAbs: string): boolean {\n return abs === scopeAbs || abs.startsWith(scopeAbs.endsWith(pathSep) ? scopeAbs : scopeAbs + pathSep);\n}\n\n/** A blocked tool call, recorded so the trace/report can prove enforcement actually fired. */\nexport interface Denial {\n tool: string;\n reason: string;\n command?: string;\n}\n\nexport interface GuardConfig {\n readOnly: boolean;\n /** Absolute artifact-write scope dir (prompt flavor); null keeps the agent fully read-only. */\n writeScope: string | null;\n /** The session cwd (bound wren project), used to resolve relative write paths. */\n cwd: string;\n /**\n * +Mutating: when set, Write/Edit calls are the gated apply of a mutating component's diff, not a\n * plain artifact write. The actual approval decision is borrowed from the SDK embedder's own\n * `canUseTool` wrapper / approval channel — this guard cannot grant an apply on its own, so it\n * always denies fail-closed and records why (a target with no approval channel is the honest edge,\n * not a bug to route around).\n */\n mutation?: {\n mustDryRun: boolean;\n approvalRequired: boolean;\n /**\n * +Constitutive: the THIRD enforcement point, `context_write_authz` — a path-scoped gate distinct\n * from `writeScope` (render artifact writes) and the plain mutation approval gate (data writes).\n * When set, a Write/Edit outside this scope is denied with a SCOPE-VIOLATION reason (never even\n * reaches the approval question); a write inside the scope still denies fail-closed, but with an\n * APPROVAL reason — same fail-closed philosophy as the unscoped mutation branch below. The two\n * reasons are distinguishable so callers/tests can tell which gate fired. Unset keeps the existing\n * unscoped mutation behavior unchanged.\n */\n contextScope?: string;\n };\n /**\n * +Setup (genbi-setup, the 5th enforcement point: `setup_execution`): the onboarding flavor. When\n * set, Bash is broadened beyond `wren` (connector CLIs like `dlt` are permitted too — still subject\n * to the DESTRUCTIVE/REDIRECTION/dotenv-read denylist, checked first and never relaxed), and\n * Write/Edit are scoped to this project root rather than denied outright, and Read is denied for a\n * dotenv-shaped path (see DOTENV_READER_COMMANDS/DOTENV_PATH below). Distinct from `writeScope`\n * (render artifacts) and the `mutation` gates (a pre-existing MDL's diff/apply lifecycle): setup has\n * no pre-bound context to gate reads against and no diff to approve — it is scaffolding a NEW\n * project. `undefined`/`null` leaves every other component's behavior unchanged.\n */\n setupScope?: string | null;\n}\n\nconst DESTRUCTIVE = /\\b(rm|sudo|dd|mkfs|shutdown|reboot|kill|chmod|chown|mv|cp)\\b/;\nconst REDIRECTION = /(^|[^>])>>?[^>]/; // shell output redirection → an artifact/warehouse write escape\n\n/**\n * Reader commands that can print a file's contents: `cat`, `head`, `tail`, `less`, `more`, `od`,\n * `xxd`, `strings`, `grep`, `awk`, `sed`. Matched as a whole word (`\\b`) so a lookalike substring\n * inside another word — `cat` inside \"concatenate\", `sed` inside \"used\", `od` inside \"produce\" —\n * never matches.\n *\n * DOTENV_READER_COMMANDS and DOTENV_PATH (below), and the pairing that uses them in `canUseTool`'s\n * Bash and Read branches, are the ORIGINAL that the genbi in-process setup tool copies verbatim (see\n * `apps/genbi/harness/tools/setup-native.ts`'s `DOTENV_READER_COMMANDS`/`DOTENV_PATH` in the public\n * WrenAI repo) — deliberately, so the two setup boundaries cannot drift apart. Keep both regexes\n * byte-identical across the two files; changing one without the other reopens the gap this closes.\n *\n * The gap: the setup credential design writes an EMPTY `.env` template and relies on the agent never\n * reading the filled-in values back (the user fills them out-of-band) — but until this pair existed,\n * nothing enforced that. Observed live (real model, genbi in-process copy): a setup agent ran `cat\n * <project>/.env`, it succeeded (neither DESTRUCTIVE nor REDIRECTION matches a plain read), and the\n * full stdout — a connection string / password / API key / service-account value — reached both the\n * model's own context and the host app's persisted turn trace.\n *\n * Note for anyone auditing this the way that genbi incident was found: warble itself has no\n * counterpart to genbi's output-redaction layer, and intentionally so — `trace.json` (see `Trace` in\n * run.ts) only ever persists metadata (`target, verb, model, split, run, usage, modelUsage, steps,\n * denials`), never raw tool stdout/stderr. There is no persistence choke point in warble for a leaked\n * secret to land in on disk the way it did in genbi's turn trace; the exposure this pair (and the\n * PreToolUse hook below, for Read) closes is the model's own context window, not a stored artifact.\n */\nconst DOTENV_READER_COMMANDS = /\\b(cat|head|tail|less|more|od|xxd|strings|grep|awk|sed)\\b/;\n/**\n * A `.env`/`.env.<suffix>` path token (`.env`, `project/.env`, `.env.local`, `.env.production`, …),\n * matched precisely: the literal `.env` must be preceded by start-of-string/whitespace/quote/`/`/`=`\n * and followed by end-of-string/whitespace/quote/`/`, with an optional `.<suffix>` in between. This is\n * what keeps a file named `.environment` (no boundary right after `.env` — the next character is `i`,\n * not one of the above) and a bare directory named `env/` (no leading dot at all) from tripping the\n * match, even though both contain the substring \"env\" — both are exercised in\n * `tests/guardrails.test.ts`.\n */\nconst DOTENV_PATH = /(^|[\\s\"'/=])\\.env(\\.[\\w.-]+)?(?=$|[\\s\"'/])/;\n\n/**\n * Whether `text` references a dotenv-shaped path at all. Used two ways: paired with\n * `DOTENV_READER_COMMANDS` against a Bash command string (either alone is over- or under-broad — a\n * reader command alone would deny an unrelated `cat notes.txt`; the path token alone would deny a\n * command that merely mentions \".env\" as a substring of something else — the pairing is load-bearing),\n * and unpaired against a Read tool's `file_path` (Read has no accompanying \"reader command\" to pair\n * against — the tool call itself IS the read).\n */\nfunction referencesDotenvPath(text: string): boolean {\n return DOTENV_PATH.test(text);\n}\n\n/** First executable token of a (possibly compound) bash command. */\nfunction firstToken(command: string): string {\n return command.trim().split(/\\s+/)[0] ?? \"\";\n}\n\nfunction allow(input: Record<string, unknown>): PermissionResult {\n return { behavior: \"allow\", updatedInput: input };\n}\n\nfunction deny(message: string): PermissionResult {\n return { behavior: \"deny\", message };\n}\n\n/**\n * The LIVE enforcement point for the Read-side of the dotenv-read gap under +Setup — NOT the `Read`\n * branch inside `canUseTool` above, which is dead code against the real SDK for any in-cwd path (see\n * that branch's comment for the empirical evidence). `PreToolUse` hooks are a structurally separate\n * control path from `canUseTool`: the SDK's internal `checkPermissions` auto-allow for in-cwd Read\n * happens before the `canUseTool` callback, but it does NOT suppress `PreToolUse` — confirmed\n * empirically (throwaway `query()` probes against the bundled CLI) that this hook fires for an in-cwd\n * Read of `.env` with `hook_event_name: \"PreToolUse\"`, `tool_name: \"Read\"`, `tool_input.file_path` set,\n * even in the same run where `canUseTool` sees zero invocations for that call.\n *\n * Only wired in when `cfg.setupScope != null` (the caller passes an empty array of matchers\n * otherwise, so this never changes behavior for read_only_execution/artifact_write/data_write/\n * context_write_authz components — those don't use setupScope and are unaffected).\n */\nfunction makeSetupReadDenyHook(cfg: GuardConfig, denials: Denial[]): HookCallbackMatcher[] {\n if (cfg.setupScope == null) return [];\n return [\n {\n matcher: \"Read\",\n hooks: [\n async (input) => {\n if (input.hook_event_name !== \"PreToolUse\") return { continue: true };\n const toolInput = input.tool_input as Record<string, unknown> | null | undefined;\n const target =\n toolInput != null && typeof toolInput[\"file_path\"] === \"string\"\n ? (toolInput[\"file_path\"] as string)\n : \"\";\n if (!referencesDotenvPath(target)) return { continue: true };\n const reason =\n \"reading a dotenv path via Read is blocked by the read_only_execution guardrail; the \" +\n \"setup credential design writes an empty .env template and is never meant to read it back.\";\n denials.push({ tool: \"Read\", reason, command: target });\n return {\n continue: false,\n decision: \"block\",\n reason,\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason: reason,\n },\n };\n },\n ],\n },\n ];\n}\n\n/**\n * Build the `canUseTool` gate for a component, plus the `PreToolUse` hooks needed to actually enforce\n * the +Setup dotenv-read gap's Read side (see `makeSetupReadDenyHook`'s comment — `canUseTool` alone\n * does not reach in-cwd Read in the real SDK). Both share the same `denials` array so the trace sees\n * every enforcement point that fired, however it fired. Callers MUST wire `hooks` into the `query()`\n * `Options.hooks.PreToolUse` for every invocation this guard's `canUseTool` is passed to — passing one\n * without the other leaves the Read side unenforced for +Setup. `hooks` is `[]` for every non-setup\n * component (readOnly/writeScope/mutation/context_write_authz), so wiring it unconditionally is safe\n * and does not change behavior for those paths.\n *\n * Fail-closed: anything not explicitly permitted by `canUseTool` is denied with guidance.\n */\nexport function makeReadOnlyGuard(\n cfg: GuardConfig,\n): { canUseTool: CanUseTool; denials: Denial[]; hooks: HookCallbackMatcher[] } {\n const denials: Denial[] = [];\n const hooks = makeSetupReadDenyHook(cfg, denials);\n\n const canUseTool: CanUseTool = async (toolName, input) => {\n // Read: this branch is DEAD CODE against the real SDK for any in-cwd path, and is kept only as\n // defense-in-depth for a future SDK version. Confirmed empirically (throwaway query() probes\n // against the bundled CLI, both with `allowedTools: [\"Read\"]` and `allowedTools: []`): the SDK's\n // internal `checkPermissions` auto-resolves `{behavior:\"allow\"}` for any path inside the session\n // cwd/`additionalDirectories` BEFORE this developer `canUseTool` callback ever runs — the callback\n // is simply never invoked for Read there, so this dotenv check below cannot fire in practice. The\n // live enforcement point is the `PreToolUse` hook built by `makeSetupReadDenyHook` below, which\n // DOES fire for in-cwd Read (hooks are a structurally separate control path from `canUseTool` —\n // confirmed by the same probes). This branch would only matter for a Read outside cwd/\n // additionalDirectories, which setup components don't produce, so treat it as inert today.\n if (toolName === \"Read\") {\n if (cfg.setupScope != null) {\n const target = typeof input[\"file_path\"] === \"string\" ? (input[\"file_path\"] as string) : \"\";\n if (referencesDotenvPath(target)) {\n const reason =\n \"reading a dotenv path via Read is blocked by the read_only_execution guardrail; the \" +\n \"setup credential design writes an empty .env template and is never meant to read it back.\";\n denials.push({ tool: \"Read\", reason, command: target });\n return deny(reason);\n }\n }\n return allow(input);\n }\n if (toolName === \"Task\" || toolName === \"TodoWrite\") {\n return allow(input);\n }\n\n if (toolName === \"Bash\") {\n const command = typeof input[\"command\"] === \"string\" ? (input[\"command\"] as string) : \"\";\n // Dotenv-read pair: checked FIRST and unconditionally, before DESTRUCTIVE/REDIRECTION and\n // before the setupScope branch below. Either regex alone is over-broad (see\n // DOTENV_READER_COMMANDS/DOTENV_PATH's doc comments above) — the pairing is load-bearing and\n // is never relaxed, exactly like DESTRUCTIVE/REDIRECTION.\n if (DOTENV_READER_COMMANDS.test(command) && referencesDotenvPath(command)) {\n const reason =\n \"reading a dotenv file's contents is blocked by the read_only_execution guardrail; the \" +\n \"setup credential design writes an empty .env template and is never meant to read it back.\";\n denials.push({ tool: \"Bash\", reason, command });\n return deny(reason);\n }\n if (DESTRUCTIVE.test(command) || REDIRECTION.test(command)) {\n const reason =\n \"destructive or file-writing bash is blocked by the read_only_execution guardrail; \" +\n \"all data access must go through the read-only `wren` CLI.\";\n denials.push({ tool: \"Bash\", reason, command });\n return deny(reason);\n }\n // +Setup: broadened beyond `wren` (e.g. `dlt` connector CLIs) — the destructive/redirection\n // and dotenv-read checks above still run first and are never relaxed for setup.\n if (cfg.setupScope != null) return allow(input);\n if (firstToken(command) !== \"wren\") {\n const reason =\n \"only `wren` CLI invocations are permitted (data access goes through the semantic \" +\n \"layer); this command is blocked by the read_only_execution guardrail.\";\n denials.push({ tool: \"Bash\", reason, command });\n return deny(reason);\n }\n return allow(input);\n }\n\n if (toolName === \"Write\" || toolName === \"Edit\") {\n if (cfg.mutation) {\n if (cfg.mutation.contextScope) {\n // +Constitutive: context_write_authz — a path-scoped gate, distinct from writeScope\n // (render artifacts) and from the unscoped mutation approval gate below. The scopes must\n // never cross: a data path or a models/knowledge path outside this component's own scope\n // is denied outright, before the approval question is even reached.\n const target = typeof input[\"file_path\"] === \"string\" ? (input[\"file_path\"] as string) : \"\";\n const abs = resolvePath(cfg.cwd, target);\n const scopeAbs = resolvePath(cfg.cwd, cfg.mutation.contextScope);\n if (!withinScope(abs, scopeAbs)) {\n const reason =\n `write to '${target}' is outside the context_write_authz scope '${cfg.mutation.contextScope}'.`;\n denials.push({ tool: toolName, reason, command: target });\n return deny(reason);\n }\n // In scope: the path authorization gate clears, but the apply is still gated on human\n // approval, which this guard does not provide — same fail-closed philosophy as the\n // unscoped mutation branch below, just reached from inside the scope.\n const gate = cfg.mutation.approvalRequired ? \"human approval\" : \"the must_dry_run gate\";\n const reason =\n `${toolName} is inside the context_write_authz scope '${cfg.mutation.contextScope}', ` +\n `but the apply still requires ${gate} to clear first; that approval is borrowed from ` +\n \"the SDK embedder's own canUseTool/approval channel, which this guard does not \" +\n \"provide, so it denies by default (fail-closed).\";\n denials.push({ tool: toolName, reason, command: target });\n return deny(reason);\n }\n const gate = cfg.mutation.approvalRequired ? \"human approval\" : \"the must_dry_run gate\";\n const reason =\n `${toolName} is the gated apply of a mutating component and requires ${gate} to clear ` +\n \"first; that approval is borrowed from the SDK embedder's own canUseTool/approval \" +\n \"channel, which this guard does not provide, so it denies by default (fail-closed).\";\n denials.push({ tool: toolName, reason });\n return deny(reason);\n }\n if (cfg.setupScope != null) {\n // +Setup: onboarding writes (a new project's files, an EMPTY .env template, generated MDL)\n // are scoped to the project root, not denied outright — this branch is reached because setup\n // components carry neither `cfg.mutation` nor `cfg.writeScope`.\n const target = typeof input[\"file_path\"] === \"string\" ? (input[\"file_path\"] as string) : \"\";\n const abs = resolvePath(cfg.cwd, target);\n const scopeAbs = resolvePath(cfg.cwd, cfg.setupScope);\n if (withinScope(abs, scopeAbs)) return allow(input);\n const reason = `write to '${target}' is outside the setup project-root scope '${cfg.setupScope}'.`;\n denials.push({ tool: toolName, reason, command: target });\n return deny(reason);\n }\n if (cfg.writeScope) {\n const target = typeof input[\"file_path\"] === \"string\" ? (input[\"file_path\"] as string) : \"\";\n const abs = resolvePath(cfg.cwd, target);\n const scopeAbs = resolvePath(cfg.cwd, cfg.writeScope);\n if (withinScope(abs, scopeAbs)) return allow(input);\n const reason = `write to '${target}' is outside the permitted artifact scope '${cfg.writeScope}'.`;\n denials.push({ tool: toolName, reason, command: target });\n return deny(reason);\n }\n const reason =\n `${toolName} is blocked: this component is read-only (programmatic render flavor keeps the ` +\n `agent from writing files; the dispatcher renders the dashboard from your envelope).`;\n denials.push({ tool: toolName, reason });\n return deny(reason);\n }\n\n // Fail-closed for anything unexpected.\n const reason = `tool '${toolName}' is not permitted for this component.`;\n denials.push({ tool: toolName, reason });\n return deny(reason);\n };\n\n return { canUseTool, denials, hooks };\n}\n","/**\n * Minimal OpenAI-compatible chat client for the hybrid-staged path (see docs/spec/capability-model.md §7.2).\n *\n * A local step (provider `openai_compat`, e.g. ollama's `http://localhost:11434/v1`) is executed by\n * calling `POST {endpoint}/chat/completions` directly — NOT through the Claude SDK, whose `agents[].model`\n * is a restricted alias union that loud-fails on a local model id (SDK-NOTES.md #1). ollama speaks the\n * OpenAI Chat Completions shape, not the Anthropic Messages shape, so this is a distinct, deliberately\n * tiny client — no streaming, no tools, no retries. It is the \"third provider-aware back-end\" embryo:\n * enough to prove a per-step local model can be marshaled into a cloud run, not a production LLM client.\n *\n * Live-gated: exercised only when an ollama (or other OpenAI-compat) endpoint is reachable. The request\n * SHAPING is unit-tested via {@link buildChatRequest} with no network.\n */\nimport type { StepMessage } from \"./route.js\";\n\nexport interface ChatRequest {\n model: string;\n messages: StepMessage[];\n stream: false;\n /** Deterministic-leaning default; a local step is a bounded transform, not open-ended generation. */\n temperature: number;\n}\n\n/** Build the JSON body for an OpenAI-compatible `/chat/completions` call. Pure (no network). */\nexport function buildChatRequest(model: string, messages: StepMessage[]): ChatRequest {\n return { model, messages, stream: false, temperature: 0 };\n}\n\n/** Extract the assistant text from an OpenAI-compatible completion response. Pure. */\nexport function extractCompletionText(body: unknown): string {\n const choices = (body as { choices?: unknown })?.choices;\n if (!Array.isArray(choices) || choices.length === 0) {\n throw new Error(\"openai_compat response has no choices\");\n }\n const content = (choices[0] as { message?: { content?: unknown } })?.message?.content;\n if (typeof content !== \"string\") {\n throw new Error(\"openai_compat response choice has no message.content string\");\n }\n return content;\n}\n\nexport interface CallLocalOptions {\n endpoint: string;\n model: string;\n messages: StepMessage[];\n /** Optional bearer token (ollama ignores it; other OpenAI-compat servers may require it). */\n apiKey?: string;\n /** Injectable for tests; defaults to global fetch. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Call an OpenAI-compatible chat endpoint and return the assistant text. Live-gated (needs a reachable\n * endpoint); the request/response shaping is covered by {@link buildChatRequest} /\n * {@link extractCompletionText} tests, and a stubbed `fetchImpl` can drive this end-to-end offline.\n */\nexport async function callOpenAiCompat(opts: CallLocalOptions): Promise<string> {\n const url = `${opts.endpoint.replace(/\\/$/, \"\")}/chat/completions`;\n const headers: Record<string, string> = { \"content-type\": \"application/json\" };\n if (opts.apiKey) headers[\"authorization\"] = `Bearer ${opts.apiKey}`;\n const doFetch = opts.fetchImpl ?? fetch;\n const res = await doFetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(buildChatRequest(opts.model, opts.messages)),\n });\n if (!res.ok) {\n throw new Error(`openai_compat call to ${url} failed: ${res.status} ${res.statusText}`);\n }\n return extractCompletionText(await res.json());\n}\n","/**\n * Alternative hybrid realization: per-step model calls as a TOOL the orchestrator invokes (spike\n * follow-up to `runHybridStaged`). Instead of Warble driving the step sequence itself, a single SDK\n * `query()` loop runs an orchestrator (the `orchestrator` tier, e.g. sonnet) that calls one neutral\n * `dispatch_step` tool per step, in order. Warble supplies only the tool; the SDK loop owns the\n * sequencing — so orchestration is *borrowed* again (vision invariant #3), and the local model becomes\n * \"just another borrowed action\" alongside `wren`.\n *\n * Provider stays OUT of the driver prompt: the prompt names step names + the consumes/produces\n * marshaling only. The `dispatch_step` handler reads each step's resolved binding and routes it —\n * local (`openai_compat`) → a direct ollama call; cloud (`anthropic`) → a scoped nested `query()` on\n * that step's tier model (with the read-only wren tools, so a strong SQL step still runs on Opus).\n *\n * Trade-off vs `runHybridStaged`: here the step order + marshaling are LLM-driven (the orchestrator\n * decides), so it is less deterministic than the staged executor — the same axis the all-cloud\n * sdk-split path already lives on. Selected at runtime via `WARBLE_HYBRID_MODE=tool`.\n */\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { query, tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n HookCallbackMatcher,\n Options,\n SDKMessage,\n SDKResultMessage,\n SDKAssistantMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { z } from \"zod\";\n\nimport { DispatchError } from \"./error.js\";\nimport { makeReadOnlyGuard } from \"./guardrails.js\";\nimport { callOpenAiCompat } from \"./localClient.js\";\nimport { DESTRUCTIVE_BASH_DENY, type DispatchPlan } from \"./options.js\";\nimport type { StagedStep } from \"./route.js\";\nimport type { RunResult, RunConfig, Trace, StepUsage } from \"./run.js\";\n\nfunction isResult(msg: SDKMessage): msg is SDKResultMessage {\n return msg.type === \"result\";\n}\nfunction isAssistant(msg: SDKMessage): msg is SDKAssistantMessage {\n return msg.type === \"assistant\";\n}\nfunction requireFinalText(result: SDKResultMessage | undefined): string {\n if (result === undefined) throw new DispatchError(\"the query() stream ended without a result message\");\n if (result.subtype !== \"success\") {\n throw new DispatchError(`agent run failed (${result.subtype}): ${result.errors.join(\"; \")}`);\n }\n return result.result;\n}\nfunction cloudPreamble(cwd: string): string {\n return [\n `You are bound to the wren project at \\`${cwd}\\` (your working directory).`,\n \"All data access MUST go through the `wren` CLI — never raw SQL clients.\",\n ].join(\"\\n\");\n}\n\n/** The user turn for one step: the question plus whatever the orchestrator marshaled in as `inputs`. */\nfunction stepUserPrompt(question: string, inputsText: string): string {\n return inputsText ? `Question: ${question}\\n\\nInputs from the previous step:\\n${inputsText}` : `Question: ${question}`;\n}\n\n/**\n * The orchestrator's system prompt — PROVIDER-AGNOSTIC. Lists the steps in order by name and the\n * produces→consumes marshaling; it never says which step is local vs cloud (that is the handler's job,\n * from the binding). So the same prompt shape is emitted whether the binding is all-cloud or hybrid.\n */\nexport function buildToolDriverPrompt(steps: readonly StagedStep[]): string {\n const producers = new Map<string, string>();\n for (const s of steps) if (s.produces) producers.set(s.produces, s.name);\n const lines = steps.map((s, i) => {\n const parts = [`${i + 1}. Call the \\`dispatch_step\\` tool with step=\"${s.name}\".`];\n if (s.consumes.length > 0) {\n const srcs = s.consumes\n .map((slot) => {\n const p = producers.get(slot);\n return p ? `the text step \"${p}\" returned` : `\"${slot}\"`;\n })\n .join(\", \");\n parts.push(`Pass ${srcs} as the tool's \\`inputs\\` argument.`);\n }\n if (s.conditional) parts.push(\"(Only if the previous step's output indicates the query failed and needs repair.)\");\n return parts.join(\" \");\n });\n return [\n \"You orchestrate a multi-step data task by calling the `dispatch_step` tool exactly once per step, in order.\",\n \"You have NO other tools and you must NOT try to answer yourself — each step runs on its own configured model behind the tool.\",\n \"\",\n \"Steps, in order:\",\n \"\",\n ...lines,\n \"\",\n \"Marshal each step's returned text into the next step's `inputs` exactly as noted above. Your FINAL \" +\n \"message MUST be the last executed step's returned text verbatim — do not summarize it or add commentary.\",\n ].join(\"\\n\");\n}\n\ninterface CloudCtx {\n cwd: string;\n env: Record<string, string>;\n maxTurns: number;\n canUseTool: Options[\"canUseTool\"];\n /** From `makeReadOnlyGuard`'s `hooks` — see that function's doc comment. `[]` for non-setup components. */\n hooks: HookCallbackMatcher[];\n}\n\n/** Cloud step: a scoped nested query() on the step's tier model, with the read-only wren tools. */\nasync function runCloudStep(step: StagedStep, question: string, inputsText: string, ctx: CloudCtx): Promise<string> {\n const options: Options = {\n cwd: ctx.cwd,\n permissionMode: \"default\",\n maxTurns: ctx.maxTurns,\n model: step.model,\n systemPrompt: `${cloudPreamble(ctx.cwd)}\\n\\n${step.prompt}`,\n tools: [\"Read\", \"Bash\"],\n allowedTools: [\"Read\"],\n disallowedTools: [...DESTRUCTIVE_BASH_DENY],\n canUseTool: ctx.canUseTool,\n // Read never reaches `canUseTool` for an in-cwd path in the real SDK (see guardrails.ts); this\n // hook is the live enforcement point for the +Setup dotenv-read gap's Read side.\n hooks: { PreToolUse: ctx.hooks },\n env: ctx.env,\n };\n const msgs: SDKMessage[] = [];\n for await (const m of query({ prompt: stepUserPrompt(question, inputsText), options })) msgs.push(m);\n return requireFinalText(msgs.find(isResult));\n}\n\n/**\n * Run the hybrid-tool path: one orchestrator query() + a `dispatch_step` tool that routes each step to\n * its bound provider. Mirrors {@link runHybridStaged}'s outputs (result.txt / trace.json / RunResult).\n */\nexport async function runHybridTool(plan: DispatchPlan, cfg: RunConfig): Promise<RunResult> {\n mkdirSync(cfg.outDir, { recursive: true });\n const cwd = plan.options.cwd ?? process.cwd();\n const { canUseTool, denials, hooks } = makeReadOnlyGuard({\n readOnly: plan.meta.readOnly,\n writeScope: null,\n cwd,\n setupScope: plan.meta.setupScope,\n });\n\n const venvBin = join(cwd, \".venv\", \"bin\");\n const pathEnv = existsSync(venvBin) ? `${venvBin}:${process.env.PATH ?? \"\"}` : (process.env.PATH ?? \"\");\n const env: Record<string, string> = { ...(process.env as Record<string, string>), PATH: pathEnv };\n\n const steps = plan.meta.stagedSteps;\n const question = plan.prompt;\n const maxTurns = plan.options.maxTurns ?? 40;\n const traceSteps: StepUsage[] = [];\n\n const dispatchStep = tool(\n \"dispatch_step\",\n \"Execute one named step of the task on its own configured model and return its text output.\",\n { step: z.string(), inputs: z.string().optional() },\n async (args) => {\n const step = steps.find((s) => s.name === args.step);\n if (!step) {\n return { content: [{ type: \"text\" as const, text: `ERROR: unknown step '${args.step}'` }], isError: true };\n }\n const inputsText = args.inputs ?? \"\";\n let text: string;\n // `provider` is an open string, but only `openai_compat` has a local transport wired here; any\n // other provider falls through to the cloud path. Routing arbitrary providers to their own\n // transport is the per-provider adapter-registry follow-up work.\n if (step.provider === \"openai_compat\") {\n if (!step.endpoint) throw new DispatchError(`local step '${step.name}' has no endpoint`);\n text = await callOpenAiCompat({\n endpoint: step.endpoint,\n model: step.model,\n messages: [\n { role: \"system\", content: step.prompt },\n { role: \"user\", content: stepUserPrompt(question, inputsText) },\n ],\n });\n process.stderr.write(`warble hybrid-tool: step '${step.name}' → local ${step.model}\\n`);\n } else {\n text = await runCloudStep(step, question, inputsText, { cwd, env, maxTurns, canUseTool, hooks });\n process.stderr.write(`warble hybrid-tool: step '${step.name}' → cloud ${step.model}\\n`);\n }\n traceSteps.push({ model: `${step.provider}:${step.model}`, parent_tool_use_id: step.name, usage: null });\n return { content: [{ type: \"text\" as const, text }] };\n },\n );\n\n const server = createSdkMcpServer({ name: \"warble\", version: \"0.0.0\", tools: [dispatchStep] });\n const driverModel = plan.options.model ?? \"sonnet\";\n const driverOptions: Options = {\n cwd,\n permissionMode: \"default\",\n maxTurns,\n model: driverModel,\n systemPrompt: buildToolDriverPrompt(steps),\n mcpServers: { warble: server },\n allowedTools: [\"mcp__warble__dispatch_step\"],\n env,\n };\n\n const msgs: SDKMessage[] = [];\n for await (const m of query({ prompt: question, options: driverOptions })) msgs.push(m);\n const result = msgs.find(isResult);\n const finalText = requireFinalText(result);\n for (const m of msgs.filter(isAssistant)) {\n traceSteps.push({ model: m.message.model, parent_tool_use_id: \"orchestrator\", usage: m.message.usage });\n }\n\n const trace: Trace = {\n target: plan.meta.target,\n verb: plan.meta.verb,\n model: `hybrid-tool(driver=${driverModel})`,\n split: false,\n run:\n result && result.subtype === \"success\"\n ? { total_cost_usd: result.total_cost_usd, duration_ms: result.duration_ms, duration_api_ms: result.duration_api_ms, num_turns: result.num_turns }\n : null,\n usage: null,\n modelUsage: {},\n steps: traceSteps,\n denials,\n };\n\n writeFileSync(join(cfg.outDir, \"result.txt\"), finalText, \"utf8\");\n writeFileSync(join(cfg.outDir, \"trace.json\"), JSON.stringify(trace, null, 2) + \"\\n\", \"utf8\");\n return {\n finalText,\n trace,\n htmlPath: null,\n denials,\n sessionId: result?.session_id ?? null,\n renderDegraded: null,\n };\n}\n","/**\n * Render step — reuse the Warble reference renderer (`warble render`) rather than reimplementing it\n * in TS (ir-schema §v0.3). The agent (programmatic flavor) emits a\n * `{ blocks, summary }` envelope as its final message; we hand that text to `warble render`, which\n * deterministically produces a self-contained `dashboard.html`. Same envelope ⇒ identical bytes as\n * the file target — that is the \"one renderer, many back-ends\" contract being exercised across\n * languages.\n */\nimport { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { DispatchError } from \"./error.js\";\n\nexport interface RenderResult {\n outPath: string;\n /** stderr from `warble render` (it logs \"wrote … (N block(s))\"). */\n log: string;\n}\n\n/**\n * Write the captured agent output to a temp file and shell out to `warble render`. `warble render`\n * tolerates the model fencing/prose-wrapping the envelope and unwraps a `--output-format json`\n * result object (see the Rust `parseEnvelope`), so we pass the raw final text through unchanged.\n */\nexport function renderEnvelope(\n finalText: string,\n outPath: string,\n opts: { warbleBin: string; title?: string },\n): RenderResult {\n const dir = mkdtempSync(join(tmpdir(), \"warble-sdk-\"));\n const envelopePath = join(dir, \"envelope.txt\");\n writeFileSync(envelopePath, finalText, \"utf8\");\n\n const args = [\"render\", envelopePath, \"--out\", outPath];\n if (opts.title) args.push(\"--title\", opts.title);\n\n const proc = spawnSync(opts.warbleBin, args, { encoding: \"utf8\" });\n if (proc.error) {\n throw new DispatchError(missingWarbleBinaryMessage(opts.warbleBin, proc.error));\n }\n if (proc.status !== 0) {\n throw new DispatchError(\n `warble render exited ${proc.status}: ${proc.stderr?.trim() || proc.stdout?.trim() || \"no output\"}`,\n );\n }\n return { outPath, log: (proc.stderr ?? \"\").trim() };\n}\n\n/**\n * One actionable message for a failed `spawnSync` on the `warble` binary. ENOENT (the binary isn't\n * on PATH, or `warbleBin`/`--warble-bin` points at nothing) is by far the common case for someone\n * who installed this npm package on its own — `@warble/claude-agent-sdk` never bundles or fetches\n * the `warble` binary itself, so it names the one channel that's genuinely public and works\n * unauthenticated: `cargo install warble-cli` (crates.io). Any other spawn error (e.g. a permission\n * problem on an existing path) gets the underlying message plus the override, without the\n * misleading \"go install it\" hint.\n *\n * Names `warbleBin` (the actual knob) before `--warble-bin` (its CLI spelling): this message fires\n * from three call sites with different surfaces — the `warble-agent-sdk` CLI (where `--warble-bin`\n * is real), a library consumer calling `renderEnvelope` directly (no CLI flag exists — only the\n * `warbleBin` option), and an emitted standalone agent module (same: only its `RunOptions.warbleBin`\n * option exists). Leading with a flag a library caller has no way to pass would be actionable in\n * only one of the three contexts.\n */\nfunction missingWarbleBinaryMessage(warbleBin: string, error: NodeJS.ErrnoException): string {\n const base = `failed to run '${warbleBin} render': ${error.message}`;\n if (error.code === \"ENOENT\") {\n return (\n `${base}\\n` +\n `The 'warble' binary was not found. Install it with 'cargo install warble-cli' ` +\n `(requires a Rust toolchain; installs from crates.io), or set the 'warbleBin' option ` +\n `(CLI: --warble-bin <path>) to point at an existing 'warble' binary.`\n );\n }\n return `${base} (set the 'warbleBin' option, or pass --warble-bin <path> on the CLI, to point at a different binary)`;\n}\n","/**\n * Drive the Agent SDK `query()` loop and capture what the file target cannot: a `{ blocks, summary }`\n * render envelope AND a per-step usage trace. The agent loop, permissions, sandbox, and\n * tool calls are all borrowed from the SDK — this module only assembles options, attaches the\n * runtime guardrail, consumes the message stream, and hands the envelope to `warble render`.\n */\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { query } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n HookCallbackMatcher,\n ModelUsage,\n NonNullableUsage,\n Options,\n SDKAssistantMessage,\n SDKMessage,\n SDKResultMessage,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nimport {\n classifyConditionalStep,\n DEFAULT_MAX_REPAIR_ATTEMPTS,\n runRepairLoop,\n type StepIdentity,\n type StepOutcome,\n} from \"./conditional.js\";\nimport { DispatchError } from \"./error.js\";\nimport { ChatEventMapper, type WarbleChatEvent } from \"./events.js\";\nimport { makeReadOnlyGuard, type Denial } from \"./guardrails.js\";\nimport { runHybridTool } from \"./hybridTool.js\";\nimport { callOpenAiCompat } from \"./localClient.js\";\nimport type { DispatchPlan, RenderGate } from \"./options.js\";\nimport { renderEnvelope } from \"./render.js\";\nimport { buildStepMessages, type StagedStep } from \"./route.js\";\n\n// --- trace (per-step cost/latency → eval) -------------------------------------------------------\n\n/** One assistant turn's usage. `parent_tool_use_id` distinguishes driver turns from subagent turns. */\nexport interface StepUsage {\n model: string;\n parent_tool_use_id: string | null;\n usage: unknown;\n}\n\nexport interface Trace {\n target: string;\n verb: string;\n model: string;\n split: boolean;\n run: {\n total_cost_usd: number;\n duration_ms: number;\n duration_api_ms: number;\n num_turns: number;\n } | null;\n usage: NonNullableUsage | null;\n /** Per-model usage — and since each tier maps to a distinct model, this is per-tier cost. */\n modelUsage: Record<string, ModelUsage>;\n /** Per assistant turn (per-step granularity the headless file target can't produce). */\n steps: StepUsage[];\n denials: Denial[];\n}\n\nfunction isResult(msg: SDKMessage): msg is SDKResultMessage {\n return msg.type === \"result\";\n}\n\nfunction isAssistant(msg: SDKMessage): msg is SDKAssistantMessage {\n return msg.type === \"assistant\";\n}\n\n/** Pure: fold the captured message stream + guardrail denials into a trace. */\nexport function aggregateTrace(\n messages: readonly SDKMessage[],\n meta: { target: string; verb: string; model: string; split: boolean },\n denials: Denial[],\n): Trace {\n const steps: StepUsage[] = messages.filter(isAssistant).map((m) => ({\n model: m.message.model,\n parent_tool_use_id: m.parent_tool_use_id,\n usage: m.message.usage,\n }));\n\n const result = messages.find(isResult);\n const run =\n result === undefined\n ? null\n : {\n total_cost_usd: result.total_cost_usd,\n duration_ms: result.duration_ms,\n duration_api_ms: result.duration_api_ms,\n num_turns: result.num_turns,\n };\n\n return {\n target: meta.target,\n verb: meta.verb,\n model: meta.model,\n split: meta.split,\n run,\n usage: result?.usage ?? null,\n modelUsage: result?.modelUsage ?? {},\n steps,\n denials,\n };\n}\n\n// --- drive --------------------------------------------------------------------------------------\n\nexport interface RunResult {\n finalText: string;\n trace: Trace;\n htmlPath: string | null;\n denials: Denial[];\n /** The SDK's session id for this run, if the result carried one (multi-turn resume anchor). */\n sessionId: string | null;\n /** Set when a best-effort `render_contract` failed at runtime (`warble render` exited non-zero)\n * and the turn degraded instead of hard-failing (`render.onFailure === \"degrade\"`): `htmlPath`\n * stays `null`, `finalText` is still the agent's answer, and this carries why the render was\n * skipped. `null` on every run that never hit a render failure — a required/safety-critical\n * render failure still throws (`DispatchError`/`DispatchSessionError`) and never reaches here. */\n renderDegraded: { reason: string } | null;\n}\n\nexport interface RunConfig {\n outDir: string;\n warbleBin: string;\n /** Optional dashboard title passed through to `warble render`. */\n title?: string;\n /** Resume a prior turn's session (multi-turn continuity, session.ts). Mutually exclusive in practice\n * with a fresh turn — omit for turn 1. */\n resume?: string;\n /** Opt-in streaming sink (`chat --stream-json`, cli.ts): called once per `WarbleChatEvent` as the\n * message stream is consumed, not batched after the fact. Only wired on the main (single/split) SDK\n * loop below — the hybrid-staged executor passes through with no events. */\n onEvent?: (event: WarbleChatEvent) => void;\n}\n\n/**\n * A dispatch failure that still carries the SDK's session id, when the result message had one —\n * e.g. `error_max_turns`: the run failed, but the conversation itself is still resumable. A caller\n * that wants to continue the SAME session with more turns (rather than re-dispatching a fresh\n * prompt) needs this id; a plain `DispatchError` would discard it. `sessionId` is null only when\n * the SDK never produced a result message at all (no session to resume).\n */\nexport class DispatchSessionError extends DispatchError {\n constructor(\n message: string,\n readonly sessionId: string | null,\n ) {\n super(message);\n this.name = \"DispatchSessionError\";\n }\n}\n\n/**\n * Realize a `gate.kind === \"realize\"` render, applying the resolved `onFailure` policy on a runtime\n * failure (`warble render` exiting non-zero): `\"degrade\"` (best-effort `render_contract`) catches the\n * error and reports it back instead of throwing, so the turn still succeeds with the agent's own\n * `finalText`; `\"fail\"` (required/safety-critical, or the facet absent — the additive default) rethrows\n * exactly as before this change. Exported so the branch can be exercised offline (no live SDK / release\n * binary needed): a deliberately-unresolvable `warbleBin` makes `renderEnvelope` fail deterministically.\n */\nexport function realizeRender(\n gate: RenderGate,\n finalText: string,\n outPath: string,\n renderOpts: { warbleBin: string; title?: string },\n): { htmlPath: string | null; renderDegraded: { reason: string } | null } {\n try {\n renderEnvelope(finalText, outPath, renderOpts);\n return { htmlPath: outPath, renderDegraded: null };\n } catch (err) {\n // best-effort render_contract: degrade to the agent's own text instead of failing the whole turn\n // (capability-model.md — only safety-critical/required capabilities never silently degrade).\n // `onFailure` absent/\"fail\" preserves the prior hard-fail behavior exactly.\n if (gate.onFailure !== \"degrade\") throw err;\n const reason = err instanceof Error ? err.message : String(err);\n process.stderr.write(`warble-agent-sdk: render_contract degraded (best-effort) — ${reason}\\n`);\n return { htmlPath: null, renderDegraded: { reason } };\n }\n}\n\n/** Extract the final assistant text from the result message (success subtype). */\nfunction requireFinalText(result: SDKResultMessage | undefined): string {\n if (result === undefined) {\n throw new DispatchSessionError(\"the query() stream ended without a result message\", null);\n }\n if (result.subtype !== \"success\") {\n // Every non-success result arm carries `errors: string[]`.\n throw new DispatchSessionError(\n `agent run failed (${result.subtype}): ${result.errors.join(\"; \")}`,\n result.session_id ?? null,\n );\n }\n return result.result;\n}\n\n/**\n * Run a dispatch plan against the live Agent SDK, then render + trace. Writes `result.txt`,\n * `trace.json`, and (programmatic realize flavor) `dashboard.html` into `outDir`.\n */\nexport async function runDispatch(plan: DispatchPlan, cfg: RunConfig): Promise<RunResult> {\n // Hybrid: steps span providers. Two realizations, selected at runtime:\n // - staged (default): the back-end drives the step sequence itself (deterministic; good for eval).\n // - tool (WARBLE_HYBRID_MODE=tool): one orchestrator query() calls a `dispatch_step` tool per step,\n // so sequencing is borrowed from the SDK loop again (see hybridTool.ts).\n // Routed here so the SDK-single/split path is untouched.\n if (plan.meta.mode === \"hybrid-staged\") {\n return process.env[\"WARBLE_HYBRID_MODE\"] === \"tool\"\n ? runHybridTool(plan, cfg)\n : runHybridStaged(plan, cfg);\n }\n\n mkdirSync(cfg.outDir, { recursive: true });\n\n const cwd = plan.options.cwd ?? process.cwd();\n const gate = plan.meta.render;\n const writeScope = gate.kind === \"realize\" && gate.flavor === \"prompt\" ? gate.scope : null;\n const { canUseTool, denials, hooks } = makeReadOnlyGuard({\n readOnly: plan.meta.readOnly,\n writeScope,\n cwd,\n setupScope: plan.meta.setupScope,\n });\n\n // P2: make the bound project queryable at run time without a manual\n // PATH dance. The SDK spawns tool subprocesses (and Task subagents) with `env`; when omitted it\n // defaults to the parent `process.env`, but that default does not reliably reach split subagents.\n // We set it explicitly and prepend the project's `.venv/bin` (the eval-runner convention) so the\n // agent's `wren` resolves from the bound project first, then the ambient PATH.\n const venvBin = join(cwd, \".venv\", \"bin\");\n const pathEnv = existsSync(venvBin)\n ? `${venvBin}:${process.env.PATH ?? \"\"}`\n : (process.env.PATH ?? \"\");\n const env: Record<string, string> = { ...(process.env as Record<string, string>), PATH: pathEnv };\n\n const options: Options = {\n ...plan.options,\n canUseTool,\n // Read never reaches `canUseTool` for an in-cwd path in the real SDK (see guardrails.ts); this\n // hook is the live enforcement point for the +Setup dotenv-read gap's Read side.\n hooks: { ...plan.options.hooks, PreToolUse: [...(plan.options.hooks?.PreToolUse ?? []), ...hooks] },\n env,\n ...(cfg.resume ? { resume: cfg.resume } : {}),\n };\n\n const mapper = new ChatEventMapper(plan.meta.verb);\n const messages: SDKMessage[] = [];\n for await (const message of query({ prompt: plan.prompt, options })) {\n messages.push(message);\n if (cfg.onEvent) for (const event of mapper.next(message)) cfg.onEvent(event);\n }\n\n const result = messages.find(isResult);\n const finalText = requireFinalText(result);\n // requireFinalText throws on a failed/missing result before this line, so the closing step event\n // is only emitted on success. A failed turn surfaces to the consumer via the process exit / error\n // path, not a step_finish(ok:false) event; mapper.finish(false, …) is exercised only by unit tests.\n if (cfg.onEvent) for (const event of mapper.finish(true)) cfg.onEvent(event);\n const trace = aggregateTrace(messages, plan.meta, denials);\n const sessionId = result?.session_id ?? null;\n\n writeFileSync(join(cfg.outDir, \"result.txt\"), finalText, \"utf8\");\n writeFileSync(join(cfg.outDir, \"trace.json\"), JSON.stringify(trace, null, 2) + \"\\n\", \"utf8\");\n\n let htmlPath: string | null = null;\n let renderDegraded: { reason: string } | null = null;\n if (gate.kind === \"realize\" && gate.flavor === \"programmatic\") {\n const out = join(cfg.outDir, \"dashboard.html\");\n const realized = realizeRender(gate, finalText, out, {\n warbleBin: cfg.warbleBin,\n ...(cfg.title ? { title: cfg.title } : {}),\n });\n htmlPath = realized.htmlPath;\n renderDegraded = realized.renderDegraded;\n } else if (plan.meta.assertion) {\n // +Assertive: the read-only verdict envelope's `status` block renders deterministically through\n // the same `warble render` path as GenBI's dashboard — one renderer, many outcomes.\n const out = join(cfg.outDir, \"status.html\");\n renderEnvelope(finalText, out, {\n warbleBin: cfg.warbleBin,\n ...(cfg.title ? { title: cfg.title } : {}),\n });\n htmlPath = out;\n }\n\n return { finalText, trace, htmlPath, denials, sessionId, renderDegraded };\n}\n\n// --- hybrid-staged executor — live-gated --------------------------------------------------------\n//\n// Drives one isolated invocation per step on that step's provider, marshaling `produces`→`consumes`\n// between them (route.ts `buildStepMessages`). Cloud steps run a scoped `query()` (with the read-only\n// data tools so a strong step can actually run SQL through `wren`); local steps hit the OpenAI-compat\n// endpoint directly (localClient.ts). This is the generalization of the file target's isolated subagent\n// invocation across providers — the mechanism the spike proves. Requires a reachable local endpoint\n// AND a Claude subscription for the mixed run, so it is exercised live, not in the offline suite.\n//\n// This deterministic guard evaluation fires ONLY on the hybrid-staged path — the back-end drives the\n// step sequence itself here, so it owns the run/skip/repair decision. On the single / sdk-split paths\n// the SDK owns the loop, so `when` is carried through and judged emergently by the model from the\n// prompt text instead (intentional — those paths have no separate deterministic scheduler).\n//\n// Conditional steps (`conditional: true`) are realized deterministically via conditional.ts's guard\n// evaluator, not punted:\n// - guarded-skip (R2): a step's `when` guard is evaluated against the outcomes/slots recorded so\n// far; false → the step is skipped and its `produces` slot is simply never set, which\n// `buildStepMessages` already marshals to downstream consumers as an explicit \"not produced\"\n// note rather than a crash (cascade-optional).\n// - repair fold-into-loop (R1): an `on_failure` guard whose target is the adjacent preceding step,\n// consuming that step's own output (the `generate_sql`→`repair_sql` shape), turns a failure of\n// that preceding step into a bounded repair turn instead of an immediate throw. Exhausting\n// `DEFAULT_MAX_REPAIR_ATTEMPTS` without recovery is a loud `DispatchError`, never a silent skip.\n// Note: the repair-fold shape only checks that the preceding step's `produces` is in the\n// conditional step's `consumes`; it does NOT require the repair step's own `produces` to match\n// the target's slot. The repair prompt is trusted to re-emit the same artifact contract.\n//\n// Step tolerance: a step must run *tolerantly* (capture its failure and continue, instead of throwing\n// and aborting the whole run) whenever some other step's `on_failure` guard names it as the target —\n// otherwise its failure would abort before that guard could ever observe `outcomes[target] ===\n// \"failure\"`. This covers the repair target AND any non-adjacent (or adjacent-but-non-consuming)\n// guarded-skip target. Every step no guard depends on keeps the original eager-throw behavior.\n\n/** A short preamble so a cloud step knows it is bound to the wren project and must query through `wren`. */\nfunction hybridCloudPreamble(cwd: string): string {\n return [\n `You are bound to the wren project at \\`${cwd}\\` (your working directory).`,\n \"All data access MUST go through the `wren` CLI — never raw SQL clients.\",\n ].join(\"\\n\");\n}\n\n/** Marshal-forward key for a step's output: its declared `produces` slot, or its name as a fallback. */\nfunction slotKey(step: StagedStep): string {\n return step.produces ?? step.name;\n}\n\ninterface StepExecResult {\n outcome: StepOutcome;\n text: string;\n}\n\ninterface StepExecContext {\n cwd: string;\n canUseTool: Options[\"canUseTool\"];\n /** From `makeReadOnlyGuard`'s `hooks` — see that function's doc comment. `[]` for non-setup components. */\n hooks: HookCallbackMatcher[];\n env: Record<string, string>;\n plan: DispatchPlan;\n steps: StepUsage[];\n recordCost: (cost: number) => void;\n}\n\n/**\n * Execute one staged step (local or cloud) and marshal its result. When `tolerant` is false (every\n * step no later guard depends on), a failure propagates exactly as before this change:\n * `requireFinalText`/`callOpenAiCompat` throw and the run aborts. When `tolerant` is true (this step\n * is named by some later `on_failure` guard, or is itself a repair attempt), a failure is caught and\n * returned as `{ outcome: \"failure\", text }` instead — the caller decides what happens next (let a\n * guarded step observe the failure, fold into a repair turn, or exhaust and loud-fail).\n */\nasync function executeStep(\n step: StagedStep,\n slots: Readonly<Record<string, string>>,\n ctx: StepExecContext,\n tolerant: boolean,\n): Promise<StepExecResult> {\n const messages = buildStepMessages(step, ctx.plan.prompt, slots);\n const userPrompt = messages.find((m) => m.role === \"user\")?.content ?? ctx.plan.prompt;\n\n try {\n // `provider` is an open string, but this back-end only knows two runtime routes today: the\n // built-in `openai_compat` local call below, else the cloud `query()` path. A novel provider\n // therefore falls through to cloud — wiring arbitrary providers to their own transport is the\n // per-provider adapter-registry follow-up work, not this binding-layer change.\n if (step.provider === \"openai_compat\") {\n if (!step.endpoint) throw new DispatchError(`local step '${step.name}' has no endpoint`);\n const text = await callOpenAiCompat({ endpoint: step.endpoint, model: step.model, messages });\n ctx.steps.push({ model: `openai_compat:${step.model}`, parent_tool_use_id: step.name, usage: null });\n process.stderr.write(`warble hybrid: step '${step.name}' → local ${step.model}\\n`);\n return { outcome: \"success\", text };\n }\n\n // Anthropic step: an isolated query() with the read-only data tools so it can run SQL via wren.\n const stepOptions: Options = {\n cwd: ctx.cwd,\n permissionMode: \"default\",\n maxTurns: ctx.plan.options.maxTurns ?? 40,\n model: step.model,\n systemPrompt: `${hybridCloudPreamble(ctx.cwd)}\\n\\n${step.prompt}`,\n tools: ctx.plan.options.tools,\n allowedTools: ctx.plan.options.allowedTools,\n disallowedTools: ctx.plan.options.disallowedTools,\n canUseTool: ctx.canUseTool,\n // Read never reaches `canUseTool` for an in-cwd path in the real SDK (see guardrails.ts); this\n // hook is the live enforcement point for the +Setup dotenv-read gap's Read side.\n hooks: { PreToolUse: ctx.hooks },\n env: ctx.env,\n };\n const msgs: SDKMessage[] = [];\n for await (const message of query({ prompt: userPrompt, options: stepOptions })) {\n msgs.push(message);\n }\n for (const m of msgs.filter(isAssistant)) {\n ctx.steps.push({ model: m.message.model, parent_tool_use_id: step.name, usage: m.message.usage });\n }\n const result = msgs.find(isResult);\n const text = requireFinalText(result);\n if (result && result.subtype === \"success\") ctx.recordCost(result.total_cost_usd);\n process.stderr.write(`warble hybrid: step '${step.name}' → cloud ${step.model}\\n`);\n return { outcome: \"success\", text };\n } catch (err) {\n if (!tolerant) throw err;\n const text = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `warble hybrid: step '${step.name}' failed (tolerant — a later guard depends on its outcome): ${text}\\n`,\n );\n return { outcome: \"failure\", text };\n }\n}\n\nasync function runHybridStaged(plan: DispatchPlan, cfg: RunConfig): Promise<RunResult> {\n mkdirSync(cfg.outDir, { recursive: true });\n const cwd = plan.options.cwd ?? process.cwd();\n const { canUseTool, denials, hooks } = makeReadOnlyGuard({\n readOnly: plan.meta.readOnly,\n writeScope: null,\n cwd,\n setupScope: plan.meta.setupScope,\n });\n\n const venvBin = join(cwd, \".venv\", \"bin\");\n const pathEnv = existsSync(venvBin)\n ? `${venvBin}:${process.env.PATH ?? \"\"}`\n : (process.env.PATH ?? \"\");\n const env: Record<string, string> = { ...(process.env as Record<string, string>), PATH: pathEnv };\n\n const slots: Record<string, string> = {};\n const outcomes: Record<string, StepOutcome> = {};\n const steps: StepUsage[] = [];\n let finalText = \"\";\n let totalCost = 0;\n const startedAll = Date.now();\n const execCtx: StepExecContext = {\n cwd,\n canUseTool,\n hooks,\n env,\n plan,\n steps,\n recordCost: (cost) => {\n totalCost += cost;\n },\n };\n\n const stagedSteps = plan.meta.stagedSteps;\n\n // Steps that some `on_failure` guard depends on must run tolerantly (see the header note): capture\n // their failure and record it so the guard can fire, rather than throwing and aborting the run.\n const failureGuardTargets = new Set<string>();\n for (const s of stagedSteps) {\n if (s.conditional && s.when !== null && s.when.guard === \"on_failure\") {\n failureGuardTargets.add(s.when.target);\n }\n }\n\n for (let i = 0; i < stagedSteps.length; i++) {\n const step = stagedSteps[i]!;\n\n if (step.conditional) {\n if (step.when === null) {\n throw new DispatchError(`conditional step '${step.name}' has no 'when' guard`);\n }\n const preceding = i > 0 ? stagedSteps[i - 1]! : null;\n const precedingIdentity: StepIdentity | null =\n preceding === null ? null : { name: preceding.name, produces: preceding.produces };\n const decision = classifyConditionalStep(step.when, step.consumes, precedingIdentity, {\n slots,\n outcomes,\n });\n\n if (decision.kind === \"skip\") {\n process.stderr.write(`warble hybrid: guard false — skipping conditional step '${step.name}'\\n`);\n continue;\n }\n\n if (decision.kind === \"repair\") {\n // Seed with the target's own failure text so the loud-fail below carries the real cause even\n // if every repair attempt itself throws before producing anything more specific.\n let lastFailureText = slots[decision.target.produces ?? decision.target.name] ?? \"\";\n const { recovered, attempts } = await runRepairLoop(DEFAULT_MAX_REPAIR_ATTEMPTS, async () => {\n const attempt = await executeStep(step, slots, execCtx, true);\n outcomes[step.name] = attempt.outcome;\n slots[slotKey(step)] = attempt.text;\n if (attempt.outcome === \"success\") finalText = attempt.text;\n else lastFailureText = attempt.text;\n return { failed: attempt.outcome === \"failure\" };\n });\n if (!recovered) {\n throw new DispatchError(\n `repair step '${step.name}' did not recover '${decision.target.name}' after ${attempts} ` +\n `attempt(s); last failure: ${lastFailureText}`,\n );\n }\n process.stderr.write(\n `warble hybrid: step '${step.name}' recovered '${decision.target.name}' (attempt ${attempts})\\n`,\n );\n continue;\n }\n // decision.kind === \"run\": guard true — fall through to the normal execution below.\n }\n\n // A later `on_failure` guard depending on this step means its failure must be observable, not\n // fatal — run it tolerantly. Every other step keeps eager-throw.\n const outcome = await executeStep(step, slots, execCtx, failureGuardTargets.has(step.name));\n outcomes[step.name] = outcome.outcome;\n slots[slotKey(step)] = outcome.text;\n if (outcome.outcome === \"success\") finalText = outcome.text;\n }\n\n const trace: Trace = {\n target: plan.meta.target,\n verb: plan.meta.verb,\n model: plan.meta.model,\n split: false,\n run: {\n total_cost_usd: totalCost,\n duration_ms: Date.now() - startedAll,\n duration_api_ms: 0,\n num_turns: steps.length,\n },\n usage: null,\n modelUsage: {},\n steps,\n denials,\n };\n\n writeFileSync(join(cfg.outDir, \"result.txt\"), finalText, \"utf8\");\n writeFileSync(join(cfg.outDir, \"trace.json\"), JSON.stringify(trace, null, 2) + \"\\n\", \"utf8\");\n\n return { finalText, trace, htmlPath: null, denials, sessionId: null, renderDegraded: null };\n}\n","/**\n * Deterministic realization of a `conditional` step's closed-vocabulary `when` guard (IR v0.3+:\n * `on_failure` / `on_flag` / `on_missing`, see `docs/spec/ir-schema.md`), for the hybrid-staged\n * executor (`run.ts`).\n *\n * Two shapes fall out of the same three-value vocabulary, keyed structurally (never on a component's\n * id/verb):\n *\n * - **repair fold-into-loop**: an `on_failure` guard whose `target` is the step immediately before\n * it, where that preceding step's `produces` is also this step's sole/consumed input (the\n * `generate_sql` → `repair_sql` shape). This is not a plain run/skip — a failed target step is\n * RETRIED via the conditional step as a bounded error-recovery turn, capped at\n * `DEFAULT_MAX_REPAIR_ATTEMPTS`. Exhausting the bound is a loud-fail (`run.ts` throws), never a\n * silent skip — an unbounded retry loop or a swallowed failure are both worse than stopping.\n * - **guarded-skip**: every other guard shape (`on_flag`, `on_missing`, or an `on_failure` that\n * isn't the adjacent-repair shape) is a plain deterministic decision: guard true → run the step,\n * guard false → skip it. A skipped step's `produces` artifact is simply never set in `slots`, and\n * `route.ts`'s `buildStepMessages` already marshals an absent slot as an explicit \"not produced\"\n * note rather than crashing — so the artifact is optional for whatever consumes it downstream\n * (cascade). No new marshaling code is needed for that half of the contract; this module only\n * supplies the run/skip/repair decision itself.\n *\n * Pure and synchronous (no SDK, no network): every function here is exercised with synthetic state,\n * which is what makes the decision layer offline-testable and lets it double as the deterministic\n * reference this back-end contributes to the shared cross-target conformance fixtures.\n */\nimport { DispatchError } from \"./error.js\";\nimport type { WhenGuard } from \"./ir.js\";\n\nexport type StepOutcome = \"success\" | \"failure\";\n\n/** The subset of a step's identity this module needs: its name (an `on_failure` target) and the\n * slot its output would land in (an `on_failure`-repair shape also requires it to be consumed). */\nexport interface StepIdentity {\n name: string;\n produces: string | null;\n}\n\nexport interface GuardState {\n /** Every slot value produced by steps run so far, keyed by their `produces` name. */\n slots: Readonly<Record<string, string>>;\n /** Every step's outcome recorded so far, keyed by step name. */\n outcomes: Readonly<Record<string, StepOutcome>>;\n}\n\nexport type ConditionalDecision =\n | { kind: \"run\" }\n | { kind: \"skip\" }\n | { kind: \"repair\"; target: StepIdentity };\n\n/** Default bound on repair attempts. Not (yet) an IR field — `max_attempts` is not part of the\n * schema this back-end reads — so this is a back-end-local runtime constant; a future IR facet\n * could override it per step without changing this module's contract. */\nexport const DEFAULT_MAX_REPAIR_ATTEMPTS = 1;\n\nfunction tryParseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/** Resolve a dotted `slot.field.nested` path against the parsed JSON of `slots[slot]`. Any failure\n * along the way (slot absent, not JSON, path doesn't resolve) reads as `false`/absent — a guard\n * never throws on a shape mismatch, it just doesn't fire. */\nfunction readFlag(slots: Readonly<Record<string, string>>, target: string): boolean {\n const [slotName, ...path] = target.split(\".\");\n if (slotName === undefined) return false;\n const raw = slots[slotName];\n if (raw === undefined) return false;\n let cur: unknown = tryParseJson(raw);\n for (const key of path) {\n if (typeof cur !== \"object\" || cur === null) return false;\n cur = (cur as Record<string, unknown>)[key];\n }\n return cur === true;\n}\n\n/**\n * Evaluate a guard's truth value directly (R2 — guarded-skip). Does not special-case the R1 repair\n * shape; callers that need to distinguish repair-fold from a plain `on_failure` skip should use\n * {@link classifyConditionalStep} instead.\n */\nexport function evaluateGuard(when: WhenGuard, state: GuardState): boolean {\n switch (when.guard) {\n case \"on_failure\":\n return state.outcomes[when.target] === \"failure\";\n case \"on_flag\":\n return readFlag(state.slots, when.target);\n case \"on_missing\":\n return state.slots[when.target] === undefined;\n default:\n // The compiler validates guard names against the closed vocabulary before this IR ever\n // reaches a back-end (core/src/compile.rs); an unrecognized value here means a hand-edited or\n // future-versioned IR slipped through — loud-fail rather than silently treating it as false.\n throw new DispatchError(\n `unknown guard '${when.guard}' (closed vocabulary: on_failure, on_flag, on_missing)`,\n );\n }\n}\n\n/**\n * Structural test for the R1 repair shape: an `on_failure` guard whose target is `precedingStep`,\n * where that step's sole produced artifact is also consumed by the conditional step. Returns the\n * target's identity when the shape matches, else `null` (falls back to R2 guarded-skip).\n */\nexport function repairFoldTarget(\n when: WhenGuard,\n consumes: readonly string[],\n precedingStep: StepIdentity | null,\n): StepIdentity | null {\n if (when.guard !== \"on_failure\" || precedingStep === null) return null;\n if (when.target !== precedingStep.name) return null;\n if (precedingStep.produces === null || !consumes.includes(precedingStep.produces)) return null;\n return precedingStep;\n}\n\n/**\n * The single entry point run.ts uses to decide what a conditional step does next: fold into a\n * bounded repair turn (R1), run (R2 guard true), or skip (R2 guard false / R1 target didn't fail).\n */\nexport function classifyConditionalStep(\n when: WhenGuard,\n consumes: readonly string[],\n precedingStep: StepIdentity | null,\n state: GuardState,\n): ConditionalDecision {\n const target = repairFoldTarget(when, consumes, precedingStep);\n if (target !== null) {\n return state.outcomes[target.name] === \"failure\" ? { kind: \"repair\", target } : { kind: \"skip\" };\n }\n return evaluateGuard(when, state) ? { kind: \"run\" } : { kind: \"skip\" };\n}\n\nexport interface RepairAttemptResult {\n failed: boolean;\n}\n\n/**\n * Drive a bounded repair loop: call `attempt` up to `maxAttempts` times, stopping at the first\n * non-failing attempt. Never loops unboundedly and never swallows a fully-exhausted failure —\n * exhaustion is reported back (`recovered: false`) so the caller can loud-fail (`run.ts` throws a\n * `DispatchError`); this function itself does not throw on exhaustion, only on a rejected attempt.\n */\nexport async function runRepairLoop(\n maxAttempts: number,\n attempt: (attemptNumber: number) => Promise<RepairAttemptResult>,\n): Promise<{ recovered: boolean; attempts: number }> {\n for (let i = 1; i <= maxAttempts; i++) {\n const result = await attempt(i);\n if (!result.failed) return { recovered: true, attempts: i };\n }\n return { recovered: false, attempts: maxAttempts };\n}\n","/**\n * Warble's own, consumer-agnostic chat-event vocabulary — the NDJSON records `chat --stream-json`\n * (cli.ts) emits to stdout, one JSON object per line, as a turn runs. This module owns the mapping\n * FROM the Agent SDK's `SDKMessage` stream TO this vocabulary; it knows nothing about any particular\n * consumer's own event types — a consumer maps `WarbleChatEvent` to whatever shape it needs on its own\n * side (out of scope here).\n *\n * Step bracketing: rather than trying to derive nested Task-subagent step boundaries from\n * `parent_tool_use_id` transitions (fragile — a subagent's tool calls interleave with the driver's,\n * and the SDK gives no explicit \"subagent started/finished\" message), `ChatEventMapper` emits a\n * SINGLE enclosing `step_start` (id = the dispatched verb) on the first message that produces a tool\n * call, and a matching `step_finish` when the caller reports the turn is done (`finish()`). Every\n * `tool_call`/`tool_result` the turn produces is grouped under that one step. Simple and correct beats\n * clever-but-fragile here — a consumer that wants finer-grained nesting can still use each event's\n * `parent`/`depth` fields (populated from `parent_tool_use_id`) to distinguish driver-turn tool calls\n * from subagent-turn tool calls within the single step.\n *\n * The mapper does NOT emit `answer` — that line is assembled by the CLI from the turn's final text\n * once the whole message stream has been consumed (see cli.ts's `runChatCmd`).\n */\n\nexport type WarbleChatEvent =\n | {\n readonly t: \"step_start\";\n readonly id: string;\n readonly name: string;\n readonly parent: string | null;\n readonly depth: number;\n }\n | {\n readonly t: \"step_finish\";\n readonly id: string;\n readonly ok: boolean;\n readonly detail?: string;\n }\n | {\n readonly t: \"tool_call\";\n readonly id: string;\n readonly name: string;\n readonly input?: unknown;\n readonly parent: string | null;\n readonly depth: number;\n }\n | {\n readonly t: \"tool_result\";\n readonly id: string;\n readonly ok: boolean;\n readonly summary?: string;\n readonly error?: string;\n }\n | {\n readonly t: \"answer\";\n readonly text: string;\n }\n | {\n /**\n * The turn's SDK session id (multi-turn resume anchor, `run.ts`'s `RunResult.sessionId`),\n * emitted once per turn by `chat --stream-json` (cli.ts) — on success AND on a failed turn\n * (e.g. `error_max_turns`), since a caller resuming after a failure needs the session id of\n * the conversation that failed, not just of a successfully completed one. `id` is null only\n * if the SDK's result message never carried a session id at all.\n */\n readonly t: \"session\";\n readonly id: string | null;\n };\n\n// --- SDK message/content-block shapes (local, minimal) -------------------------------------------\n//\n// `@anthropic-ai/claude-agent-sdk`'s own `.d.ts` types its assistant/user message `content` against\n// `@anthropic-ai/sdk`'s real content-block unions, but that package is not a resolvable dependency in\n// this workspace (its `package.json` declares no dependencies of its own) — under this project's\n// `skipLibCheck: true`, that gap silently collapses `content`'s element type to `any` rather than\n// surfacing as a build error, so the compiler cannot be relied on to narrow these shapes for us. The\n// interfaces below are this module's own minimal, runtime-checked contract for exactly the fields it\n// reads (per Anthropic's documented content-block shapes), validated with type guards rather than\n// compiler narrowing.\n\ninterface SdkMessageLike {\n readonly type: string;\n readonly parent_tool_use_id?: string | null;\n readonly message?: { readonly content?: unknown };\n}\n\ninterface ToolUseBlock {\n readonly type: \"tool_use\";\n readonly id: string;\n readonly name: string;\n readonly input?: unknown;\n}\n\ninterface ToolResultBlock {\n readonly type: \"tool_result\";\n readonly tool_use_id: string;\n readonly content?: unknown;\n readonly is_error?: boolean;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isToolUseBlock(block: unknown): block is ToolUseBlock {\n return (\n isRecord(block) &&\n block[\"type\"] === \"tool_use\" &&\n typeof block[\"id\"] === \"string\" &&\n typeof block[\"name\"] === \"string\"\n );\n}\n\nfunction isToolResultBlock(block: unknown): block is ToolResultBlock {\n return isRecord(block) && block[\"type\"] === \"tool_result\" && typeof block[\"tool_use_id\"] === \"string\";\n}\n\nconst SUMMARY_MAX_LENGTH = 240;\n\nfunction truncate(text: string, max: number = SUMMARY_MAX_LENGTH): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n/** Render a tool_result block's `content` — a string, an array of `{type:\"text\",text}`-shaped blocks\n * (the common case), or anything else — down to a short display string. */\nfunction summarizeResultContent(content: unknown): string {\n if (typeof content === \"string\") return truncate(content);\n if (Array.isArray(content)) {\n const text = content\n .map((b) => (isRecord(b) && typeof b[\"text\"] === \"string\" ? (b[\"text\"] as string) : \"\"))\n .filter((s) => s.length > 0)\n .join(\" \");\n if (text.length > 0) return truncate(text);\n }\n return truncate(JSON.stringify(content ?? null));\n}\n\n/**\n * Stateful mapper: feed one `SDKMessage` at a time — the same objects `run.ts`'s `query()` loop\n * iterates, in arrival order — and get back zero or more `WarbleChatEvent`s, in order. Tracks\n * in-flight `tool_use` ids (so a later `tool_result` can be paired with the tool name it belongs to,\n * and so a `tool_result` for an id this mapper never saw start is dropped rather than fabricated).\n */\nexport class ChatEventMapper {\n private readonly stepId: string;\n private stepStarted = false;\n private readonly pendingToolNames = new Map<string, string>();\n\n /** `name` becomes the enclosing step's `name` (the dispatched verb, e.g. \"answer_query\"). */\n constructor(name: string) {\n this.stepId = name;\n }\n\n /** Feed one SDK message; returns the events it produces, in arrival order. */\n next(message: SdkMessageLike): WarbleChatEvent[] {\n if (message.type === \"assistant\") return this.onAssistant(message);\n if (message.type === \"user\") return this.onUser(message);\n return [];\n }\n\n /** Call once the turn is done (successfully or not) to close the enclosing step, if one was opened. */\n finish(ok: boolean, detail?: string): WarbleChatEvent[] {\n if (!this.stepStarted) return [];\n return [{ t: \"step_finish\", id: this.stepId, ok, ...(detail !== undefined ? { detail } : {}) }];\n }\n\n private startStepIfNeeded(): WarbleChatEvent[] {\n if (this.stepStarted) return [];\n this.stepStarted = true;\n return [{ t: \"step_start\", id: this.stepId, name: this.stepId, parent: null, depth: 0 }];\n }\n\n private onAssistant(message: SdkMessageLike): WarbleChatEvent[] {\n const content = message.message?.content;\n if (!Array.isArray(content)) return [];\n const parent = message.parent_tool_use_id ?? null;\n const depth = parent ? 1 : 0;\n\n const events: WarbleChatEvent[] = [];\n for (const block of content) {\n if (!isToolUseBlock(block)) continue;\n events.push(...this.startStepIfNeeded());\n this.pendingToolNames.set(block.id, block.name);\n events.push({\n t: \"tool_call\",\n id: block.id,\n name: block.name,\n ...(block.input !== undefined ? { input: block.input } : {}),\n parent,\n depth,\n });\n }\n return events;\n }\n\n private onUser(message: SdkMessageLike): WarbleChatEvent[] {\n const content = message.message?.content;\n if (!Array.isArray(content)) return [];\n\n const events: WarbleChatEvent[] = [];\n for (const block of content) {\n if (!isToolResultBlock(block)) continue;\n const name = this.pendingToolNames.get(block.tool_use_id);\n if (name === undefined) continue; // no matching tool_use ever seen — drop rather than fabricate\n this.pendingToolNames.delete(block.tool_use_id);\n const ok = block.is_error !== true;\n const text = summarizeResultContent(block.content);\n events.push({\n t: \"tool_result\",\n id: block.tool_use_id,\n ok,\n ...(ok ? { summary: text } : { error: text }),\n });\n }\n return events;\n }\n}\n","/**\n * High-level dispatch API — the embeddable surface (embed this back-end in your own TS app).\n *\n * Two entry points over the lower-level modules:\n * - `prepareDispatch` — PURE: parse IR → resolve capabilities → build one `query({options})` per\n * component. No SDK call. Powers `--dry-run`, codegen (`emit`), and offline inspection.\n * - `dispatch` — runs each prepared plan against the live Agent SDK loop (+ render + trace).\n *\n * A caller who wants full control of the loop can stop at `prepareDispatch` and hand `plan.options`\n * to the SDK's `query()` themselves (attaching their own tools/MCP/permission strategy) — the plan's\n * options are the language-neutral hand-off.\n */\nimport { dirname, isAbsolute, resolve } from \"node:path\";\n\nimport { DispatchError } from \"./error.js\";\nimport { assertSupportedIrVersion, parseIr, type ComponentNode, type WarbleIr } from \"./ir.js\";\nimport { ModelConfig } from \"./models.js\";\nimport {\n buildDispatchPlan,\n DEFAULT_RENDER_FLAVOR,\n type BuildConfig,\n type DispatchPlan,\n type RenderFlavor,\n} from \"./options.js\";\nimport { inspectNodeCapabilities, resolveNodeCapabilities, type ResolutionReport } from \"./resolve.js\";\nimport { runDispatch, type RunResult } from \"./run.js\";\nimport { DEFAULT_TARGET } from \"./targets.js\";\n\nexport interface DispatchInput {\n /** A parsed IR or a raw JSON string. */\n ir: WarbleIr | string;\n /** The data question to answer (the `query()` prompt). Optional for prepare-only (dry-run/emit). */\n question?: string;\n target?: string;\n flavor?: RenderFlavor;\n models?: ModelConfig;\n maxTurns?: number;\n /** Explicit bound-project cwd (absolute or cwd-relative). Overrides `irPath`-based resolution. */\n project?: string;\n /** Resolve each node's relative `context_binding.project` against this IR file's directory. */\n irPath?: string;\n /**\n * Scope preparation to exactly this component id: only its capabilities are resolved and only\n * its plan is built — every *other* component in the IR is left untouched, so its\n * `required_capabilities` never enter this dispatch's preflight. Use this for `chat`, which\n * only ever runs one component per process.\n *\n * Omit (the default) to prepare every component in the IR — the shape `manifest`, `emit`, and\n * the whole-profile `dispatch` subcommand need, since each of those actually reads or runs\n * every component and must know every component's resolution, not just one's.\n *\n * This narrows *which* component's requirements gate a given `prepareDispatch` call — it does\n * not change what happens when a gated capability is unmet (still a loud throw, same message,\n * same named capability; see `resolveNodeCapabilities`). A component that can itself invoke\n * another IR component at runtime would need that callee's requirements folded in here too, but\n * no such reachability exists yet: `borrowed_actions` names external runtime actions (notify,\n * ticket, …), never another component, and the one mechanism shaped for it — `orchestrating` /\n * `effect.outcome.kind: \"dispatch\"` with `routable_scope` — is parsed but not consumed by any\n * back-end (`docs/spec/authoring.md` marks `orchestrating` \"scaffolded\", not realized). If that\n * ever lands, this scoping must fold in the callee's requirements too.\n */\n componentId?: string;\n}\n\nexport interface PreparedComponent {\n id: string;\n node: ComponentNode;\n report: ResolutionReport;\n plan: DispatchPlan;\n}\n\nexport interface PreparedDispatch {\n target: string;\n components: PreparedComponent[];\n}\n\n/** Stable redacted status for a component the configured target cannot run. */\nexport const UNAVAILABLE_COMPONENT_REASON = \"component is unavailable on the configured runtime\";\n\nexport interface UnavailableDisplayComponent {\n id: string;\n node: ComponentNode;\n availability: { status: \"unavailable\"; reason: typeof UNAVAILABLE_COMPONENT_REASON };\n}\n\nexport type DisplayComponent = PreparedComponent | UnavailableDisplayComponent;\n\nexport interface PreparedDisplayManifest {\n target: string;\n components: DisplayComponent[];\n}\n\nfunction buildPreparedComponent(\n node: ComponentNode,\n report: ResolutionReport,\n input: DispatchInput,\n target: string,\n models: ModelConfig,\n): PreparedComponent {\n const cfg: BuildConfig = {\n target,\n flavor: input.flavor ?? DEFAULT_RENDER_FLAVOR,\n models,\n question: input.question ?? \"\",\n cwd: resolveProjectCwd(node, { ...(input.project !== undefined ? { project: input.project } : {}), ...(input.irPath !== undefined ? { irPath: input.irPath } : {}) }),\n ...(input.maxTurns !== undefined ? { maxTurns: input.maxTurns } : {}),\n };\n return { id: node.id, node, report, plan: buildDispatchPlan(node, report, cfg) };\n}\n\n/**\n * Resolve a node's bound wren project to an absolute cwd. Relative `context_binding.project` paths\n * resolve against the IR file's directory (`irPath`) when given, else the current working directory;\n * an explicit `project` always wins.\n */\nexport function resolveProjectCwd(\n node: ComponentNode,\n opts: { project?: string; irPath?: string },\n): string {\n if (opts.project) return resolve(opts.project);\n const p = node.context_binding.project;\n if (isAbsolute(p)) return p;\n const baseDir = opts.irPath ? dirname(resolve(opts.irPath)) : process.cwd();\n return resolve(baseDir, p);\n}\n\n/**\n * Parse + resolve + build every requested component's `query({options})`, without calling the SDK.\n *\n * By default this prepares every component in the IR. Pass `input.componentId` to scope\n * preparation — and therefore capability resolution — to exactly that one component; every other\n * component's `required_capabilities` are never consulted, so a component that isn't being\n * dispatched can't wall-hit a dispatch it has nothing to do with. See {@link DispatchInput.componentId}.\n */\nexport function prepareDispatch(input: DispatchInput): PreparedDispatch {\n const ir: WarbleIr = typeof input.ir === \"string\" ? parseIr(input.ir) : input.ir;\n // `parseIr` already gates the string-input branch; an object handed in directly (e.g. a caller's\n // own `JSON.parse` widened to `WarbleIr`) never runs through it, so gate here too — every caller\n // of `prepareDispatch`/`dispatch`, not just callers who pass a raw string, is covered.\n assertSupportedIrVersion(ir.warble_ir_version);\n const target = input.target ?? DEFAULT_TARGET;\n const models = input.models ?? ModelConfig.default();\n models.validate(ir); // every step tier must map to a model — abort before building anything.\n\n let scoped = ir.components;\n if (input.componentId !== undefined) {\n const node = ir.components.find((candidate) => candidate.id === input.componentId);\n if (!node) {\n throw new DispatchError(\n `component '${input.componentId}' not found in IR (available: ${ir.components.map((c) => c.id).join(\", \")})`,\n );\n }\n scoped = [node];\n }\n\n const components: PreparedComponent[] = scoped.map((node) => {\n const report = resolveNodeCapabilities(node, target);\n return buildPreparedComponent(node, report, input, target, models);\n });\n\n return { target, components };\n}\n\n/**\n * Prepare a display-only whole-profile manifest. Unsupported components are\n * represented by a closed unavailable marker; no executable plan is built\n * for them. This must never be used by emit, dispatch, or chat.\n */\nexport function prepareDisplayManifest(input: Omit<DispatchInput, \"componentId\" | \"question\">): PreparedDisplayManifest {\n const ir: WarbleIr = typeof input.ir === \"string\" ? parseIr(input.ir) : input.ir;\n assertSupportedIrVersion(ir.warble_ir_version);\n const target = input.target ?? DEFAULT_TARGET;\n const models = input.models ?? ModelConfig.default();\n models.validate(ir);\n\n const components: DisplayComponent[] = ir.components.map((node) => {\n const report = inspectNodeCapabilities(node, target);\n if (report.some((entry) => entry.outcome === \"fail\")) {\n return { id: node.id, node, availability: { status: \"unavailable\", reason: UNAVAILABLE_COMPONENT_REASON } };\n }\n return buildPreparedComponent(node, report, input, target, models);\n });\n return { target, components };\n}\n\nexport interface DispatchRunConfig {\n outDir: string;\n warbleBin?: string;\n title?: string;\n}\n\nexport interface ComponentOutcome {\n id: string;\n report: ResolutionReport;\n plan: DispatchPlan;\n result: RunResult;\n}\n\nexport interface DispatchOutcome {\n target: string;\n components: ComponentOutcome[];\n}\n\n/**\n * Prepare then RUN each component against the live Agent SDK loop. Requires `input.question`.\n * Writes each run's artifacts under `runCfg.outDir` (see {@link runDispatch}).\n */\nexport async function dispatch(\n input: DispatchInput,\n runCfg: DispatchRunConfig,\n): Promise<DispatchOutcome> {\n const prepared = prepareDispatch(input);\n const warbleBin = runCfg.warbleBin ?? \"warble\";\n\n const components: ComponentOutcome[] = [];\n for (const c of prepared.components) {\n const result = await runDispatch(c.plan, {\n outDir: runCfg.outDir,\n warbleBin,\n ...(runCfg.title ? { title: runCfg.title } : {}),\n });\n components.push({ id: c.id, report: c.report, plan: c.plan, result });\n }\n return { target: prepared.target, components };\n}\n","/**\n * The `claude-agent-sdk:local` display manifest — a stable, structural snapshot of a resolved\n * profile (agents / steps / tiers / capabilities / guardrails) for THIS target, so a consumer can\n * source a \"what will run\" display from whichever back-end actually runs, instead of always\n * reading the vercel bundle target's output even when this back-end is the one dispatching.\n *\n * Field-for-field port of the vercel bundle target's assembly (`dispatcher/vercel/src/{bundle,\n * guardrails,schema,classify,emit}.rs`), driven off the same parsed IR + `ResolutionReport` this\n * back-end already produces via `prepareDispatch` — no shelling out to the Rust binary, and no\n * shared code between the two ports (each is a small, pure derivation from the same IR seam, kept\n * independently portable per language).\n */\nimport type { ComponentNode, Effect, Guardrail, RenderBlock } from \"./ir.js\";\nimport { parseIr } from \"./ir.js\";\nimport { collectRequiredCapabilities, type ResolutionReport } from \"./resolve.js\";\nimport type { DisplayComponent, PreparedComponent, PreparedDisplayManifest, PreparedDispatch, UnavailableDisplayComponent } from \"./dispatch.js\";\n\n/** This manifest format's own version — bumped when its shape changes, independent of the IR\n * version and of the vercel bundle format's own version. */\nexport const MANIFEST_VERSION = \"0.1\";\n\n/** The IR version window this manifest format was built against — a consumer checks a manifest's\n * own compat window, not the source IR's declared version. Mirrors the vercel bundle target's\n * `MIN/MAX_SUPPORTED_IR_VERSION` (`dispatcher/vercel/src/emit.rs`); kept in sync by hand since the\n * two are independent ports of the same policy, not shared code. */\nconst MIN_SUPPORTED_IR_VERSION = \"0.6\";\nconst MAX_SUPPORTED_IR_VERSION = \"0.6\";\n\nexport interface CompatibilityPolicy {\n min_ir_version: string;\n max_ir_version: string;\n}\n\nexport interface WhenGuardOut {\n guard: string;\n target: string;\n}\n\n/**\n * How a conditional step is realized — mirrors the vercel bundle's `StepRealization` (serde\n * `tag = \"kind\"`, `snake_case`). `fallback` is omitted (never emitted): the IR has no field\n * declaring one today, matching the Rust port's `skip_serializing_if` behavior.\n */\nexport type StepRealization =\n | { kind: \"independent\" }\n | { kind: \"repair_fold\"; fold_into: string; max_attempts: number; fallback?: string }\n | { kind: \"guarded_skip\" };\n\nexport interface StepManifest {\n name: string;\n tier: string;\n consumes: string[];\n produces?: string;\n prompt: string;\n when?: WhenGuardOut;\n realization: StepRealization;\n}\n\nexport interface ToolRef {\n name: string;\n source: string;\n}\n\nexport interface GuardrailManifest {\n enforcement: string;\n locked: boolean;\n scope?: string;\n threshold?: unknown;\n}\n\nexport interface AvailableAgentManifest {\n id: string;\n verb: string;\n component_type: ComponentNode[\"type\"];\n realization_kind: ComponentNode[\"realization_kind\"];\n trigger: ComponentNode[\"trigger\"][\"kind\"];\n outcome: ComponentNode[\"effect\"][\"outcome\"][\"kind\"];\n steps: StepManifest[];\n guardrails: Record<string, GuardrailManifest>;\n tools: ToolRef[];\n output_schema: unknown;\n capabilities: ResolutionReport;\n brief?: string;\n}\n\n/** A display-only declaration of a component that remains unavailable to this target. */\nexport interface UnavailableAgentManifest {\n id: string;\n verb: string;\n component_type: ComponentNode[\"type\"];\n realization_kind: ComponentNode[\"realization_kind\"];\n trigger: ComponentNode[\"trigger\"][\"kind\"];\n outcome: ComponentNode[\"effect\"][\"outcome\"][\"kind\"];\n /** Fixed empty surfaces: this record can never be treated as an execution plan. */\n steps: [];\n guardrails: Record<string, never>;\n tools: [];\n output_schema: Record<string, never>;\n capabilities: [];\n availability: { status: \"unavailable\"; reason: string };\n}\n\nexport type AgentManifest = AvailableAgentManifest | UnavailableAgentManifest;\n\nexport interface Manifest {\n manifest_version: string;\n compat: CompatibilityPolicy;\n profile: string;\n target: string;\n agents: AgentManifest[];\n}\n\nconst DEFAULT_MAX_ATTEMPTS = 1;\n\n/**\n * Structural port of the vercel bundle's `classify_step` (`classify.rs`) — purely an adjacency\n * check over `when.guard`/`when.target`, no `consumes`/`produces` condition. Deliberately NOT the\n * same function as this back-end's own runtime classifier (`conditional.ts::repairFoldTarget`),\n * which has an extra consumes/produces condition and needs live execution state (`GuardState`) —\n * this one classifies statically off the IR alone, so its output matches vercel's field-for-field.\n */\nfunction classifyStep(node: ComponentNode, stepIndex: number): StepRealization {\n const when = node.llm_calls[stepIndex]!.when;\n if (!when) return { kind: \"independent\" };\n\n const adjacentPreceding =\n stepIndex > 0 &&\n when.guard === \"on_failure\" &&\n node.llm_calls[stepIndex - 1]!.name === when.target;\n\n if (adjacentPreceding) {\n return { kind: \"repair_fold\", fold_into: when.target, max_attempts: DEFAULT_MAX_ATTEMPTS };\n }\n return { kind: \"guarded_skip\" };\n}\n\nfunction buildStep(node: ComponentNode, stepIndex: number): StepManifest {\n const call = node.llm_calls[stepIndex]!;\n return {\n name: call.name,\n tier: call.tier,\n consumes: call.consumes,\n ...(call.produces !== null ? { produces: call.produces } : {}),\n prompt: call.prompt,\n ...(call.when ? { when: { guard: call.when.guard, target: call.when.target } } : {}),\n realization: classifyStep(node, stepIndex),\n };\n}\n\n/**\n * Port of the vercel bundle's `enforcement_for` (`guardrails.rs`) — a closed vocabulary keyed on\n * the guardrail's *name*, never on the owning component's id/verb.\n */\nfunction enforcementFor(name: string, hasThreshold: boolean): string {\n if (name === \"read_only_execution\") return \"read_only\";\n if (name === \"artifact_write\") return \"scoped_write\";\n if (\n name.includes(\"_limit\") ||\n name.endsWith(\"_gate\") ||\n name === \"deterministic_gate\" ||\n name === \"additivity_guard\"\n ) {\n return hasThreshold ? \"threshold_limit\" : \"gated_check\";\n }\n return \"generic\";\n}\n\nfunction guardrailManifest(g: Guardrail): GuardrailManifest {\n return {\n enforcement: enforcementFor(g.name, g.threshold !== undefined && g.threshold !== null),\n locked: g.locked,\n ...(g.scope !== null ? { scope: g.scope } : {}),\n ...(g.threshold !== undefined && g.threshold !== null ? { threshold: g.threshold } : {}),\n };\n}\n\n/** Port of the vercel bundle's `build_guardrails` — one entry per declared guardrail, keyed by\n * name, sorted (mirrors the Rust side's `BTreeMap` — deterministic output). */\nfunction buildGuardrails(node: ComponentNode): Record<string, GuardrailManifest> {\n const out: Record<string, GuardrailManifest> = {};\n for (const g of [...node.guardrails].sort((a, b) => a.name.localeCompare(b.name))) {\n out[g.name] = guardrailManifest(g);\n }\n return out;\n}\n\nconst PRIMITIVES = new Set([\"string\", \"number\", \"boolean\", \"row\"]);\n\nfunction primitiveSchema(name: string): Record<string, unknown> {\n switch (name) {\n case \"string\":\n return { type: \"string\" };\n case \"number\":\n return { type: \"number\" };\n case \"boolean\":\n return { type: \"boolean\" };\n case \"row\":\n return { type: \"object\" };\n default:\n return { type: \"string\", enum: [name] };\n }\n}\n\n/** Widen a schema's `type` to include `\"null\"` — port of `schema.rs::make_nullable`. */\nfunction makeNullable(schema: Record<string, unknown>): Record<string, unknown> {\n const type = schema[\"type\"];\n if (type === undefined) return schema;\n let widened: unknown;\n if (typeof type === \"string\") {\n widened = [type, \"null\"];\n } else if (Array.isArray(type)) {\n widened = type.includes(\"null\") ? type : [...type, \"null\"];\n } else {\n widened = type;\n }\n return { ...schema, type: widened };\n}\n\n/** Port of `schema.rs::field_type_to_schema` — the render-block field-type grammar (trailing `?`\n * nullable, trailing `[]` array, `|`-union) echoed into JSON Schema. */\nfunction fieldTypeToSchema(typeStr: string): Record<string, unknown> {\n const nullable = typeStr.endsWith(\"?\");\n const base = nullable ? typeStr.slice(0, -1) : typeStr;\n\n let schema: Record<string, unknown>;\n if (base.endsWith(\"[]\")) {\n schema = { type: \"array\", items: primitiveSchema(base.slice(0, -2)) };\n } else if (base.includes(\"|\")) {\n const alternatives = base.split(\"|\");\n schema = alternatives.every((alt) => PRIMITIVES.has(alt))\n ? { type: alternatives }\n : { type: \"string\", enum: alternatives };\n } else {\n schema = primitiveSchema(base);\n }\n\n return nullable ? makeNullable(schema) : schema;\n}\n\n/** Port of `schema.rs::render_block_schema`. */\nfunction renderBlockSchema(block: RenderBlock): Record<string, unknown> {\n const properties: Record<string, unknown> = { type: { const: block.type } };\n const required: string[] = [\"type\"];\n for (const [name, typeStr] of Object.entries(block.fields).sort(([a], [b]) => a.localeCompare(b))) {\n properties[name] = fieldTypeToSchema(typeStr);\n if (!typeStr.endsWith(\"?\")) required.push(name);\n }\n return { type: \"object\", properties, required };\n}\n\n/** Port of `schema.rs::output_schema_for` — the render-contract Envelope shape (`{blocks,\n * summary, verified}`) every agent's structured output conforms to. */\nfunction outputSchemaFor(effect: Effect): Record<string, unknown> {\n const blockSchemas = effect.render_blocks.map(renderBlockSchema);\n const blocksItems: Record<string, unknown> =\n blockSchemas.length === 0\n ? { type: \"object\" }\n : blockSchemas.length === 1\n ? blockSchemas[0]!\n : { anyOf: blockSchemas };\n\n return {\n type: \"object\",\n properties: {\n blocks: { type: \"array\", items: blocksItems },\n summary: { type: [\"string\", \"null\"] },\n verified: { type: [\"boolean\", \"null\"] },\n },\n required: [\"blocks\"],\n };\n}\n\n/**\n * This target's fixed local tool map — unlike the vercel bundle target (which composes a tool map\n * from pluggable per-target **provider** fragments, see `dispatcher/vercel/src/{tools,provider}.rs`),\n * this back-end has exactly one target and drives its own fixed mechanisms directly (the `wren` CLI\n * via Bash, the filesystem, git), so its tool bindings are a fixed table rather than composed. Names\n * mirror the vercel port's shape (a callable `{name, source}` per domain capability); `source` values\n * reuse this back-end's own mechanism labels (`targets.ts::localProfile()`'s `via` strings) rather\n * than vercel's provider-specific ones — the two back-ends are expected to differ in tool *values*,\n * only their *shape* (deduped `{name, source}[]`, non-callable capabilities excluded) needs to match.\n */\nconst LOCAL_TOOL_MAP: Record<string, ToolRef> = {\n \"sql_execution:read_only\": { name: \"wren_query\", source: \"bash-wren\" },\n genbi_build: { name: \"wren_build\", source: \"bash-wren\" },\n semantic_introspection: { name: \"wren_context_show\", source: \"bash-wren\" },\n raw_material_read: { name: \"read_raw_material\", source: \"sdk-read\" },\n schema_introspection: { name: \"wren_context_show\", source: \"bash-wren\" },\n source_connect: { name: \"wren_connect\", source: \"bash-setup\" },\n context_build: { name: \"wren_context_build\", source: \"bash-setup\" },\n artifact_write: { name: \"write_artifact\", source: \"fs\" },\n version_control: { name: \"commit\", source: \"git\" },\n scheduler: { name: \"schedule\", source: \"os-cron\" },\n event_bus: { name: \"publish_event\", source: \"pub-sub\" },\n notify_channel: { name: \"notify\", source: \"mcp-notify\" },\n};\n\n/** Port of `tools.rs::build_tools` — the de-duplicated list of tool refs `node` needs, derived from\n * its declared + implied required capabilities. Capabilities with no entry in `LOCAL_TOOL_MAP`\n * (LLM tiers, the structured-output contract, authz gates, human approval, blast-radius, …) are\n * intentionally not tools and are skipped, same exclusion set as the vercel port. */\nfunction buildTools(node: ComponentNode): ToolRef[] {\n const seen = new Set<string>();\n const out: ToolRef[] = [];\n for (const capability of collectRequiredCapabilities(node)) {\n const binding = LOCAL_TOOL_MAP[capability];\n if (!binding || seen.has(binding.name)) continue;\n seen.add(binding.name);\n out.push(binding);\n }\n return out;\n}\n\n/** Port of `emit.rs::build_agent_bundle`, minus the tool-map parameter (this back-end's is fixed,\n * see `LOCAL_TOOL_MAP`). */\nexport function buildAgentManifest(component: PreparedComponent): AvailableAgentManifest {\n const node = component.node;\n return {\n id: node.id,\n verb: node.verb,\n component_type: node.type,\n realization_kind: node.realization_kind,\n trigger: node.trigger.kind,\n outcome: node.effect.outcome.kind,\n steps: node.llm_calls.map((_call, i) => buildStep(node, i)),\n guardrails: buildGuardrails(node),\n tools: buildTools(node),\n output_schema: outputSchemaFor(node.effect),\n capabilities: component.report,\n ...(node.brief !== undefined ? { brief: node.brief } : {}),\n };\n}\n\n/** Never derives a plan, tool, or capability grant for an unavailable component. */\nexport function buildUnavailableAgentManifest(component: UnavailableDisplayComponent): UnavailableAgentManifest {\n const node = component.node;\n return {\n id: node.id,\n verb: node.verb,\n component_type: node.type,\n realization_kind: node.realization_kind,\n trigger: node.trigger.kind,\n outcome: node.effect.outcome.kind,\n steps: [],\n guardrails: {},\n tools: [],\n output_schema: {},\n capabilities: [],\n availability: component.availability,\n };\n}\n\n/** Build the full display manifest for a `prepareDispatch` result. `raw` is the same IR the\n * dispatch was prepared from — re-parsed here (a second, cheap, pure parse) just to read\n * `profile`, which `PreparedDispatch` does not itself carry. */\nexport function buildManifest(prepared: PreparedDispatch | PreparedDisplayManifest, raw: string): Manifest {\n const ir = parseIr(raw);\n return {\n manifest_version: MANIFEST_VERSION,\n compat: { min_ir_version: MIN_SUPPORTED_IR_VERSION, max_ir_version: MAX_SUPPORTED_IR_VERSION },\n profile: ir.profile,\n target: prepared.target,\n agents: prepared.components.map((component: DisplayComponent) =>\n \"availability\" in component ? buildUnavailableAgentManifest(component) : buildAgentManifest(component)),\n };\n}\n","import { query, type ModelInfo, type Query } from \"@anthropic-ai/claude-agent-sdk\";\nimport { resolve } from \"node:path\";\n\n/** The deliberately small host-facing contract for provider-owned model discovery. */\nexport const MODEL_CATALOG_VERSION = 1 as const;\n\nexport interface ModelCatalogModel {\n model: string;\n displayName: string;\n description?: string;\n isDefault?: boolean;\n reasoningEfforts?: Array<{ value: string; displayName: string; description?: string }>;\n}\n\nexport type ModelCatalogUnavailableCode =\n | \"not_authenticated\"\n | \"runtime_unavailable\"\n | \"timeout\"\n | \"protocol_error\";\n\nexport type ModelCatalogResult =\n | {\n version: typeof MODEL_CATALOG_VERSION;\n status: \"ready\";\n provider: \"claude\";\n models: ModelCatalogModel[];\n }\n | {\n version: typeof MODEL_CATALOG_VERSION;\n status: \"unavailable\";\n provider: \"claude\";\n code: ModelCatalogUnavailableCode;\n retryable: boolean;\n };\n\ntype QueryFactory = (params: {\n prompt: AsyncIterable<unknown>;\n options: {\n cwd: string;\n tools: string[];\n mcpServers: [];\n settingSources: [];\n abortController: AbortController;\n };\n}) => Query;\n\n// Cleanup must never turn a bounded catalog request back into an unbounded CLI operation. This is\n// intentionally short and only gives the SDK a chance to release its child process/iterator.\nconst CLEANUP_GRACE_MS = 25;\n\nexport interface DiscoverClaudeModelsOptions {\n cwd?: string;\n timeoutMs?: number;\n /** Test seam; production always uses the installed Agent SDK query factory. */\n queryFactory?: QueryFactory;\n}\n\nfunction unavailable(code: ModelCatalogUnavailableCode, retryable: boolean): ModelCatalogResult {\n return { version: MODEL_CATALOG_VERSION, status: \"unavailable\", provider: \"claude\", code, retryable };\n}\n\nfunction classify(error: unknown): ModelCatalogResult {\n const message = error instanceof Error ? error.message.toLowerCase() : \"\";\n if (message.includes(\"timed out\")) return unavailable(\"timeout\", true);\n if (/(not authenticated|unauthenticated|authentication|login required|sign in)/.test(message)) {\n return unavailable(\"not_authenticated\", false);\n }\n if (/(enoent|failed to start|not found|runtime unavailable)/.test(message)) {\n return unavailable(\"runtime_unavailable\", true);\n }\n // Do not reflect provider exceptions: they can contain raw response data or credentials.\n return unavailable(\"protocol_error\", false);\n}\n\nasync function* idleInput(): AsyncGenerator<never, void> {\n // `supportedModels()` needs a Query instance, but discovery must never create a user turn.\n // Keeping this async iterable empty is stronger than supplying a synthetic/empty user message.\n}\n\nfunction mapModel(model: ModelInfo): ModelCatalogModel {\n if (typeof model.value !== \"string\" || typeof model.displayName !== \"string\") {\n throw new Error(\"malformed model catalog response\");\n }\n return {\n model: model.value,\n displayName: model.displayName,\n ...(typeof model.description === \"string\" && model.description.length > 0\n ? { description: model.description }\n : {}),\n };\n}\n\nasync function withinTimeout<T>(\n operation: Promise<T>,\n timeoutMs: number,\n abortController: AbortController,\n): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n operation,\n new Promise<T>((_, reject) => {\n timer = setTimeout(() => {\n abortController.abort();\n reject(new Error(\"model catalog timed out\"));\n }, timeoutMs);\n }),\n ]);\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n\nasync function settleCleanup(operation: Promise<unknown>): Promise<void> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n operation.catch(() => undefined),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, CLEANUP_GRACE_MS);\n }),\n ]);\n } finally {\n if (timer !== undefined) clearTimeout(timer);\n }\n}\n\n/**\n * Ask the authenticated Agent SDK for its model picker data without yielding a user message.\n * The Query object still owns a subprocess/session, so every exit path interrupts, aborts, and\n * returns its iterator before exposing the narrow catalog result.\n */\nexport async function discoverClaudeModels(\n options: DiscoverClaudeModelsOptions = {},\n): Promise<ModelCatalogResult> {\n const abortController = new AbortController();\n const timeoutMs = options.timeoutMs ?? 10_000;\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) return unavailable(\"protocol_error\", false);\n\n let catalogQuery: Query | undefined;\n try {\n const queryFactory = options.queryFactory ?? (query as unknown as QueryFactory);\n catalogQuery = queryFactory({\n prompt: idleInput(),\n options: {\n cwd: resolve(options.cwd ?? process.cwd()),\n tools: [],\n mcpServers: [],\n settingSources: [],\n abortController,\n },\n });\n const models = await withinTimeout(catalogQuery.supportedModels(), timeoutMs, abortController);\n if (!Array.isArray(models)) throw new Error(\"malformed model catalog response\");\n return {\n version: MODEL_CATALOG_VERSION,\n status: \"ready\",\n provider: \"claude\",\n models: models.map(mapModel),\n };\n } catch (error) {\n return classify(error);\n } finally {\n // Cleanup is deliberately unconditional: supportedModels can fail before, during, or after\n // transport startup. Never leave an idle query/session behind.\n abortController.abort();\n if (catalogQuery !== undefined) {\n // Start both cleanup operations even if either SDK promise stalls. The bounded races retain\n // best-effort cleanup without allowing a hung interrupt/return to delay the JSON result.\n await Promise.all([\n settleCleanup(catalogQuery.interrupt()),\n settleCleanup(catalogQuery.return()),\n ]);\n }\n }\n}\n","/**\n * Multi-turn chat session over a SINGLE prepared profile component (Phase 1.3, G1 — single-profile\n * multi-turn only; multi-profile routing / `route_by_semantic_domain` is explicitly out of scope\n * here and is left to a later phase of this back-end's runtime-UX work).\n *\n * Two layers, split for offline testability:\n * - PURE state + heuristics (this file's top half): `SessionState`, `distillFollowup`,\n * `decideClarify`. No SDK import, no network — unit-testable with plain data.\n * - Thin LIVE driver (bottom half): `ChatSession` / `createChatSession`, which just resumes\n * `runDispatch` (run.ts) turn over turn via the SDK's `resume: session_id` mechanism. A session\n * can optionally be seeded with a session id captured by an earlier process, so a brand-new\n * `ChatSession` instance can resume a conversation it did not itself start (see\n * `initialResumeSessionId` below).\n *\n * Design invariant: stickiness/routing/intent-resolution is an LLM decision — it is NEVER encoded as\n * a data-flow DSL here. `distillFollowup` does not decide anything;\n * it only threads the PRIOR turn's already-resolved intent forward as guidance text prepended to the\n * next question, so a follow-up like \"break it down by region\" can reuse the prior filter without the\n * agent re-deriving it from scratch. The actual resolution (what the filters/dimensions ARE) remains\n * the agent's job each turn — this module only carries forward what was resolved last time.\n */\nimport { mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { WarbleChatEvent } from \"./events.js\";\nimport type { DispatchPlan } from \"./options.js\";\nimport { runDispatch, type RunConfig, type Trace } from \"./run.js\";\n\n// --- resolved intent (structured carry-forward) --------------------------------------------------\n\n/**\n * A minimal structured snapshot of what a turn resolved — filters/dimensions/measures/grain — used\n * only to thread context into the NEXT turn's prompt. Nothing here is inferred by this module: a\n * caller who has parsed it out of the agent's own answer (or a render envelope) supplies it via\n * `ChatSession.ask(question, { intent })`. Sessions with no supplied intent simply skip distillation.\n */\nexport interface ResolvedIntent {\n filters: string[];\n dimensions: string[];\n measures: string[];\n grain?: string;\n}\n\nconst BREAKDOWN_RE = /\\bby\\s+([a-z][a-z0-9_]*(?:\\s*(?:,|and)\\s*[a-z][a-z0-9_]*)*)/i;\nconst FILTER_OVERRIDE_RE = /\\b(where|only|instead of|excluding|filtered?\\s+to)\\b/i;\n\n/** Heuristic: does the follow-up name its own breakdown (\"break it down by X\", \"group by X, Y\")? */\nfunction extractBreakdownDimensions(question: string): string[] | null {\n const m = question.match(BREAKDOWN_RE);\n if (!m) return null;\n const dims = m[1]!\n .split(/\\s*(?:,|and)\\s*/i)\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n return dims.length > 0 ? dims : null;\n}\n\n/**\n * Merge the prior turn's resolved intent with a new follow-up question into a distilled context\n * string, PREPENDED to the question as guidance for the agent — this never decides routing or\n * overrides the agent's own resolution, it only reduces the odds it drops context a human speaker\n * would have kept implicit (\"break it down by region\" after \"completed orders\" should still mean\n * completed orders, broken down by region).\n *\n * Merge policy (heuristic, intentionally simple for G1):\n * - filters: carried forward unless the new question signals its own filter override (`where`,\n * `only`, `excluding`, `filtered to`, `instead of`).\n * - dimensions: swapped to whatever the new question names after \"by\"/\"group by\"; otherwise carried.\n * - measures / grain: always carried (no override heuristic yet — every question in G1 keeps the\n * same metric family; multi-metric follow-ups are out of scope).\n */\nexport function distillFollowup(prevIntent: ResolvedIntent, newQuestion: string): string {\n const newDimensions = extractBreakdownDimensions(newQuestion);\n const dimensions = newDimensions ?? prevIntent.dimensions;\n const filters = FILTER_OVERRIDE_RE.test(newQuestion) ? [] : prevIntent.filters;\n\n const carried: string[] = [];\n if (filters.length > 0) carried.push(`filter(s): ${filters.join(\", \")}`);\n if (dimensions.length > 0) {\n carried.push(\n newDimensions\n ? `breakdown swapped to: ${dimensions.join(\", \")} (was: ${prevIntent.dimensions.join(\", \") || \"none\"})`\n : `dimension(s): ${dimensions.join(\", \")}`,\n );\n }\n if (prevIntent.measures.length > 0) carried.push(`measure(s): ${prevIntent.measures.join(\", \")}`);\n if (prevIntent.grain) carried.push(`grain: ${prevIntent.grain}`);\n\n if (carried.length === 0) return newQuestion;\n\n return [\n \"[Context carried from the previous turn — reuse it unless this question overrides it; you \" +\n \"still decide the actual resolution.]\",\n carried.map((c) => `- ${c}`).join(\"\\n\"),\n \"\",\n newQuestion,\n ].join(\"\\n\");\n}\n\n// --- clarify policy --------------------------------------------------------------------------------\n\nexport type ClarifyOutcome = { kind: \"clarify\"; question: string } | { kind: \"answer\" };\n\n/** Below this confidence, clarify rather than guess (a clarifying question is cheaper than a\n * wasted expensive call). Confidence itself is supplied by the caller — parsed from whatever signal\n * the agent/router gave (an eval score, a router's own stated confidence, etc.); this function only\n * encodes the threshold policy, it doesn't compute confidence. */\nexport const DEFAULT_CLARIFY_THRESHOLD = 0.55;\n\nexport function decideClarify(\n question: string,\n confidence: number,\n threshold: number = DEFAULT_CLARIFY_THRESHOLD,\n): ClarifyOutcome {\n if (confidence < threshold) {\n return {\n kind: \"clarify\",\n question:\n `I want to make sure I answer \"${question}\" correctly — could you clarify which metric, ` +\n \"filter, or time range you mean?\",\n };\n }\n return { kind: \"answer\" };\n}\n\n// --- session state (pure) --------------------------------------------------------------------------\n\nexport interface Turn {\n question: string;\n /** The prompt actually sent to `query()` for this turn (post-distillation). */\n prompt: string;\n /** The turn's resolved intent, if the caller supplied one for carry-forward; null if not tracked. */\n intent: ResolvedIntent | null;\n /** The SDK's session id for this turn's run (resume anchor for the next turn), if any. */\n sessionId: string | null;\n finalText: string;\n}\n\nexport interface SessionState {\n turns: readonly Turn[];\n}\n\nexport function createSessionState(): SessionState {\n return { turns: [] };\n}\n\nfunction lastTurn(state: SessionState): Turn | undefined {\n return state.turns[state.turns.length - 1];\n}\n\n/** The resume anchor for the NEXT turn: the most recent turn's `session_id`, or null on turn 1. */\nexport function lastSessionId(state: SessionState): string | null {\n return lastTurn(state)?.sessionId ?? null;\n}\n\n/** The most recently resolved intent to carry forward, or null if none was ever supplied. */\nexport function lastResolvedIntent(state: SessionState): ResolvedIntent | null {\n return lastTurn(state)?.intent ?? null;\n}\n\n/** Pure append — returns a new state, does not mutate. */\nexport function appendTurn(state: SessionState, turn: Turn): SessionState {\n return { turns: [...state.turns, turn] };\n}\n\n/** Build the next turn's prompt: turn 1 = the raw question; turn N = distilled context + question. */\nexport function buildTurnPrompt(state: SessionState, question: string): string {\n const prevIntent = lastResolvedIntent(state);\n return prevIntent ? distillFollowup(prevIntent, question) : question;\n}\n\n// --- live driver (thin) -----------------------------------------------------------------------------\n\nexport interface TurnResult {\n finalText: string;\n sessionId: string | null;\n trace: Trace;\n /** The actual (post-distillation) prompt sent for this turn. */\n prompt: string;\n}\n\nexport interface AskOptions {\n /** Supply this turn's resolved intent so it can be carried forward into the NEXT turn's prompt. */\n intent?: ResolvedIntent;\n /** Opt-in streaming sink for this turn, forwarded straight to `runDispatch` (`chat --stream-json`). */\n onEvent?: (event: WarbleChatEvent) => void;\n}\n\n/**\n * A multi-turn chat session over ONE prepared component's `DispatchPlan`. Each `ask()` resumes the\n * prior turn's SDK session (`resume: session_id`) so the agent keeps the real conversation history;\n * `distillFollowup` layers a structured hint on top for callers tracking resolved intent explicitly.\n * All branching policy (distillation, clarify) lives in the pure functions above — this class is just\n * plumbing over `runDispatch`.\n */\nexport class ChatSession {\n private state: SessionState = createSessionState();\n\n constructor(\n private readonly plan: DispatchPlan,\n private readonly runCfg: RunConfig,\n /**\n * Seeds the FIRST `ask()` call's resume anchor with a session id captured by an earlier\n * process (e.g. `warble-agent-sdk chat --resume <id>`, cli.ts) — lets a NEW `ChatSession`\n * instance resume a conversation it did not itself start. Ignored once any real turn has been\n * asked in THIS instance: `lastSessionId(this.state)` then takes over, exactly as before.\n */\n private readonly initialResumeSessionId?: string,\n ) {}\n\n getState(): SessionState {\n return this.state;\n }\n\n async ask(question: string, opts: AskOptions = {}): Promise<TurnResult> {\n const prompt = buildTurnPrompt(this.state, question);\n const resume = lastSessionId(this.state) ?? this.initialResumeSessionId ?? null;\n const turnPlan: DispatchPlan = { ...this.plan, prompt };\n const turnOutDir = join(this.runCfg.outDir, `turn-${this.state.turns.length + 1}`);\n mkdirSync(turnOutDir, { recursive: true });\n\n const result = await runDispatch(turnPlan, {\n ...this.runCfg,\n outDir: turnOutDir,\n ...(resume ? { resume } : {}),\n ...(opts.onEvent ? { onEvent: opts.onEvent } : {}),\n });\n\n this.state = appendTurn(this.state, {\n question,\n prompt,\n intent: opts.intent ?? null,\n sessionId: result.sessionId,\n finalText: result.finalText,\n });\n\n return { finalText: result.finalText, sessionId: result.sessionId, trace: result.trace, prompt };\n }\n}\n\nexport function createChatSession(\n plan: DispatchPlan,\n runCfg: RunConfig,\n initialResumeSessionId?: string,\n): ChatSession {\n return new ChatSession(plan, runCfg, initialResumeSessionId);\n}\n"],"mappings":"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","names":["json","options","reason","gate","writeFileSync","join","join","writeFileSync","existsSync","mkdirSync","writeFileSync","join","query","isResult","isAssistant","requireFinalText","mkdirSync","join","existsSync","query","writeFileSync","text","entry","buildTools","query","resolve","mkdirSync","join","join","mkdirSync"]}
|