@demlik/tea 0.3.0 → 0.5.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.
Files changed (117) hide show
  1. package/dist/agent/index.d.ts +5 -5
  2. package/dist/agent/index.js +10 -10
  3. package/dist/authed-call/index.d.ts +2 -2
  4. package/dist/authed-call/index.js +7 -7
  5. package/dist/await-terminal/index.d.ts +2 -2
  6. package/dist/await-terminal/index.js +2 -2
  7. package/dist/batch-window/index.d.ts +3 -3
  8. package/dist/batch-window/index.js +3 -3
  9. package/dist/cache/index.d.ts +2 -2
  10. package/dist/cache/index.js +4 -4
  11. package/dist/{chunk-S4O26D7B.js → chunk-362SZ6CS.js} +3 -3
  12. package/dist/{chunk-S4O26D7B.js.map → chunk-362SZ6CS.js.map} +1 -1
  13. package/dist/{chunk-JFFVBEDI.js → chunk-62QBHM3T.js} +3 -3
  14. package/dist/{chunk-JFFVBEDI.js.map → chunk-62QBHM3T.js.map} +1 -1
  15. package/dist/{chunk-TPGASTFF.js → chunk-7A74NSG4.js} +3 -3
  16. package/dist/{chunk-TPGASTFF.js.map → chunk-7A74NSG4.js.map} +1 -1
  17. package/dist/{chunk-2KNLKQVN.js → chunk-7UU5P2CX.js} +3 -3
  18. package/dist/{chunk-2KNLKQVN.js.map → chunk-7UU5P2CX.js.map} +1 -1
  19. package/dist/{chunk-NPERUUUE.js → chunk-CIDS43FH.js} +3 -3
  20. package/dist/{chunk-NPERUUUE.js.map → chunk-CIDS43FH.js.map} +1 -1
  21. package/dist/{chunk-PBDYW2TU.js → chunk-DBOJ2UC6.js} +14 -3
  22. package/dist/chunk-DBOJ2UC6.js.map +1 -0
  23. package/dist/{chunk-WGGAMW7Y.js → chunk-KEFMI24G.js} +7 -7
  24. package/dist/{chunk-WGGAMW7Y.js.map → chunk-KEFMI24G.js.map} +1 -1
  25. package/dist/{chunk-MVY5DAMF.js → chunk-KWPB6BM6.js} +4 -4
  26. package/dist/{chunk-MVY5DAMF.js.map → chunk-KWPB6BM6.js.map} +1 -1
  27. package/dist/{chunk-C6QC273X.js → chunk-LFW66IIV.js} +4 -4
  28. package/dist/{chunk-C6QC273X.js.map → chunk-LFW66IIV.js.map} +1 -1
  29. package/dist/{chunk-BP2R7TPP.js → chunk-PBAYOJJO.js} +150 -38
  30. package/dist/chunk-PBAYOJJO.js.map +1 -0
  31. package/dist/{chunk-SK5JGUY7.js → chunk-PUTHY7LR.js} +3 -3
  32. package/dist/{chunk-SK5JGUY7.js.map → chunk-PUTHY7LR.js.map} +1 -1
  33. package/dist/{chunk-LYLDCIPH.js → chunk-QKUWDC4P.js} +32 -25
  34. package/dist/chunk-QKUWDC4P.js.map +1 -0
  35. package/dist/{chunk-VBUCHVCV.js → chunk-T6HDAPMR.js} +3 -3
  36. package/dist/{chunk-VBUCHVCV.js.map → chunk-T6HDAPMR.js.map} +1 -1
  37. package/dist/{chunk-IXBKFQH5.js → chunk-W2S4HK7J.js} +6 -6
  38. package/dist/{chunk-IXBKFQH5.js.map → chunk-W2S4HK7J.js.map} +1 -1
  39. package/dist/{chunk-CAXMQJJ3.js → chunk-ZILCH3WS.js} +4 -4
  40. package/dist/{chunk-CAXMQJJ3.js.map → chunk-ZILCH3WS.js.map} +1 -1
  41. package/dist/{chunk-RMX4EOQK.js → chunk-ZT3MGQB7.js} +3 -3
  42. package/dist/{chunk-RMX4EOQK.js.map → chunk-ZT3MGQB7.js.map} +1 -1
  43. package/dist/{core-42kapW0n.d.ts → core-DPYOyOJv.d.ts} +8 -5
  44. package/dist/deadline/index.d.ts +2 -2
  45. package/dist/deadline/index.js +3 -3
  46. package/dist/do/index.d.ts +6 -6
  47. package/dist/do/index.js +10 -10
  48. package/dist/{durable-effects-CFRngTNA.d.ts → durable-effects-B0YpoCHg.d.ts} +1 -1
  49. package/dist/extension/index.d.ts +2 -2
  50. package/dist/extension/index.js +3 -3
  51. package/dist/extension/react.js +3 -3
  52. package/dist/extension/subs/index.d.ts +2 -2
  53. package/dist/fan-out/index.d.ts +2 -2
  54. package/dist/idempotent-intake/index.d.ts +2 -2
  55. package/dist/index.d.ts +18 -4
  56. package/dist/index.js +2 -2
  57. package/dist/llm-call/index.d.ts +2 -2
  58. package/dist/llm-call/index.js +7 -7
  59. package/dist/{machine-B_BF4jij.d.ts → machine-Q_Bsm7Vu.d.ts} +1 -1
  60. package/dist/machine-viz/index.d.ts +1 -1
  61. package/dist/machine-viz/index.js +2 -2
  62. package/dist/mem/index.d.ts +2 -2
  63. package/dist/monitored-run/index.d.ts +3 -3
  64. package/dist/monitored-run/index.js +5 -5
  65. package/dist/node/index.d.ts +2 -2
  66. package/dist/paginated-walk/index.d.ts +2 -2
  67. package/dist/paginated-walk/index.js +7 -7
  68. package/dist/parity/index.d.ts +2 -2
  69. package/dist/parity/index.js +3 -3
  70. package/dist/pbt/arbitraries/index.d.ts +1 -1
  71. package/dist/pbt/index.d.ts +1 -1
  72. package/dist/pbt/index.js +3 -3
  73. package/dist/pbt/runners/index.d.ts +1 -1
  74. package/dist/pbt/runners/index.js +3 -3
  75. package/dist/poller/index.d.ts +2 -2
  76. package/dist/poller/index.js +3 -3
  77. package/dist/prediction/index.d.ts +1 -1
  78. package/dist/prediction/index.js +2 -2
  79. package/dist/pure/index.d.ts +1 -1
  80. package/dist/pure/index.js +2 -2
  81. package/dist/react/index.d.ts +9 -3
  82. package/dist/react/index.js +2 -2
  83. package/dist/react/index.js.map +1 -1
  84. package/dist/reconciler/index.d.ts +2 -2
  85. package/dist/reconciler/index.js +7 -7
  86. package/dist/recorder/index.d.ts +2 -2
  87. package/dist/resilient-call/index.d.ts +2 -2
  88. package/dist/resilient-call/index.js +6 -6
  89. package/dist/{runtime-types-gsog27b6.d.ts → runtime-types-uBuVvZqa.d.ts} +117 -3
  90. package/dist/saga/index.d.ts +2 -2
  91. package/dist/snapshot/index.d.ts +1 -1
  92. package/dist/snapshot/index.js +3 -3
  93. package/dist/subs/index.d.ts +16 -9
  94. package/dist/subs/index.js +3 -3
  95. package/dist/testing/index.d.ts +2 -2
  96. package/dist/testing/index.js +2 -2
  97. package/dist/throttled-input/index.d.ts +2 -2
  98. package/dist/throttled-input/index.js +6 -6
  99. package/dist/token-refresh/index.d.ts +1 -1
  100. package/dist/token-refresh/index.js +3 -3
  101. package/dist/trace-replay/index.d.ts +2 -2
  102. package/dist/trace-replay/index.js +3 -3
  103. package/dist/{types-KbL3W1mj.d.ts → types-C6mXL9wA.d.ts} +1 -1
  104. package/dist/with-deadline/index.d.ts +1 -1
  105. package/dist/with-deadline/index.js +2 -2
  106. package/dist/with-resilience/index.d.ts +2 -2
  107. package/dist/with-resilience/index.js +6 -6
  108. package/dist/with-telemetry/index.d.ts +1 -1
  109. package/dist/with-telemetry/index.js +2 -2
  110. package/dist/work-queue/adapter.d.ts +2 -2
  111. package/dist/work-queue/index.d.ts +2 -2
  112. package/dist/work-queue/ops.d.ts +2 -2
  113. package/dist/workflow/index.d.ts +3 -3
  114. package/package.json +1 -1
  115. package/dist/chunk-BP2R7TPP.js.map +0 -1
  116. package/dist/chunk-LYLDCIPH.js.map +0 -1
  117. package/dist/chunk-PBDYW2TU.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agent/schema.ts","../src/agent/compaction.ts","../src/agent/internal.ts","../src/agent/machine.ts","../src/agent/types.ts","../src/agent/index.ts"],"names":["runSlice","cmds"],"mappings":"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","file":"chunk-WGGAMW7Y.js","sourcesContent":["/**\n * @demlik/tea/agent — internal structured-output schema helper.\n *\n * NOT part of the public `./agent` barrel: `schemaFromGuard` is the shared\n * zod-style `parse` throw-wrapper the two owned structured-output schemas\n * (`agentTurnSchema`, `compactionSummarySchema`) are built from. It lives in its\n * own module so both `types.ts` and `compaction.ts` can import it without either\n * re-exporting it (the barrel `index.ts` never re-exports this file, so the\n * helper stays internal).\n */\n\nimport type { Schema } from \"../llm-call\";\n\n/**\n * Build a `Schema<T>` from a type guard — the zod-style `parse` throw-wrapper the\n * llm-call handler relies on, factored so tea's two owned structured-output\n * schemas ({@link agentTurnSchema}, {@link compactionSummarySchema}) share one\n * shape. On a\n * value the guard rejects it throws `structured-output parse failed: not <name>`\n * (a `*_err` at the boundary — errors are data); otherwise it narrows through.\n * `name` is the full noun phrase incl. article (\"an AgentTurn\").\n */\nexport function schemaFromGuard<T>(\n guard: (value: unknown) => value is T,\n name: string,\n): Schema<T> {\n return {\n parse: (value: unknown): T => {\n if (!guard(value)) {\n throw new Error(`structured-output parse failed: not ${name}`);\n }\n return value;\n },\n };\n}\n","/**\n * @demlik/tea/agent — the context-compaction seam (#85).\n *\n * The opt-in transcript snapshot-and-compact policy, shaped exactly like\n * `AgentSnapshotConfig` (see `./types`) so a short agent pays nothing and cannot\n * even mention the machinery. This module owns the whole `$compact` vocabulary:\n * the reserved purpose, the summary schema, the consumer policy, the config\n * discriminant, and the dedicated `compact_run` / `compact_ok` / `compact_err`\n * Cmd + Msgs re-keyed off the composed resilient call at the agent boundary.\n */\n\nimport type { Cmd, Interpret } from \"../index\";\nimport type {\n LlmCall,\n LlmErr,\n LlmOk,\n MessageLoader,\n Schema,\n} from \"../llm-call\";\nimport type { MsgType } from \"../protocol\";\nimport { schemaFromGuard } from \"./schema\";\nimport type { Conversation } from \"./types\";\n\n/**\n * The reserved purpose the compaction round-trip runs under (#85). Compaction\n * is a DEDICATED resilient LLM call (design B1), NOT one of the consumer's brain\n * purposes `P` — so it carries its own purpose literal, kept in the agent's\n * private `$`-namespace (the same reserved-namespace discipline `with-resilience`\n * uses) so it never collides with a consumer purpose. A consumer never names it.\n */\nexport type CompactionPurpose = \"$compact\";\n\n/** The reserved compaction purpose's value — the single in-flight summarize call's key. */\nexport const COMPACTION_PURPOSE: CompactionPurpose = \"$compact\";\n\n/**\n * The purpose→output map for the compaction LLM call — the single reserved\n * `$compact` purpose mapping to a {@link CompactionSummary}. Mirrors the brain\n * call's `O` map, scoped to the one compaction purpose, so the composed\n * `createLlmCall` parses the summarize output under the same structured-output\n * contract the brain call uses.\n */\nexport interface CompactionOutputs extends Record<CompactionPurpose, unknown> {\n readonly $compact: CompactionSummary;\n}\n\n/**\n * Narrow an unknown to a {@link CompactionSummary} — the runtime witness for the\n * compaction call's structured output. Checks the one load-bearing field\n * (`summary` is a string). PURE — allocates no Error.\n */\nexport function isCompactionSummary(\n value: unknown,\n): value is CompactionSummary {\n if (value === null || typeof value !== \"object\") return false;\n return typeof (value as { summary?: unknown }).summary === \"string\";\n}\n\n/**\n * The `Schema<CompactionSummary>` the compaction call binds — tea's own parse\n * target for the summarize round-trip (it OWNS the `$compact` purpose's output).\n * Throws on a non-summary (the zod-style `parse` contract the llm-call handler\n * relies on), so a malformed summary is a `compact_err` (errors are data), never\n * a corrupt fold-back.\n */\nexport const compactionSummarySchema: Schema<CompactionSummary> =\n schemaFromGuard(isCompactionSummary, \"a CompactionSummary\");\n\n/**\n * The result a compaction round-trip produces — the model's summary of the\n * folded-away turns. Tea OWNS this shape (the `$compact` purpose's output): the\n * fold-back (`compact_ok`) writes `summary` into a synthetic head `AgentTurn`\n * (design A1), so a consumer's `loadMessages` reads it as a normal turn with no\n * watermark to learn. Generic-free — the summary is always plain text.\n */\nexport interface CompactionSummary {\n /** The model's summary of the folded-away (oldest) turns + their tool records. */\n readonly summary: string;\n}\n\n/**\n * The consumer's compaction policy (#85). One PURE trigger; the impure\n * summarize round-trip is composed by the agent (a dedicated resilient LLM call\n * under the reserved `$compact` purpose, inheriting retry/backoff — design B1),\n * so the policy never reaches the model itself.\n *\n * - `planCompaction` — PURE: given the live conversation ABOUT to fire a brain\n * call, return how many of the OLDEST turns to fold into a summary, or `0`\n * to skip. No clock, no RNG → replay re-decides identically (design D). A\n * char-length / turn-count / real deterministic-tokenizer heuristic all\n * qualify. Returning `>= turns.length` is clamped to \"fold all but keep the\n * loop alive\" by the trigger (it never folds the turn currently in flight).\n * - `payloadOf` — build the per-call prompt payload the compaction\n * `MessageLoader` reads (the turns being folded). Omit → `null` (the loader,\n * if any, reads the conversation off the agent's own state). Opaque to the\n * agent, exactly like the brain call's `payloadOf`.\n */\nexport interface CompactionPolicy<R, Msg = unknown> {\n /** PURE trigger: how many OLDEST turns to fold (`0` = skip). No clock/RNG. */\n readonly planCompaction: (conversation: Conversation<R>) => number;\n /** Build the summarize call's prompt payload from the turns being folded. Omit → `null`. */\n readonly payloadOf?: (\n conversation: Conversation<R>,\n folding: number,\n ) => unknown;\n /** DI port — the SDK / message loader for the summarize call. Omit → invoke with `[]`. */\n readonly loadMessages?: MessageLoader<CompactionPurpose, Msg>;\n}\n\n/**\n * The compaction discriminant (#85), shaped exactly like {@link\n * AgentSnapshotConfig}. Compaction is either OFF —\n * `compaction` is structurally absent and the agent never emits a `compact_run`\n * Cmd — or ON, in which case `compaction` is a {@link CompactionPolicy}. A `{\n * compaction?: never }` member (rather than a bare optional) makes the OFF case\n * load-bearing: it forbids passing `compaction` at all, so `toMachine`\n * config-derives whether the `compact_run` interpret cell is REQUIRED (ON) or\n * FORBIDDEN (OFF) — never a silent no-op cell, the #55 type-lie-killer reused.\n */\nexport type AgentCompactionConfig<R, Msg> =\n | { readonly compaction?: never }\n | { readonly compaction: CompactionPolicy<R, Msg> };\n\n/**\n * The \"summarize the oldest N turns\" effect Cmd — the compaction round-trip's\n * carrier (#85). It mirrors the brain `resilient_run` Cmd's shape (a `key` + the\n * plain `LlmCall<CompactionPurpose>` input, no closures) but under the dedicated\n * `compact_run` discriminant so it routes to the compaction interpret cell, not\n * the brain one. The cell composes the resilient brick (retry/backoff) and\n * returns the re-keyed `compact_ok` / `compact_err` settle for re-entry.\n */\nexport type AgentCompactRunCmd = Cmd<typeof MsgType.CompactRun> & {\n readonly key: CompactionPurpose;\n readonly input: LlmCall<CompactionPurpose>;\n};\n\n/** The compaction round-trip success settle Msg — carries the parsed {@link CompactionSummary}. */\nexport type AgentCompactOkMsg = {\n readonly type: typeof MsgType.CompactOk;\n readonly key: CompactionPurpose;\n readonly result: LlmOk<CompactionPurpose, CompactionOutputs>;\n readonly at: number;\n};\n\n/** The compaction round-trip failure settle Msg — carries the typed {@link LlmErr}. */\nexport type AgentCompactErrMsg = {\n readonly type: typeof MsgType.CompactErr;\n readonly key: CompactionPurpose;\n readonly error: LlmErr<CompactionPurpose>;\n readonly at: number;\n};\n\n/**\n * The CONFIG-DERIVED compaction obligation on `toMachine`'s `toolInterpret`\n * (#85), the exact twin of {@link SnapshotInterpret}.\n * Resolves on the `Compact` discriminant the compaction overload of\n * `createAgent` fixes:\n *\n * - compaction ON → a REQUIRED `compact_run` cell\n * (`Interpret<M, AgentCompactRunCmd, Ctx>`). The summarize round-trip MUST be\n * wired — the agent never defaults it to a no-op.\n * - compaction OFF → `{ compact_run?: never }`. The cell is FORBIDDEN: with no\n * policy the agent never emits a `compact_run` Cmd, so wiring it would be\n * dead code. The consumer cannot even mention `compact_run`.\n *\n * Same type-lie-killer as the snapshot derivation: the obligation is present\n * EXACTLY when the Cmd can fire, never as a silent gap the agent backfills.\n */\nexport type CompactInterpret<\n M extends { type: string },\n Compact extends boolean,\n Ctx,\n> = Compact extends true\n ? Interpret<M, AgentCompactRunCmd, Ctx>\n : { readonly compact_run?: never };\n","/**\n * @demlik/tea/agent — the closure-free PURE reducer helpers.\n *\n * NOT part of the public `./agent` barrel: these are the reducer core's pure\n * conversation / state operations, factored OUT of the `createAgent` closure so\n * the factory module holds only the verbs that genuinely close over the composed\n * bricks (`run` / `llm` / `fan` / `compactRc` / `config`). Each function here is\n * pure and generic over the same `Stage / P / O / R` params the closure fixes,\n * so the call sites inside `createAgent` read identically (TS infers the params\n * from the state argument). The barrel `index.ts` never re-exports this file, so\n * everything stays internal.\n */\n\nimport type { LlmRunCmd } from \"../llm-call\";\nimport { MsgType } from \"../protocol\";\nimport type { AgentCompactRunCmd, CompactionPurpose } from \"./compaction\";\nimport { COMPACTION_PURPOSE } from \"./compaction\";\nimport type {\n AgentState,\n AgentTurn,\n Awaiting,\n Conversation,\n ToolCall,\n} from \"./types\";\n\n/** The narrowed `awaiting` variant for a given `kind`. */\nexport type AwaitingOf<K extends Awaiting[\"kind\"]> = Extract<\n Awaiting,\n { kind: K }\n>;\n\n/** A fresh conversation entering the agentic loop — awaiting the first brain call. */\nexport function freshConversation<R>(): Conversation<R> {\n return {\n turns: [],\n toolRecords: [],\n turnCount: 0,\n awaiting: { kind: \"llm\" },\n };\n}\n\n/**\n * Collapse a turn's tool calls to one per `callId` (first occurrence wins).\n * `callId` is the fan-out identity (`idOf`); duplicates in one batch are a\n * model defect that, un-deduped, would double-execute the tool and wedge the\n * batch (one settle Msg cannot close two same-id `running` entries). PURE —\n * preserves order, allocates no Error.\n */\nexport function dedupeByCallId(\n calls: readonly ToolCall[],\n): readonly ToolCall[] {\n const seen = new Set<string>();\n const out: ToolCall[] = [];\n for (const call of calls) {\n if (seen.has(call.callId)) continue;\n seen.add(call.callId);\n out.push(call);\n }\n return out;\n}\n\n/**\n * Fold the oldest `folding` turns of a conversation into a single synthetic\n * `summaryTurn` (#85, design A1) — PURE. The summary becomes the new head turn\n * (index 0); the surviving turns (`turns.slice(folding)`) follow. Every tool\n * record whose producing turn was folded (`turn < folding`) is DROPPED; each\n * survivor's `turn` is RE-INDEXED by `-folding + 1` so it still equals the new\n * index in `turns` of its producing turn (the summary occupies one slot where\n * `folding` turns stood, so survivors shift left by `folding` then right by 1).\n * `turnCount` is UNCHANGED — compaction is not a model round-trip (decision C).\n *\n * Caller guarantees `2 <= folding <= turns.length` (the trigger clamps + skips\n * `< 2`), so the result is strictly shorter (`length - folding + 1`).\n */\nexport function foldSummary<R>(\n conv: Conversation<R>,\n folding: number,\n summaryTurn: AgentTurn,\n): Conversation<R> {\n const shift = folding - 1; // survivors move left by this many slots.\n const survivingTurns = conv.turns.slice(folding);\n const survivingRecords = conv.toolRecords\n .filter((rec) => rec.turn >= folding)\n .map((rec) => ({ ...rec, turn: rec.turn - shift }));\n return {\n ...conv,\n turns: [summaryTurn, ...survivingTurns],\n toolRecords: survivingRecords,\n awaiting: { kind: \"llm\" },\n };\n}\n\n/** The current pipeline stage value (`undefined` for a single-shot run). */\nexport function currentStage<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): Stage | undefined {\n return s.run.stepStates.find((i) => i.status === \"running\")?.input;\n}\n\n/** True iff the run is in a terminal state (monitored-run done/failed, or agent failure). */\nexport function isSettled<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): boolean {\n return (\n s.run.phase === \"done\" || s.run.phase === \"failed\" || s.failure !== null\n );\n}\n\n/**\n * The stale-settle guard shared by the awaiting-scoped verbs (`turn` /\n * `settleTool` / `compactOk` / `compactErr`): return the live conversation\n * ALREADY narrowed to the given `awaiting.kind`, or `null` when the verb must\n * no-op — the run is settled, there is no conversation, or it is awaiting\n * something else (a stale settle after boot / advance). Collapses the\n * `isSettled → conv === null → awaiting.kind` triple that recurred verbatim\n * across the four verbs; each caller supplies its own no-op return. PURE.\n */\nexport function requireAwaiting<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n K extends Awaiting[\"kind\"],\n>(\n s: AgentState<Stage, P, O, R>,\n kind: K,\n): (Conversation<R> & { readonly awaiting: AwaitingOf<K> }) | null {\n if (isSettled(s)) return null;\n const conv = s.conversation;\n if (conv === null || conv.awaiting.kind !== kind) return null;\n return conv as Conversation<R> & { readonly awaiting: AwaitingOf<K> };\n}\n\n/** Re-key a composed compaction `resilient_run` Cmd to the dedicated `compact_run`. */\nexport function toCompactRunCmd(\n cmd: LlmRunCmd<CompactionPurpose>,\n): AgentCompactRunCmd {\n return {\n type: MsgType.CompactRun,\n key: COMPACTION_PURPOSE,\n input: cmd.input,\n };\n}\n","/**\n * @demlik/tea/agent — the wired-machine surface.\n *\n * The Cmd / Msg vocabulary the knob speaks, the knob interface `createAgent`\n * returns (`AgentKnob` / `AgentToMachine`), the do↔agent boot port, the\n * semantic lifecycle event stream + its projector (`agentEvents`), and the two\n * pure wiring helpers `mergeInterpret` / `liftAgent`. The reducer core (the\n * `createAgent` factory that implements this surface) lives in `./index`.\n */\n\nimport type { Cmd, Interpret, Machine } from \"../index\";\nimport type {\n LlmCall,\n LlmCallPorts,\n LlmFailMsg,\n LlmRunCmd,\n LlmSucceedMsg,\n LlmTimerMsg,\n} from \"../llm-call\";\nimport type { DeadlineSub, MonitoredRunCmd } from \"../monitored-run\";\nimport { MsgType } from \"../protocol\";\nimport type {\n AgentCompactErrMsg,\n AgentCompactOkMsg,\n AgentCompactRunCmd,\n CompactInterpret,\n} from \"./compaction\";\nimport type { AgentState, AgentTurn } from \"./types\";\n\n// ===========================================================================\n// Cmds + Msgs the knob speaks. Generic over the composed bricks' shapes.\n// ===========================================================================\n\n/** The brain-call effect Cmd, inherited from `../llm-call`. */\nexport type AgentLlmRunCmd<P extends string> = LlmRunCmd<P>;\n\n/**\n * The Cmd union the agent emits, as a CLOSED discriminated union (precise `TC`,\n * not the open `Cmd`) so `Interpret<M, AgentCmd<P, TC>, Ctx>` maps each key\n * precisely and `toMachine` merges the interpret halves with no laundering cast:\n *\n * - `AgentLlmRunCmd<P>` — the brain-call run Cmd (`resilient_run`), folded\n * by the wired `brainHandlers` cell.\n * - `MonitoredRunCmd<unknown>` — the durable checkpoint write the monitored-run\n * slice emits, present in the union ONLY when\n * checkpointing is on (`Snap = true`). With\n * checkpointing off the monitored-run slice never\n * emits a `snapshot_write` Cmd, so it is config-derived\n * OUT of the emitted set — the consumer is never asked\n * to interpret a Cmd that can never fire (#55).\n * - `TC` — the consumer's per-tool effect, mapped to the\n * consumer's own tool interpret cell.\n *\n * `Snap` defaults to `true` so the verb-internal usage (which forwards whatever\n * monitored-run emits) and the published type stay a safe superset; the wired\n * machine `toMachine` returns is parametrized on the overload-fixed `Snap` so its\n * Cmd set is exact (`MonitoredRunCmd` present only when checkpointing is on).\n */\nexport type AgentCmd<\n P extends string,\n TC extends Cmd = Cmd,\n Snap extends boolean = true,\n Compact extends boolean = true,\n> =\n | AgentLlmRunCmd<P>\n | (Snap extends true ? MonitoredRunCmd<unknown> : never)\n | (Compact extends true ? AgentCompactRunCmd : never)\n | TC;\n\n/**\n * The CONFIG-DERIVED snapshot obligation on `toMachine`'s `toolInterpret` (#55).\n * Resolves on the `Snap` discriminant the snapshotting overload of `createAgent`\n * fixes (`true` checkpointing-on / `false` off):\n *\n * - checkpointing ON → a REQUIRED `snapshot_write` cell\n * (`Interpret<M, MonitoredRunCmd<unknown>, Ctx>`). A real checkpoint write\n * MUST be wired — the agent never defaults it to a no-op.\n * - checkpointing OFF → `{ snapshot_write?: never }`. The cell is FORBIDDEN:\n * the Cmd is config-derived out of the emitted set, so wiring it would be\n * dead code. The consumer cannot even mention `snapshot_write`.\n *\n * This is the type that kills the `snapshot_write: async () => undefined`\n * ceremony: the obligation is present in the contract EXACTLY when the Cmd can\n * fire, never as a silent gap the agent backfills.\n */\nexport type SnapshotInterpret<\n M extends { type: string },\n Snap extends boolean,\n Ctx,\n> = Snap extends true\n ? Interpret<M, MonitoredRunCmd<unknown>, Ctx>\n : { readonly snapshot_write?: never };\n\n/**\n * The `toMachine` signature, parametrized on the `Snap` + `Compact` discriminants\n * so the snapshotting / compaction overloads of `createAgent` hand back the right\n * obligations. The `toolInterpret` requires (ON) or forbids (OFF) the\n * `snapshot_write` cell via {@link SnapshotInterpret} and the `compact_run` cell\n * via {@link CompactInterpret}, and the machine's Cmd type is the config-derived\n * `AgentCmd<P, TC, Snap, Compact>`.\n */\nexport type AgentToMachine<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Snap extends boolean,\n Compact extends boolean,\n> = <Ctx = object>(opts?: {\n readonly toolInterpret?: Interpret<AgentMachineMsg<P, O, R>, TC, Ctx> &\n SnapshotInterpret<AgentMachineMsg<P, O, R>, Snap, Ctx> &\n CompactInterpret<AgentMachineMsg<P, O, R>, Compact, Ctx>;\n}) => Machine<\n AgentState<Stage, P, O, R>,\n AgentMachineMsg<P, O, R>,\n AgentCmd<P, TC, Snap, Compact>,\n DeadlineSub,\n Ctx\n>;\n\n/**\n * The agent knob `createAgent` returns — the uniform verb contract every tea\n * composition exposes, plus the wired `toMachine` and the `unsafeDetachedHandlers`\n * escape hatch. `Snap` flows ONLY into `toMachine`'s `toolInterpret` obligation\n * (the snapshot derivation, #55); every verb is snapshot-agnostic. The model\n * message shape `Msg` does not appear on the knob surface (it is internal to the\n * brain call's loader), so it is not a type parameter here — only `createAgent`\n * carries it, to thread the config's `loadMessages` / `model` ports.\n */\nexport interface AgentKnob<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Snap extends boolean,\n Compact extends boolean,\n> {\n readonly init: () => AgentState<Stage, P, O, R>;\n readonly start: AgentVerb1<Stage, P, O, R, TC, [runId: string, at: number]>;\n readonly turn: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [result: AgentTurn, at: number]\n >;\n readonly toolOk: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [callId: string, result: R, at: number]\n >;\n readonly toolErr: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [callId: string, reason: string, at: number]\n >;\n readonly succeed: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentLlmOkMsg<P, O>, at: number]\n >;\n readonly fail: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentLlmErrMsg<P>, at: number]\n >;\n readonly compactOk: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentCompactOkMsg, at: number]\n >;\n readonly compactErr: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentCompactErrMsg, at: number]\n >;\n readonly onTimer: AgentVerb1<Stage, P, O, R, TC, [msg: AgentTimerMsg]>;\n readonly boot: AgentVerb1<Stage, P, O, R, TC, [at: number]>;\n readonly isSettled: (s: AgentState<Stage, P, O, R>) => boolean;\n readonly currentStage: (s: AgentState<Stage, P, O, R>) => Stage | undefined;\n readonly brainCall: (s: AgentState<Stage, P, O, R>) => LlmCall<P>;\n readonly subs: (s: AgentState<Stage, P, O, R>) => readonly DeadlineSub[];\n readonly toMachine: AgentToMachine<Stage, P, O, R, TC, Snap, Compact>;\n readonly unsafeDetachedHandlers: <M>(\n ports: AgentPorts<P, O, M>,\n ) => AgentDetachedHandlers<P, M>;\n}\n\n/** A verb taking the state + `Args`, returning the knob's `[State, Cmd[]]` tuple. */\ntype AgentVerb1<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Args extends readonly unknown[],\n> = (\n s: AgentState<Stage, P, O, R>,\n ...args: Args\n) => readonly [AgentState<Stage, P, O, R>, readonly AgentCmd<P, TC>[]];\n\n/** The brain-call success / failure settle Msgs, inherited from `../llm-call`. */\nexport type AgentLlmOkMsg<\n P extends string,\n O extends Record<P, unknown>,\n> = LlmSucceedMsg<P, O>;\nexport type AgentLlmErrMsg<P extends string> = LlmFailMsg<P>;\n\n/**\n * The timer Msg (retry + safety deadline) — `DeadlineExceeded`, the shared\n * shape of both bricks' timer Msgs (`LlmTimerMsg` and `MonitoredRunTimerMsg`\n * are both `DeadlineExceeded`). One Msg variant covers both timers; `onTimer`\n * disambiguates by Sub id. This is also the machine Msg the `subscribeDeadline`\n * cell dispatches directly (no wrapping), matching the sibling gold standard.\n */\nexport type AgentTimerMsg = LlmTimerMsg;\n\n/** Ports the consumer supplies to the llm-call handler — re-exported shape. */\nexport type AgentPorts<\n P extends string,\n O extends Record<P, unknown>,\n M,\n> = LlmCallPorts<P, O, M>;\n\n/**\n * The LEGACY detached brain-call handler dictionary `handlers(ports)` returns —\n * the inherited `../llm-call` detached form's exact shape, NOT an `Interpret`.\n * The `resilient_run` cell runs the invoke inside `ctx.waitUntil` and dispatches\n * the consumer's `onOk` / `onErr` Msg directly (returning `void`), so it is a\n * fire-and-forget handler with a structural `{ waitUntil, dispatch }` ctx — it\n * does not re-enter the resilient settle Msg and so does not drive the retry\n * loop. Naming the type precisely (rather than laundering it through\n * `as unknown as Interpret<...>`) keeps `agent.unsafeDetachedHandlers(ports)` honest: the\n * consumer that wires the verbs by hand gets the real detached shape, and its\n * `resilient_run` is callable with a plain Cmd + a `{ waitUntil, dispatch }` ctx\n * with no `as never` at the call site.\n */\nexport type AgentDetachedHandlers<P extends string, M> = {\n readonly resilient_run: (\n cmd: AgentLlmRunCmd<P>,\n ctx: {\n waitUntil(p: Promise<unknown>): void;\n dispatch(msg: M): unknown;\n },\n ) => void;\n};\n\n// ===========================================================================\n// AgentBootPort — the typed do↔agent boot seam (issue #60).\n// ===========================================================================\n//\n// A run that rehydrated mid-loop must re-fire its one outstanding effect on\n// activation. `do/host`'s `autoBoot` is the firing side; this agent reducer's\n// `boot` verb is the receiving side. The coupling used to be a RAW string:\n// host built `{ type: \"agent_boot\", at }` by hand and the agent string-matched\n// it — a literal duplicated across the seam with nothing tying the two ends.\n//\n// `AgentBootPort` promotes that coupling to a typed contract OWNED by the agent\n// (which owns the boot Msg shape): the `AgentBootMsg` type and the\n// `agentBootMsg` constructor. `do/host` imports the constructor instead of\n// hand-writing the literal. Adding a field to boot (or renaming it) is now a\n// one-file change here with the constructor's signature flagging every caller,\n// not a silent cross-module string drift.\n\n/** The Msg `do/host`'s `autoBoot` fires to re-enter the agent's `boot` verb on rehydrate. */\nexport type AgentBootMsg = {\n readonly type: typeof MsgType.AgentBoot;\n readonly at: number;\n};\n\n/**\n * The do↔agent boot port: construct the `agent_boot` Msg `autoBoot` dispatches\n * on a resumable rehydrate. The agent owns this constructor so the boot Msg\n * shape lives in ONE place — the host fires it through here, never as a raw\n * `{ type: \"agent_boot\" }` literal.\n */\nexport function agentBootMsg(at: number): AgentBootMsg {\n return { type: MsgType.AgentBoot, at };\n}\n\n// ===========================================================================\n// The machine Msg union — the closed set of verb entry points `toMachine` wires.\n// ===========================================================================\n\n/**\n * The agent machine's Msg union — one variant per reducer entry point. A\n * consumer using `toMachine` dispatches `agent_start` to begin and `agent_tool_ok`\n * / `agent_tool_err` to route settled tools back; the brain-call settle Msgs\n * (`resilient_ok` / `resilient_err`) RE-ENTER from the FIXED `brainHandlers`\n * (the substrate enqueues an interpret handler's returned Msg as a follow-up),\n * driving `succeed` / `fail`. Time enters via `at` on every variant — the\n * reducer never reads the clock.\n *\n * There is deliberately NO `agent_turn` variant here. The wired loop folds a\n * model turn INSIDE `succeed` from the re-entered `resilient_ok` — a single\n * settle Msg advances both the retry slice and the conversation (the L3 fix).\n * Exposing `agent_turn` as a dispatchable Msg re-opened the stuck-`running` bug:\n * a hand-fed turn folds the conversation without ever re-entering `resilient_ok`,\n * so `succeed` never runs and the resilient slice stays `running` (#54). The\n * `turn` verb remains on the knob for the consumer that wires the verbs by hand\n * (manual wiring), but it is not part of the one wired machine's Msg surface.\n */\nexport type AgentMachineMsg<P extends string, O extends Record<P, unknown>, R> =\n | {\n readonly type: typeof MsgType.AgentStart;\n readonly runId: string;\n readonly at: number;\n }\n | {\n readonly type: typeof MsgType.AgentToolOk;\n readonly callId: string;\n readonly result: R;\n readonly at: number;\n }\n | {\n readonly type: typeof MsgType.AgentToolErr;\n readonly callId: string;\n readonly reason: string;\n readonly at: number;\n }\n // The brain-call settle Msgs RE-ENTER straight from `brainHandlers` (no\n // wrapping) — `resilient_ok` runs `succeed` (reset retry + fold the turn),\n // `resilient_err` runs `fail` (back off via retry). This is the inherited\n // llm-call settle shape, dispatched verbatim by the substrate's re-entry.\n | AgentLlmOkMsg<P, O>\n | AgentLlmErrMsg<P>\n // The compaction settle Msgs RE-ENTER from the compaction interpret cell\n // (#85) — `compact_ok` folds the summary back (drops the oldest N turns +\n // their tool records, then fires the next brain call), `compact_err` backs off\n // via the compaction slice's retry or — on exhaustion — proceeds without\n // compacting (errors are data). Dedicated discriminants, re-keyed off the\n // composed resilient settle at the cell boundary.\n | AgentCompactOkMsg\n | AgentCompactErrMsg\n // The timer Msg is `DeadlineExceeded` itself (not wrapped) so the\n // `subscribeDeadline` cell dispatches it straight into `update`, exactly as\n // the resilient-call / llm-call / monitored-run gold standards wire it.\n | AgentTimerMsg\n | AgentBootMsg;\n\n// ===========================================================================\n// AgentEvent — the SEMANTIC lifecycle event stream (issue #47).\n// ===========================================================================\n\n/**\n * The agent's PUBLIC lifecycle events — the semantic stream a consumer\n * subscribes to via `runtime.on(type, …)` (#47). This is the seam that\n * DECOUPLES observability/SSE code from the agent's PRIVATE retry/loop Msg\n * vocabulary: where the old code switched on `resilient_ok` / `agent_tool_ok`\n * (the inherited resilient-call / tool-fan-out plumbing) off the raw `observe`\n * firehose, a consumer now folds these named events. The private Msg names live\n * ONLY inside `agentEvents` (the projector) — they appear nowhere in this union\n * or any exported type, so a UI built on `TurnSettled` does not break the day\n * the retry plumbing is renamed.\n *\n * - `TurnSettled` — a brain turn settled (the model produced an `AgentTurn`).\n * Projected off the private `resilient_ok` settle Msg; carries the parsed\n * `turn` (the narration + tool calls the model asked for).\n * - `ToolSettled` — a tool call settled OK. Projected off the private\n * `agent_tool_ok` Msg; carries the `callId` and the tool `result`.\n * - `RunDone` — the run finished. Projected off the post-transition State\n * reaching `run.phase === \"done\"`; carries the run's `output` (the terminal\n * model turn, or `null`) — the same first-class result `Runtime.result()`\n * reads (#46), surfaced as an event for the streaming consumer.\n */\nexport type AgentEvent<R> =\n | { readonly type: \"TurnSettled\"; readonly turn: AgentTurn }\n | {\n readonly type: \"ToolSettled\";\n readonly callId: string;\n readonly result: R;\n }\n | { readonly type: \"RunDone\"; readonly output: AgentTurn | null };\n\n/**\n * Project one APPLIED agent transition `(msg, state)` to its semantic\n * {@link AgentEvent}s (#47) — the `events` projector a consumer passes to\n * `run(machine, { events: agentEvents() })` to light up `runtime.on(...)`.\n *\n * This is the ONE place the agent's PRIVATE Msg names are read: it maps\n * `resilient_ok` → `TurnSettled` and `agent_tool_ok` → `ToolSettled`, and reads\n * the post-transition `run.phase` for `RunDone`. The mapping is total over the\n * Msg union (a `default`-free switch on the discriminant) and returns `[]` for\n * the transitions that carry no public event (start / boot / timer / the error\n * arms), so a private name never escapes into `AgentEvent`.\n *\n * A single transition may emit more than one event: the brain turn that retires\n * the final stage settles a turn (`TurnSettled`) AND finishes the run\n * (`RunDone`) — both are projected from that one `resilient_ok` transition.\n * `RunDone` is gated on `run.phase === \"done\"`, which the wired loop reaches\n * exactly once (the agent is terminal there and dispatches no further\n * transition), so the event fires once per run.\n *\n * PURE — reads only the passed `(msg, state)`; no clock, no RNG, no throw.\n *\n * @typeParam P Brain-call purposes.\n * @typeParam O Per-purpose outputs (bound to `AgentTurn`, the agentic shape).\n * @typeParam R Tool result type.\n * @typeParam Stage Pipeline stage type.\n */\nexport function agentEvents<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n>(): (\n msg: AgentMachineMsg<P, O, R>,\n state: AgentState<Stage, P, O, R>,\n) => readonly AgentEvent<R>[] {\n return (msg, state) => {\n const events: AgentEvent<R>[] = [];\n switch (msg.type) {\n case MsgType.ResilientOk:\n // The PRIVATE brain-call settle Msg → the public TurnSettled. Its\n // `result.output` is the parsed `AgentTurn` (the `O extends Record<P,\n // AgentTurn>` bound pins every purpose's output to an `AgentTurn`, the\n // same reasoning `state.output` relies on, #46/#48).\n events.push({ type: \"TurnSettled\", turn: msg.result.output });\n break;\n case MsgType.AgentToolOk:\n // The PRIVATE tool-fan-out settle Msg → the public ToolSettled.\n events.push({\n type: \"ToolSettled\",\n callId: msg.callId,\n result: msg.result,\n });\n break;\n // start / boot / timer / the *_err arms / the compaction settles carry no\n // public event — return []. (No `default`: the switch is exhaustive over\n // the Msg discriminant, so a new Msg variant forces a decision here at\n // compile time.) Compaction is an internal optimization, not a semantic\n // lifecycle moment a UI folds — its settles are deliberately silent here.\n case MsgType.AgentStart:\n case MsgType.AgentToolErr:\n case MsgType.ResilientErr:\n case MsgType.CompactOk:\n case MsgType.CompactErr:\n case \"deadline_exceeded\":\n case MsgType.AgentBoot:\n break;\n }\n // RunDone is a STATE-shaped event (the run's terminal output, #46), not a\n // Msg-shaped one: the transition that lands `done` is the final brain turn\n // (which also emits TurnSettled above). Gate on the post-transition phase so\n // the same projector reports both.\n if (state.run.phase === \"done\") {\n events.push({ type: \"RunDone\", output: state.output });\n }\n return events;\n };\n}\n\n/**\n * Join two `Interpret` dictionaries over DISJOINT Cmd subsets `A` and `B` (over\n * the same Msg union `M` and Ctx) into the full `Interpret<M, A | B, Ctx>`. The\n * agent uses it to merge the consumer's per-tool / snapshot interpret (`A`) with\n * the agent-owned brain-call handler (`B = AgentLlmRunCmd`) into the wired\n * machine's single interpret table.\n *\n * The runtime result is exactly the spread of the two key-disjoint records. The\n * single `as` is a SOUND mapped-type identity, not a laundering cast: `Interpret`\n * is a homomorphic mapped type keyed by `Cmd[\"type\"]`, so\n * `Interpret<M, A, Ctx> & Interpret<M, B, Ctx>` IS `Interpret<M, A | B, Ctx>`\n * (`(A | B)[\"type\"] = A[\"type\"] | B[\"type\"]`). TypeScript does not reduce that\n * intersection of two GENERIC mapped types on its own, so the equality is\n * asserted ONCE here — preserving `M` and `Ctx` exactly — rather than smuggled\n * through `as unknown as Interpret<...>` at every wiring site. Pure.\n */\nexport function mergeInterpret<\n M extends { type: string },\n A extends Cmd,\n B extends Cmd,\n Ctx,\n>(\n a: Interpret<M, A, Ctx> | undefined,\n b: Interpret<M, B, Ctx>,\n): Interpret<M, A | B, Ctx> {\n return { ...(a ?? {}), ...b } as Interpret<M, A | B, Ctx>;\n}\n\n/**\n * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the slice\n * lives at `state.agent`. Convenience for a host that nests the agent slice\n * under a named field; the single-slice host uses the verbs' tuple directly.\n * PURE — a thin record rebuild, no clock / RNG.\n */\nexport function liftAgent<\n S extends { agent: AgentState<Stage, P, O, R> },\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n C extends Cmd,\n>(\n state: S,\n [slice, cmds]: readonly [AgentState<Stage, P, O, R>, readonly C[]],\n): readonly [S, readonly C[]] {\n return [{ ...state, agent: slice }, cmds];\n}\n","/**\n * @demlik/tea/agent — the domain data model: the tool + turn shapes the consumer\n * supplies, the agentic-stage conversation, the `createAgent` config knob, and\n * the durable agent slice + its lifecycle status.\n *\n * Everything here is plain data (durable + replayable): the composed bricks'\n * slices, the conversation, and the config are all JSON-serializable. The\n * compaction (#85) vocabulary lives in `./compaction`; this module imports its\n * types where the slice / config reference them. The reducer core (the verbs +\n * the wired `toMachine`) lives in `./index`.\n */\n\nimport type { FanOutState } from \"../fan-out\";\nimport type { Cmd } from \"../index\";\nimport type {\n LlmCall,\n LlmOk,\n MessageLoader,\n ModelFactory,\n ResilientState,\n Schema,\n} from \"../llm-call\";\nimport type { MonitoredRunState, RunFailure } from \"../monitored-run\";\nimport type { RetryPolicy } from \"../retry-backoff\";\nimport type {\n AgentCompactionConfig,\n CompactionOutputs,\n CompactionPurpose,\n} from \"./compaction\";\nimport { schemaFromGuard } from \"./schema\";\n\n// ===========================================================================\n// Domain seams the consumer supplies — the tool + turn shapes.\n// ===========================================================================\n\n/**\n * One tool the model asked to call this turn — the seed's `ToolCall`, stripped\n * of the audit-specific args typing. Plain data so it round-trips through the\n * durable fan-out ledger: a stable `callId` (the fan-out identity), the tool\n * `name`, and the opaque `args` the consumer's own interpret reads.\n */\nexport interface ToolCall {\n /** Stable id the model minted; the fan-out item identity (`idOf`). */\n readonly callId: string;\n /** The tool to invoke. The consumer's `toolOf` maps it to an effect Cmd. */\n readonly name: string;\n /** Args the model emitted, opaque to the agent. */\n readonly args: Readonly<Record<string, unknown>>;\n}\n\n/**\n * One model turn — the seed's `AiTurn`, generalized: the narration `content`\n * the model produced and the `toolCalls` it asked us to run. An empty\n * `toolCalls` means the model is done with this stage (advance the pipeline).\n * This is the parsed output of a brain call; the consumer's schema produces it.\n */\nexport interface AgentTurn {\n /** Free-text narration the model produced this turn (folded into the conversation). */\n readonly content: string;\n /** The tools the model asked us to run; empty = stage done. */\n readonly toolCalls: readonly ToolCall[];\n}\n\n/**\n * Narrow an unknown to a `ToolCall` — the per-element witness `isAgentTurn`\n * folds over the `toolCalls` array. Checks the three load-bearing fields:\n * `callId`/`name` are strings, `args` is a non-null object. PURE — allocates no\n * Error. Without this the array-of-`ToolCall` narrow would be validation\n * masquerading as parse: `toolCalls: [1, 2, 3]` would pass, then the downstream\n * `dedupeByCallId` / `fan.scatter` read an `undefined` `callId` and wedge the\n * fan-out batch.\n */\nfunction isToolCall(value: unknown): value is ToolCall {\n if (value === null || typeof value !== \"object\") return false;\n const t = value as { callId?: unknown; name?: unknown; args?: unknown };\n return (\n typeof t.callId === \"string\" &&\n typeof t.name === \"string\" &&\n t.args !== null &&\n typeof t.args === \"object\"\n );\n}\n\n/**\n * Narrow an unknown to an `AgentTurn` — the runtime witness for tea's own\n * structured-output type. A consumer's brain schema parses the model's output\n * into an `AgentTurn` (the agentic purpose's output); rather than every consumer\n * hand-rolling this guard + a `Schema<AgentTurn>` for a type the agent OWNS, the\n * agent exports both. Checks the load-bearing fields: `content` is a string and\n * `toolCalls` is an array of `ToolCall` (each element guarded — the narrow is a\n * real parse of the boundary, not a shallow `Array.isArray`). PURE — allocates\n * no Error.\n */\nexport function isAgentTurn(value: unknown): value is AgentTurn {\n if (value === null || typeof value !== \"object\") return false;\n const t = value as { content?: unknown; toolCalls?: unknown };\n return (\n typeof t.content === \"string\" &&\n Array.isArray(t.toolCalls) &&\n t.toolCalls.every(isToolCall)\n );\n}\n\n/**\n * The `Schema<AgentTurn>` for tea's own turn type — the parse target a brain\n * call binds when the agentic purpose's output is a bare `AgentTurn` (the common\n * case). Throws on a non-`AgentTurn` (the zod-style `parse` contract the\n * llm-call handler relies on). Deletes the consumer's hand-rolled\n * `auditSchema` / `isAgentTurn` pair.\n *\n * A consumer whose turn type EXTENDS `AgentTurn` with extra fields still writes\n * its own schema (it must validate the extra fields); this is for the plain case.\n */\nexport const agentTurnSchema: Schema<AgentTurn> = schemaFromGuard(\n isAgentTurn,\n \"an AgentTurn\",\n);\n\n/**\n * One settled tool outcome the consumer routes back into the loop — the seed's\n * `ToolOutcome`. `ok` carries the result the consumer's interpret produced;\n * `error` carries a reason the model sees (so it recovers rather than stalls —\n * \"errors are data\").\n */\nexport type ToolOutcome<R> =\n | { readonly kind: \"ok\"; readonly result: R }\n | { readonly kind: \"error\"; readonly reason: string };\n\n/**\n * A folded tool record kept on the conversation once a tool settles — the\n * call + its outcome, in settle order. The consumer's message loader reads\n * these (plus `turns`) to assemble the next brain call's prompt.\n *\n * `turn` is the `turnCount` at the time the record was folded — the association\n * compaction needs to drop the RIGHT records (#85 / design A1). When compaction\n * folds `turns[0..N]` into a summary, it must also drop every tool record that\n * belonged to those turns; without a turn stamp on the record there is no honest\n * way to know which. It is the round-trip index, not a wall clock — small and\n * JSON-stable, preserving the durability invariant.\n */\nexport interface ToolRecord<R> {\n readonly call: ToolCall;\n readonly outcome: ToolOutcome<R>;\n /** The `turnCount` at fold time — which round-trip this record belongs to (#85, A1). */\n readonly turn: number;\n}\n\n// ===========================================================================\n// Conversation — the agentic-stage loop state (the seed's `Conversation`).\n// ===========================================================================\n\n/**\n * Whether the agentic stage is waiting on the model (`llm`), on tools\n * (`tools`), or on a compaction round-trip (`compacting`, #85). The in-flight\n * fan-out batch exists ONLY in the `tools` variant — \"awaiting llm with tools\n * pending\" is structurally impossible (the seed's canon §2.6 / Rule 1\n * impossible-states pin). Discriminated on `kind`.\n *\n * `compacting` is the honest state for the dedicated compaction round-trip\n * (design B1): the transcript grew, the policy asked to fold `folding` of the\n * OLDEST turns, and the summarize call is in flight INSTEAD of the next brain\n * call. `folding` is the count `planCompaction` returned — the fold-back\n * (`compact_ok`) drops exactly that many head turns + their tool records.\n */\nexport type Awaiting =\n | { readonly kind: \"llm\" }\n | { readonly kind: \"tools\"; readonly batchTurn: number }\n | { readonly kind: \"compacting\"; readonly folding: number };\n\n/**\n * The agentic-stage conversation — durable inside the agent slice so an\n * eviction mid-loop resumes the exact turn. The model turns + folded tool\n * records are the consumer's prompt source (via the llm-call message loader);\n * `turnCount` drives the livelock guard; `awaiting` carries the ONE outstanding\n * effect for the agentic stage.\n *\n * Generic over the consumer's tool-result type `R` (what `toolOk` carries).\n */\nexport interface Conversation<R> {\n /** Model turns this stage has produced, in order. */\n readonly turns: readonly AgentTurn[];\n /** Settled tool records, in settle order — the model sees these next turn. */\n readonly toolRecords: readonly ToolRecord<R>[];\n /** Monotonic round-trip count; the livelock guard compares it to `maxTurns`. */\n readonly turnCount: number;\n /** What the loop is waiting for next. */\n readonly awaiting: Awaiting;\n}\n\n// ===========================================================================\n// Config — the knob. The domain seams (tools / schemas / model / stages) are\n// required; everything cross-cutting (retry / deadline / concurrency / loader /\n// maxTurns) is optional, per the resilient-call \"omit a brick → omit its gate\".\n// ===========================================================================\n\n/**\n * The snapshotting discriminant (#55). Checkpointing is either OFF — in which\n * case `snapshotEvery` is structurally absent and the monitored-run slice never\n * emits a `snapshot_write` Cmd — or ON, in which case `snapshotEvery` is a\n * `number`. A `{ snapshotEvery?: never }` member (rather than a bare optional)\n * makes the OFF case load-bearing: it forbids passing `snapshotEvery` at all, so\n * `toMachine` can config-derive whether the `snapshot_write` interpret cell is\n * REQUIRED (ON) or FORBIDDEN (OFF) instead of defaulting it to a silent no-op.\n *\n * This is what kills the type lie: with checkpointing off, `snapshot_write` is\n * absent from the consumer's interpret contract entirely — never a\n * `snapshot_write: async () => undefined` ceremony that masks a real wiring bug.\n */\nexport type AgentSnapshotConfig =\n | { readonly snapshotEvery?: never }\n | { readonly snapshotEvery: number };\n\n/**\n * The core (non-snapshot, non-compaction) agent knob. The full `AgentConfig`\n * intersects this with the `AgentSnapshotConfig` + `AgentCompactionConfig`\n * discriminants — see those types for why the cadence / policy are discriminated\n * unions rather than bare optionals.\n *\n * Type parameters:\n * - `Stage` — the consumer's pipeline stage id (any JSON value).\n * - `P` — the brain-call purpose union (`\"plan\" | \"act\" | ...`).\n * - `O` — the purpose→output map. Every purpose drives the agentic loop,\n * so each output is pinned to `AgentTurn` (or a subtype) by the\n * `O extends Record<P, AgentTurn>` bound — that is what the loop\n * folds. An `Outputs` whose purpose output is NOT an `AgentTurn`\n * fails to compile here; the rule lives in the type, not a cast.\n * - `R` — the consumer's tool-result type (what `toolOk` carries).\n * - `TC` — the consumer's per-tool effect Cmd, the discriminated variant\n * `toolOf` produces. Kept PRECISE (a closed Cmd variant, not the\n * open `Cmd`) so `AgentCmd<P, TC>` stays a closed discriminated\n * union and the wired machine's interpret merge type-checks per\n * key — the brain cell maps to `resilient_run`, the tool cell to\n * `TC[\"type\"]` — with no laundering cast. Defaults to `Cmd` for\n * the consumer that does not care to name its tool Cmd.\n * - `Msg` — the model's message shape (threaded through the llm-call loader).\n */\nexport interface AgentConfigCore<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n> {\n // ---- monitored-run seam (the outer pipeline) ----------------------------\n /** The ordered stages. Omit / empty → a single-shot run (one agentic stage). */\n readonly stages?: readonly Stage[];\n /** No-progress watchdog budget, in ms. Omit → no watchdog. */\n readonly deadlineMs?: number;\n\n // ---- llm-call seam (the brain) ------------------------------------------\n /** DI port — the model factory `(modelId) => Llm`. */\n readonly model: ModelFactory<Msg>;\n /** One structured-output schema per purpose; the parse target per brain call. */\n readonly schemas: { readonly [K in P]: Schema<O[K]> };\n /** Backoff policy for brain calls, composed into `../llm-call`. Omit → no backoff. */\n readonly retry?: RetryPolicy;\n /** DI port — the SDK / message loader. Omit → brain calls invoke with `[]`. */\n readonly loadMessages?: MessageLoader<P, Msg>;\n\n // ---- fan-out seam (the tools) -------------------------------------------\n /** Map one tool call to the effect Cmd the consumer's interpret performs. */\n readonly toolOf: (call: ToolCall) => TC;\n /** Max tools in flight at once. Omit / `1` → serial dispatch (the seed's behavior). */\n readonly toolConcurrency?: number;\n\n // ---- the loop wiring -----------------------------------------------------\n /**\n * Which brain-call purpose a given stage runs. The agent fires\n * `call_llm{ turnOf(stage) }` to drive the agentic stage's loop. The purpose's\n * schema output is an `AgentTurn` — enforced by the `O extends Record<P,\n * AgentTurn>` bound, not left to a doc-comment.\n */\n readonly turnOf: (stage: Stage | undefined) => P;\n /** Build the per-purpose brain-call payload from the conversation. Omit → `null`. */\n readonly payloadOf?: (\n stage: Stage | undefined,\n conversation: Conversation<R>,\n ) => unknown;\n /** The model id every brain call invokes. Omit → `null` (the host's default). */\n readonly modelId?: string | null;\n /**\n * Livelock guard: bound on model round-trips within one run. On\n * `turnCount >= maxTurns` the run fails `{ reason: \"turn_limit\" }`. Omit → no\n * turn guard (only the deadline watchdog bounds the loop).\n */\n readonly maxTurns?: number;\n\n // ---- determinism seam ----------------------------------------------------\n /**\n * The impurity-injection seam for the inherited brain-call retry jitter — the\n * ONE place this otherwise-pure machine reads randomness. Pass a fixed\n * `() => 0` to pin backoff (tests, replay, durability proofs). Omit →\n * `Math.random`, read only at the resilient-call verb boundary.\n */\n readonly rng?: () => number;\n}\n\n/**\n * The agent knob — the core seams intersected with the snapshotting discriminant\n * (`AgentSnapshotConfig`). Type parameters are documented on `AgentConfigCore`;\n * the only addition here is that `snapshotEvery` is the discriminant that drives\n * whether `toMachine` requires (or forbids) the `snapshot_write` interpret cell.\n */\nexport type AgentConfig<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n> = AgentConfigCore<Stage, P, O, R, TC, Msg> &\n AgentSnapshotConfig &\n AgentCompactionConfig<R, Msg>;\n\n// ===========================================================================\n// Slice — the Model field this knob owns. Three composed slices + the loop's\n// conversation. Plain data end to end → durable + replayable.\n// ===========================================================================\n\n/**\n * Why a run terminated as `failed`, beyond monitored-run's own reasons. The\n * `turn_limit` reason is the agent's livelock guard; deadline / stage failures\n * surface through the monitored-run slice's own `failure`.\n */\nexport type AgentFailure =\n | { readonly reason: \"turn_limit\"; readonly at: number }\n | { readonly reason: \"llm\"; readonly error: unknown; readonly at: number };\n\n/**\n * The agent slice — every composed brick's slice plus the loop's conversation\n * and the agent-specific failure annotation.\n *\n * - `run` — the `../monitored-run` slice (pipeline position +\n * lifecycle + watchdog). The OUTER lifecycle truth.\n * - `resilience` — the `../llm-call` (= resilient-call) slice (brain-call\n * retry / backoff). Per-purpose retry lives here.\n * - `tools` — the `../fan-out` ledger for the current turn's tools.\n * - `conversation` — the agentic-stage loop state. `null` until the loop is\n * entered (the consumer seeds it at the agentic stage).\n * - `failure` — the agent-specific terminal annotation (turn-limit /\n * llm), null otherwise. Distinct from `run.failure`.\n */\nexport interface AgentState<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n> {\n readonly run: MonitoredRunState<Stage>;\n readonly resilience: ResilientState<LlmCall<P>, LlmOk<P, O>>;\n readonly tools: FanOutState<ToolCall, ToolOutcome<R>>;\n readonly conversation: Conversation<R> | null;\n /**\n * The compaction round-trip's resilient slice (#85, design B1) — a DEDICATED\n * resilient-call slice for the reserved `$compact` purpose, separate from the\n * brain `resilience` slice so a compaction retry/backoff never disturbs the\n * brain call's breaker or retry counter. Always present (empty `calls` when no\n * compaction is in flight, or when no policy is configured) so the slice stays\n * a flat plain-data record — durable + replayable like every composed brick.\n */\n readonly compaction: ResilientState<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >;\n readonly failure: AgentFailure | null;\n /**\n * The run's terminal output — the FIRST-CLASS result (issue #46). `null`\n * until the pipeline finishes; set to the last model turn (the empty-tool\n * turn that retired the final stage) the instant `run.phase` becomes `\"done\"`.\n *\n * This survives the `conversation` clear on stage retire: clearing the\n * conversation is correct durability hygiene (a finished stage's transcript\n * is not live state), but the run's PRODUCT is, so it lives here on the\n * durable slice rather than being scraped off the `observe` firehose by\n * matching the private `resilient_ok` Msg and racing the clear (the old\n * `captureLastTurn` dance this field deletes). A consumer reads\n * `runtime.result()?.output` / `(await runtime.done()).output`.\n *\n * Typed `AgentTurn | null` (not `O[P]`): the run's output is always a model\n * turn — the `O extends Record<P, AgentTurn>` knob bound pins every purpose's\n * output to an `AgentTurn`, and the terminating turn is the one with no tool\n * calls. The wider `Record<P, unknown>` bound on `AgentState` itself does not\n * constrain `O[P]`, so naming the concrete `AgentTurn` keeps this field's type\n * total without a purpose-indexing narrow.\n */\n readonly output: AgentTurn | null;\n}\n\n// ===========================================================================\n// Lifecycle status — the ONE typed channel callers read instead of re-deriving\n// the private slice shape (issue #49).\n// ===========================================================================\n\n/**\n * The unified terminal failure (issue #49). The agent terminates `failed`\n * through TWO independent slice channels:\n *\n * - `state.failure` (`AgentFailure`) — the AGENT'S OWN annotation\n * (`turn_limit` livelock guard / `llm` exhausted-retry). Set WITHOUT moving\n * `run.phase` (it stays `running`); `isSettled` treats a non-null `failure`\n * as terminal regardless of `run.phase`.\n * - `state.run.failure` (`RunFailure`) — the monitored-run channel\n * (`deadline` watchdog / `stage` failure), present iff `run.phase` is\n * `\"failed\"`.\n *\n * Callers used to union these by hand at every status question. `status`\n * collapses them into ONE `failure`, so a consumer reads `status(s).failure`\n * without knowing which channel produced it.\n */\nexport type AgentTerminalFailure<Stage> = AgentFailure | RunFailure<Stage>;\n\n/**\n * The agent's lifecycle status — THE single typed channel for \"what is this run\n * doing?\" (issue #49). A discriminated union on `kind` so any change to the\n * private slice shape (`Awaiting`, the failure channels, `run.phase`) forces a\n * compile error at the call sites that switch on it, instead of silently\n * breaking a hand-rolled re-derivation. Make-invalid-states-unrepresentable:\n *\n * - `running` — live, NOT awaiting tools (a brain call is in flight, or the\n * run is between stages). Not resumable on cold wake by\n * itself — the in-flight brain call re-fires from `boot`.\n * - `suspended` — the RESUMABLE case: running + a live conversation +\n * `awaiting.kind === \"tools\"`. `pending` is the outstanding\n * tool calls (`conversation.awaiting` … the in-flight batch),\n * read off `tools.running`. This is exactly the shape\n * `agentIsResumable` re-derived by hand.\n * - `done` — the pipeline finished; `output` is the terminal model turn\n * stamped on `state.output` (issue #46), `null` if the run\n * produced no turn.\n * - `failed` — terminal failure; `failure` is the UNIFIED channel\n * (`AgentTerminalFailure`), absorbing the `state.failure` vs\n * `state.run.failure` dual channel so callers stop unioning.\n */\nexport type AgentStatus<Stage> =\n | { readonly kind: \"running\" }\n | { readonly kind: \"suspended\"; readonly pending: readonly ToolCall[] }\n | { readonly kind: \"done\"; readonly output: AgentTurn | null }\n | { readonly kind: \"failed\"; readonly failure: AgentTerminalFailure<Stage> };\n\n/**\n * Derive the agent's lifecycle `status` from its durable slice — the pure\n * status function that REPLACES every caller's hand re-derivation of the private\n * shape (issue #49). PURE — reads no clock / RNG, allocates one small record.\n *\n * Ordering is terminal-first so a settled run never reports `running`:\n *\n * 1. `state.failure` (the agent's own annotation, set WITHOUT moving\n * `run.phase`) → `failed`. Checked first because `turn_limit` / `llm`\n * leave `run.phase === \"running\"`; reading `run.phase` first would\n * misreport such a run as `running`. This is the canonical failure source\n * when present.\n * 2. `run.phase === \"failed\"` → `failed`, carrying `run.failure` (deadline /\n * stage). The fallback channel.\n * 3. `run.phase === \"done\"` → `done` with `state.output` (#46).\n * 4. running + conversation + `awaiting.kind === \"tools\"` → `suspended` with\n * the outstanding tool calls (`tools.running`). THE resumability condition.\n * 5. otherwise → `running`.\n */\nexport function status<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): AgentStatus<Stage> {\n // 1) The agent's own failure annotation is canonical — it is set without\n // moving `run.phase` (turn_limit / llm leave the run `running`), so it\n // MUST be read before `run.phase` or such a failure reports as `running`.\n if (s.failure !== null) {\n return { kind: \"failed\", failure: s.failure };\n }\n // 2) The monitored-run terminal failure (deadline / stage). `run.failure` now\n // rides ONLY the `failed` arm of the discriminated union, so narrowing on\n // `phase === \"failed\"` surfaces it with no nullable side field and no\n // fabricated fallback — the old \"failed-yet-failure-null\" state is\n // unrepresentable.\n if (s.run.phase === \"failed\") {\n return { kind: \"failed\", failure: s.run.failure };\n }\n // 3) The pipeline finished — the terminal output landed on `state.output`.\n if (s.run.phase === \"done\") {\n return { kind: \"done\", output: s.output };\n }\n // 4) Running + a live conversation awaiting tools → suspended (resumable).\n // The outstanding calls are the in-flight fan-out batch (`tools.running`).\n if (s.conversation !== null && s.conversation.awaiting.kind === \"tools\") {\n return { kind: \"suspended\", pending: s.tools.running };\n }\n // 5) Otherwise the run is live and not awaiting tools.\n return { kind: \"running\" };\n}\n","/**\n * @packageDocumentation\n * @demlik/tea/agent — THE headline Level-3 machine: a durable, crash-recoverable\n * AI agent that runs an ordered stage pipeline, and inside the agentic stage\n * drives the classic loop `llm → tools → fold → llm` until the model stops\n * asking for tools.\n *\n * This is the `seed/audit-agent-machine` reducer generalized: the seed's audit /\n * glyph / violation domain specifics are stripped, and what remains — the loop,\n * the durability, the boot-reconcile crash recovery, the serial-vs-fanned tool\n * dispatch — is yours. The consumer supplies the only things that are genuinely\n * domain: the tools, the prompts (via the llm-call message loader), the schemas,\n * and the model. `createAgent(config)` returns the uniform knob contract every\n * composition exposes (`init` / verbs returning `readonly [State, Cmd[]]` /\n * `subs`) AND a ready-to-`run` `defineMachine` (`toMachine`) — THE one wired\n * path. (`unsafeDetachedHandlers` is the hand-wiring escape hatch; its name\n * advertises that it does not drive the retry loop — see #54.)\n *\n * ## The composition (three siblings wired into ONE machine)\n *\n * - `../monitored-run` — the OUTER pipeline + lifecycle + safety watchdog.\n * The agent's stages (`plan → act → report`, say) are its stages; the\n * position survives eviction, the no-progress deadline auto-fails a wedged\n * run, and `boot` resumes mid-pipeline. The agent slice OWNS this slice and\n * delegates `start` / `advance` / `progress` / `onDeadline` / `boot` to it.\n * - `../llm-call` — every brain call (the seed's `call_llm{purpose}`). One\n * `LlmCall` per turn, structured-output parsed, retry composed in. The agent\n * delegates the resilient slice + verbs and reuses the detached handler.\n * - `../fan-out` — the tool calls a turn produced. The seed dispatched tools\n * SERIALLY (concurrency 1); fan-out generalizes that to bounded concurrency\n * `config.toolConcurrency` (default 1 = the seed's serial behavior). Each\n * tool is an `of(call)` Cmd the consumer's own interpret performs; results\n * route back through `toolOk` / `toolErr`. When the batch drains, the agent\n * folds the gathered results back into the conversation and fires the next\n * brain call (`fold → llm`).\n *\n * ## The flow loop, as TEA (generalized from the seed's `applyAiTurn`)\n *\n * 1. `start` enters the pipeline; the consumer wires the per-stage outstanding\n * effect (often a `call_llm` for the agentic stage) off the current stage.\n * 2. `turn(msg)` folds one model turn:\n * - no tool calls → the loop is done for this stage → `advance` the\n * pipeline (next stage, or finish to `done`).\n * - tool calls → `scatter` them across fan-out (≤ concurrency in flight),\n * emitting the per-tool effect Cmds. The conversation records the model\n * turn; `awaiting` flips to `tools`.\n * 3. `toolOk` / `toolErr` fold each settled tool back, launching the next\n * queued tool. When the batch drains, fold the gathered outcomes into the\n * conversation, bump the turn count (livelock guard), and fire the next\n * brain call — `awaiting` flips back to `llm`.\n * 4. The watchdog + turn-limit guard bound the loop; the deadline fires\n * `failed`, the turn limit fires `failed { turn_limit }`.\n *\n * ## Boot reconcile (crash recovery — the seed's `outstandingEffect`)\n *\n * Cold wake re-derives the ONE outstanding effect from `phase × awaiting`: a\n * brain call in flight re-fires `call_llm`; tools in flight re-fire the in-flight\n * tool Cmds. Re-fire is Model-idempotent — had the prior effect's result been\n * processed, the durable Model would already have advanced and boot re-emits the\n * NEXT effect. `boot` re-seeds the watchdog clock to NOW (a cold wake is not a\n * no-progress wedge) via the inherited monitored-run `boot`.\n *\n * ## The two non-negotiables (canon, inherited)\n *\n * - **Durable** — the whole slice is plain data: the monitored-run slice, the\n * resilient (retry) slice, the fan-out ledger, and the conversation are all\n * JSON-serializable. It survives DO eviction / reload.\n * - **Replayable** — every transition is a pure verb returning new state +\n * Cmds; nothing here reads the clock or RNG. Time arrives as an `at`\n * parameter, jitter RNG is injected once at `createAgent`, and the only clock\n * reads live inside the spliced handlers (the effect boundary).\n *\n * ## Typical wiring\n *\n * // Type params: <Stage, Purpose, Outputs, Result, ToolCmd, Msg>. `ToolCmd`\n * // is the discriminated Cmd `toolOf` returns — keep it precise (not the open\n * // `Cmd`) so the wired machine's interpret merge type-checks per key.\n * type RunTool = { readonly type: \"run_tool\" } & ToolCall;\n * const agent = createAgent<Stage, Purpose, Outputs, Result, RunTool, Msg>({\n * stages: [\"plan\", \"act\", \"report\"],\n * model: (id) => createChatModel(env, id),\n * schemas: { plan: planSchema, act: turnSchema, report: reportSchema },\n * turnOf: (stage) => stageToPurpose[stage], // which brain call a stage runs\n * toolOf: (call): RunTool => ({ type: \"run_tool\", ...call }),\n * toolConcurrency: 1, // serial like the seed (default)\n * deadlineMs: 10 * 60_000,\n * maxTurns: 60,\n * retry: defaultRetryPolicy,\n * loadMessages,\n * });\n * // The consumer supplies the per-tool (+ snapshot) interpret; the agent owns\n * // the brain interpret and merges them in `toMachine`.\n * const machine = agent.toMachine({ toolInterpret });\n * const runtime = run(machine, { ctx, store });\n */\n\nimport { createFanOut, initFanOut } from \"../fan-out\";\nimport {\n type Cmd,\n defineMachine,\n type Interpret,\n type Machine,\n type Reducer,\n} from \"../index\";\nimport {\n createLlmCall,\n deadlineSub,\n type LlmCall,\n type LlmFailMsg,\n type LlmOk,\n type LlmRunCmd,\n type LlmSucceedMsg,\n type ResilientState,\n subscribeDeadline,\n} from \"../llm-call\";\nimport {\n createMonitoredRun,\n type DeadlineSub,\n type MonitoredRunCmd,\n} from \"../monitored-run\";\nimport { MsgType } from \"../protocol\";\nimport { createResilientCall } from \"../resilient-call\";\nimport {\n type AgentCompactErrMsg,\n type AgentCompactOkMsg,\n type AgentCompactRunCmd,\n COMPACTION_PURPOSE,\n type CompactInterpret,\n type CompactionOutputs,\n type CompactionPolicy,\n type CompactionPurpose,\n} from \"./compaction\";\nimport {\n currentStage,\n dedupeByCallId,\n foldSummary,\n freshConversation,\n isSettled,\n requireAwaiting,\n toCompactRunCmd,\n} from \"./internal\";\nimport {\n type AgentCmd,\n type AgentDetachedHandlers,\n type AgentKnob,\n type AgentLlmErrMsg,\n type AgentLlmOkMsg,\n type AgentLlmRunCmd,\n type AgentMachineMsg,\n type AgentPorts,\n type AgentTimerMsg,\n mergeInterpret,\n type SnapshotInterpret,\n} from \"./machine\";\nimport type {\n AgentConfig,\n AgentConfigCore,\n AgentFailure,\n AgentState,\n AgentTurn,\n Conversation,\n ToolCall,\n ToolOutcome,\n} from \"./types\";\n\n// Re-export the concern modules so the public `@demlik/tea/agent` barrel is\n// unchanged after the split into `./types` (domain + conversation + config +\n// state/status), `./compaction` (the #85 seam), and `./machine` (the Cmd/Msg\n// vocabulary + wiring helpers). The reducer core — `createAgent` — stays here.\nexport * from \"./compaction\";\nexport * from \"./machine\";\nexport * from \"./types\";\n\n// ===========================================================================\n// The knob factory.\n// ===========================================================================\n\n/**\n * Build an agent knob from `config`. The determinism seam — `config.rng`,\n * injected for the inherited brain-call retry jitter — lives as a named field\n * on the config (pass a fixed `() => 0` to pin backoff in tests; omit → defaults\n * to `Math.random`, read only at the resilient-call verb boundary).\n *\n * Returns the uniform knob contract (`init` / verbs / `subs`) plus `toMachine()`\n * — a `defineMachine` wiring all of it into one runnable machine — and the\n * `unsafeDetachedHandlers` hand-wiring escape hatch.\n *\n * `createAgent` is OVERLOADED on TWO independent discriminants — the snapshotting\n * (#55) and the compaction (#85) one — so each `toMachine` obligation is derived\n * from the `config` VALUE, never inferred. `{ snapshotEvery: number }` REQUIRES\n * the `snapshot_write` cell, `{ snapshotEvery?: never }` FORBIDS it; `{ compaction:\n * policy }` REQUIRES the `compact_run` cell, `{ compaction?: never }` FORBIDS it.\n * The four overloads enumerate the snapshot × compaction grid: overload resolution\n * reads the two fields off `config`, so the right `Snap`/`Compact` pair is fixed\n * even when the call site passes explicit type arguments (TS does not infer\n * trailing type params — a `Cfg`-inference scheme would silently fall back to OFF\n * at every explicit-type-arg call site). The overloads fix both concretely.\n */\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery: number;\n readonly compaction: CompactionPolicy<R, Msg>;\n },\n): AgentKnob<Stage, P, O, R, TC, true, true>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery: number;\n readonly compaction?: never;\n },\n): AgentKnob<Stage, P, O, R, TC, true, false>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery?: never;\n readonly compaction: CompactionPolicy<R, Msg>;\n },\n): AgentKnob<Stage, P, O, R, TC, false, true>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery?: never;\n readonly compaction?: never;\n },\n): AgentKnob<Stage, P, O, R, TC, false, false>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfig<Stage, P, O, R, TC, Msg>,\n): AgentKnob<Stage, P, O, R, TC, boolean, boolean> {\n const rng = config.rng ?? Math.random;\n // ---- The three composed sub-knobs --------------------------------------\n\n const run = createMonitoredRun<Stage, unknown>({\n ...(config.stages !== undefined ? { stages: config.stages } : {}),\n ...(config.deadlineMs !== undefined\n ? { deadlineMs: config.deadlineMs }\n : {}),\n ...(config.snapshotEvery !== undefined\n ? { snapshotEvery: config.snapshotEvery }\n : {}),\n });\n\n const llm = createLlmCall<P, O, Msg>(\n {\n model: config.model,\n schemas: config.schemas,\n ...(config.retry !== undefined ? { retry: config.retry } : {}),\n ...(config.loadMessages !== undefined\n ? { loadMessages: config.loadMessages }\n : {}),\n },\n rng,\n );\n\n // The DEDICATED compaction round-trip's resilient slice (#85, design B1) — a\n // SECOND resilient-call slice keyed on the reserved `$compact` purpose, so the\n // summarize call inherits the SAME retry/backoff machinery as the brain call\n // WITHOUT sharing its slice (a compaction retry never touches the brain breaker\n // / retry counter). The agent owns the retry ORCHESTRATION (trigger → settle →\n // backoff → re-issue); the consumer's `compact_run` interpret cell owns the\n // summarize I/O (the model round-trip + parse), exactly as the consumer owns\n // tool I/O via `toolOf`. The slice's `input` is the plain `LlmCall<$compact>`\n // request, its `result` the parsed `LlmOk` the consumer's cell returns. Always\n // built; never driven when no policy is configured (the trigger never fires).\n const compactRc = createResilientCall<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >({ ...(config.retry !== undefined ? { retry: config.retry } : {}) }, rng);\n\n // Tools fan out at `toolConcurrency` (default 1 = the seed's serial dispatch).\n // The fan-out item is the `ToolCall`; its identity is `callId`; each launch is\n // the consumer's `toolOf(call)` effect. No `join` — the agent reads completion\n // off `isComplete` at the settle boundary (it must fold + fire the next brain\n // call, not emit a single completion Cmd).\n // `TC` is the fan-out's launch-Cmd type and `never` its join-Cmd type (the\n // agent fires no `join` — it reads completion off `isComplete`), so `scatter`\n // / `itemOk` / `itemErr` return `readonly TC[]` (not the widened `Cmd[]`). The\n // agent's verb tuples stay precisely `AgentCmd<P, TC>` with no widening cast\n // on the launch cmds.\n const fan = createFanOut<ToolCall, ToolOutcome<R>, TC, never>({\n concurrency: config.toolConcurrency ?? 1,\n idOf: (call) => call.callId,\n of: (call) => config.toolOf(call),\n });\n\n type State = AgentState<Stage, P, O, R>;\n\n /** The starting slice — every brick's `init`, no conversation yet. */\n function init(): State {\n return {\n run: run.init(),\n resilience: llm.init(),\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n conversation: null,\n compaction: compactRc.init(),\n failure: null,\n output: null,\n };\n }\n\n /** Build the brain-call request for the current stage + conversation. PURE. */\n function brainCall(s: State): LlmCall<P> {\n const stage = currentStage(s);\n const conversation = s.conversation ?? freshConversation<R>();\n return {\n purpose: config.turnOf(stage),\n model: config.modelId ?? null,\n payload: config.payloadOf ? config.payloadOf(stage, conversation) : null,\n };\n }\n\n /**\n * Fire the current stage's brain call: build the request ({@link brainCall}),\n * thread it through the resilient retry layer, and return the resilience-updated\n * state + the llm run Cmds. THE shared epilogue of every verb that (re-)enters\n * the brain path — `start`, `advanceStage`, `settleTool`'s drain, `compactOk`,\n * `compactErr`, `boot` — each concats its OWN leading Cmds onto the returned llm\n * Cmds. PURE — `at` is the only clock.\n */\n function fireBrainCall(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const call = brainCall(s);\n const [resilience, cmds] = llm.attempt(s.resilience, call, at);\n return [{ ...s, resilience }, cmds];\n }\n\n /**\n * Build the compaction summarize request for a conversation + fold count — the\n * `$compact` sibling of {@link brainCall}, so the summarize-request shape lives\n * in ONE spot and both the trigger (`maybeCompact`) and the boot re-fire emit a\n * byte-identical `LlmCall<$compact>`. PURE.\n */\n function compactionCall(\n conv: Conversation<R>,\n folding: number,\n ): LlmCall<CompactionPurpose> {\n const payloadOf = config.compaction?.payloadOf;\n return {\n purpose: COMPACTION_PURPOSE,\n model: config.modelId ?? null,\n payload: payloadOf ? payloadOf(conv, folding) : null,\n };\n }\n\n /** The dedicated compaction round-trip's resilient slice type (#85, design B1). */\n type CompactionSlice = ResilientState<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >;\n\n /**\n * Re-key a compaction verb's `[slice, resilient_run Cmds]` result so the emitted\n * Cmds carry the dedicated `compact_run` discriminant. The one place the\n * `with-resilience` boundary re-key ({@link toCompactRunCmd}) lives.\n */\n function reKeyCompactCmds(\n result: readonly [CompactionSlice, readonly LlmRunCmd<CompactionPurpose>[]],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] {\n const [slice, cmds] = result;\n return [slice, cmds.map(toCompactRunCmd)];\n }\n\n /**\n * The compaction slice's four cmd-emitting verbs, wrapped so each returns its\n * `resilient_run` Cmds ALREADY re-keyed to the dedicated `compact_run`\n * discriminant. The re-key is an INVARIANT of talking to `compactRc` — its Cmds\n * must route to the compaction interpret cell, never the brain `resilient_run`\n * one — so it lives here ONCE instead of at every call boundary, where a single\n * forgotten `.map` would misroute a compaction run Cmd to the brain cell. PURE —\n * pure delegation + re-key. (`init` / `subs` emit no run Cmds → used on\n * `compactRc` directly.)\n */\n const compact = {\n attempt: (\n slice: CompactionSlice,\n key: CompactionPurpose,\n input: LlmCall<CompactionPurpose>,\n at: number,\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.attempt(slice, key, input, at)),\n succeed: (\n slice: CompactionSlice,\n key: string,\n msg: Parameters<typeof compactRc.succeed>[2],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.succeed(slice, key, msg)),\n fail: (\n slice: CompactionSlice,\n key: string,\n msg: Parameters<typeof compactRc.fail>[2],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.fail(slice, key, msg)),\n onTimer: (\n slice: CompactionSlice,\n msg: Parameters<typeof compactRc.onTimer>[1],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.onTimer(slice, msg)),\n };\n\n // === Verb: start =========================================================\n\n /**\n * Start (or restart) the run for `runId` at `at`, entering the agentic loop:\n * seed the pipeline (via monitored-run), seed a fresh conversation, and fire\n * the first brain call. PURE — `at` is the only clock.\n */\n function start(\n s: State,\n runId: string,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice] = run.start(s.run, runId, at);\n const conversation = freshConversation<R>();\n const withRun: State = {\n ...s,\n run: runSlice,\n conversation,\n failure: null,\n // A restart clears the prior run's terminal output — `result()` reads\n // `undefined` again until THIS run finishes (#46).\n output: null,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n // A restart also clears any prior compaction slice — a fresh run never\n // inherits the previous run's summarize retry bookkeeping (#85).\n compaction: compactRc.init(),\n };\n return fireBrainCall(withRun, at);\n }\n\n // === Verb: turn ==========================================================\n\n /**\n * Fold ONE model turn (the brain call resolved with an `AgentTurn`). The core\n * of the loop — the seed's `applyAiTurn`, generalized:\n *\n * - empty `toolCalls` → the loop is done for this stage → `advance` the\n * pipeline (next stage seeds a fresh conversation + brain call, or finish\n * to `done`).\n * - non-empty `toolCalls` → `scatter` them across fan-out (≤ concurrency in\n * flight), recording the turn and flipping `awaiting` to `tools`. The\n * returned Cmds are the launched per-tool effects.\n *\n * A no-op when the run is settled or the slice is not awaiting a brain call\n * (stale settle after boot / advance). PURE — `at` is the only clock.\n */\n function turn(\n s: State,\n result: AgentTurn,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const conv = requireAwaiting(s, \"llm\");\n if (conv === null) return [s, []];\n\n const withTurn: Conversation<R> = {\n ...conv,\n turns: [...conv.turns, result],\n };\n\n // ── No tool calls → the stage's loop is done → advance the pipeline. ──\n // `result` is the terminating turn — threaded into `advanceStage` so it can\n // be stamped as the run's `output` when this retire finishes the pipeline.\n if (result.toolCalls.length === 0) {\n return advanceStage({ ...s, conversation: withTurn }, result, at);\n }\n\n // ── Tool calls → scatter across fan-out (serial by default). ──\n // The fan-out item identity IS `callId` (`idOf`). A model that emits the\n // SAME `callId` twice in one turn is a defect: scattering both would launch\n // the consumer's `toolOf(call)` effect twice for one identity (the dup runs\n // TWICE) while a single settle Msg can only close ONE of the two `running`\n // entries — the other stays in flight forever and the batch never drains.\n // Collapse duplicates by `callId` (keep first occurrence) so every distinct\n // tool launches exactly once and each `callId` settles exactly once.\n const batch = dedupeByCallId(result.toolCalls);\n const [tools, launchCmds] = fan.scatter(\n initFanOut<ToolCall, ToolOutcome<R>>(),\n batch,\n );\n const nextConv: Conversation<R> = {\n ...withTurn,\n awaiting: { kind: \"tools\", batchTurn: withTurn.turnCount },\n };\n // An advance of the loop is progress — bump the monitored-run watchdog.\n const [runSlice] = run.progress(s.run, undefined, at);\n return [{ ...s, run: runSlice, tools, conversation: nextConv }, launchCmds];\n }\n\n /**\n * Advance the outer pipeline on a finished stage loop. Retire the current\n * stage (monitored-run `advance`); if the pipeline finished → `done`, else\n * seed a fresh conversation for the next stage and fire its first brain call.\n * Shared by `turn` (empty tool calls) so the loop-end → next-stage move lives\n * in one place. PURE.\n *\n * `terminatingTurn` is the empty-tool model turn that ended the current\n * stage's loop. When THIS retire finishes the whole pipeline (`done`), it is\n * the run's terminal output — stamped on `state.output` so it survives the\n * conversation clear and `runtime.result()` can read it (#46).\n */\n function advanceStage(\n s: State,\n terminatingTurn: AgentTurn,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice, runCmds] = run.advance(\n s.run,\n undefined,\n { kind: \"ok\" },\n at,\n );\n // Pipeline finished (or single-shot done) → no further brain call. The\n // terminating turn is the run's output; record it before clearing the\n // conversation so the result survives the retire (the field the deleted\n // `captureLastTurn` host hook used to reconstruct off the stream).\n if (runSlice.phase === \"done\") {\n return [\n { ...s, run: runSlice, conversation: null, output: terminatingTurn },\n runCmds,\n ];\n }\n // Next stage → fresh conversation + its first brain call.\n const conversation = freshConversation<R>();\n const moved: State = {\n ...s,\n run: runSlice,\n conversation,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n };\n const [fired, llmCmds] = fireBrainCall(moved, at);\n return [fired, [...runCmds, ...llmCmds]];\n }\n\n // === Verb: toolOk / toolErr ==============================================\n\n /**\n * Record a tool's success for `callId` and launch the next queued tool to\n * backfill the freed slot (the seed's queue-drain → next-tool). When the batch\n * drains, fold every gathered outcome into the conversation, bump the turn\n * count (livelock guard), and fire the next brain call — `awaiting` flips back\n * to `llm` (\"fold → llm\"). PURE.\n */\n function toolOk(\n s: State,\n callId: string,\n result: R,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return settleTool(s, callId, { kind: \"ok\", result }, at);\n }\n\n /**\n * Record a tool's failure for `callId` — symmetric to `toolOk`. A failed tool\n * still counts toward batch completion (the model sees the error reason and\n * recovers — \"errors are data\"); same fold → llm tail when the batch drains.\n * PURE.\n */\n function toolErr(\n s: State,\n callId: string,\n reason: string,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return settleTool(s, callId, { kind: \"error\", reason }, at);\n }\n\n /**\n * Shared tool-settle body: route the outcome into fan-out, fold the matching\n * call+outcome onto the conversation, and — if the batch is now complete —\n * fold the turn and fire the next brain call. PURE.\n */\n function settleTool(\n s: State,\n callId: string,\n outcome: ToolOutcome<R>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const conv = requireAwaiting(s, \"tools\");\n if (conv === null) return [s, []];\n\n // Find the original call (by id) so the folded record carries it. A settle\n // for an unknown / already-settled id is a no-op (fan-out also no-ops it).\n const call = s.tools.running.find((c) => c.callId === callId);\n if (call === undefined) return [s, []];\n\n const [tools, launchCmds] =\n outcome.kind === \"ok\"\n ? fan.itemOk(s.tools, callId, outcome)\n : fan.itemErr(s.tools, callId, outcome);\n\n const foldedConv: Conversation<R> = {\n ...conv,\n // Stamp the producing-turn index on the record (#85, A1). At settle time\n // `conv.turnCount` equals the index in `turns` of the turn that scattered\n // this batch (each prior drained batch bumped `turnCount` exactly once, and\n // each tool-bearing turn appended exactly one entry to `turns`), so a record\n // carrying `turn: conv.turnCount` is dropped iff its producing turn is folded\n // (`turn < N`) — the association the fold-back relies on.\n toolRecords: [\n ...conv.toolRecords,\n { call, outcome, turn: conv.turnCount },\n ],\n };\n\n // Batch still draining → record + keep launching the next queued tool.\n if (!fan.isComplete(tools)) {\n const [runSlice] = run.progress(s.run, undefined, at);\n return [\n { ...s, run: runSlice, tools, conversation: foldedConv },\n launchCmds,\n ];\n }\n\n // ── Batch drained → fold the turn → fire the next brain call. ──\n const turnedConv: Conversation<R> = {\n ...foldedConv,\n turnCount: foldedConv.turnCount + 1,\n awaiting: { kind: \"llm\" },\n };\n\n // Livelock guard: the bumped turn count crossing maxTurns → terminal fail.\n if (\n config.maxTurns !== undefined &&\n turnedConv.turnCount >= config.maxTurns\n ) {\n return failTurnLimit({ ...s, tools, conversation: turnedConv }, at);\n }\n\n // The tool ledger resets for the next turn's batch regardless of which\n // effect (compaction or brain call) fires next.\n const drained: State = {\n ...s,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n conversation: turnedConv,\n };\n\n // ── Compaction trigger (#85, design B1). BEFORE the next brain call, ask\n // the PURE policy how many oldest turns to fold. N > 0 → fire the dedicated\n // compaction round-trip INSTEAD of the brain call and flip awaiting to\n // `compacting`; the fold-back (`compact_ok`) then fires the brain call. The\n // trigger bumps the watchdog (compaction IS liveness, decision C) but does\n // NOT bump `turnCount` — it already bumped once for this drained batch, and\n // compaction is not model reasoning progress, so it never trips `maxTurns`.\n const compacting = maybeCompact(drained, at);\n if (compacting !== null) return compacting;\n\n // ── No compaction → fire the next brain call. ──\n // An advance of the loop is progress — bump the watchdog, then fire.\n const [runSlice] = run.progress(drained.run, undefined, at);\n const [fired, llmCmds] = fireBrainCall({ ...drained, run: runSlice }, at);\n return [fired, [...launchCmds, ...llmCmds]];\n }\n\n /**\n * The compaction trigger (#85, design B1) — PURE. Given the drained-batch\n * state about to fire a brain call, consult `config.compaction.planCompaction`\n * (the consumer's PURE heuristic). Returns:\n *\n * - `null` — no policy, or the policy returned `0`, or there is nothing to\n * fold (`< 2` turns: folding 0 or 1 turns into a summary cannot shrink the\n * transcript, so it is a no-op the trigger skips rather than spend a round\n * trip). The caller fires the brain call as normal.\n * - `[state, cmds]` — fire the dedicated compaction round-trip: flip\n * `awaiting` to `compacting { folding: N }`, bump the watchdog (liveness,\n * decision C — NOT `turnCount`, so `maxTurns` is untouched), and emit the\n * re-keyed `compact_run` Cmd. `compact_ok` folds the summary back; the loop\n * resumes with the next brain call there.\n *\n * `folding` is clamped to `turns.length` so a policy returning a count larger\n * than the transcript folds the WHOLE transcript into one summary (never more).\n * The launched `launchCmds` from the final tool settle are NOT this function's\n * concern — the caller composes them.\n */\n function maybeCompact(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] | null {\n const policy = config.compaction;\n const conv = s.conversation;\n if (policy === undefined || conv === null) return null;\n const requested = policy.planCompaction(conv);\n // Nothing to gain: a fold of 0 or 1 turns cannot shrink the transcript\n // (`turns[0..N]` → one summary turn only shrinks when N >= 2).\n const folding = Math.min(requested, conv.turns.length);\n if (folding < 2) return null;\n\n const compactConv: Conversation<R> = {\n ...conv,\n awaiting: { kind: \"compacting\", folding },\n };\n // Compaction is forward progress (liveness) — bump the watchdog, NOT the\n // turn count (decision C: it is not model reasoning, must not trip maxTurns).\n const [runSlice] = run.progress(s.run, undefined, at);\n const input = compactionCall(conv, folding);\n // The `compact` adapter re-keys the composed `resilient_run` Cmd(s) to the\n // dedicated `compact_run` discriminant so they route to the compaction\n // interpret cell, never the brain `resilient_run` one (the `with-resilience`\n // boundary-re-key pattern).\n const [compaction, cmds] = compact.attempt(\n s.compaction,\n COMPACTION_PURPOSE,\n input,\n at,\n );\n return [\n { ...s, run: runSlice, conversation: compactConv, compaction },\n cmds,\n ];\n }\n\n /** Terminal: the livelock guard tripped. Settle the run failed. PURE. */\n function failTurnLimit(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return [{ ...s, failure: { reason: \"turn_limit\", at } }, []];\n }\n\n // === Verb: succeed / fail (brain-call resilient settles) =================\n\n /**\n * Fold a brain-call SUCCESS — the FIXED single entry the re-entered\n * `resilient_ok` settle Msg drives. Two halves, in order:\n *\n * 1. The RETRY layer: `llm.succeed` closes the breaker and DROPS this key's\n * retry counter. This is the half the old detached wiring skipped — the\n * detached handler dispatched the parsed turn directly and never\n * re-entered `resilient_ok`, so `succeed` never ran, the resilient slice\n * stayed stuck `running`, the breaker never closed, and the retry counter\n * ACCUMULATED across the run (a later transient failure would trip\n * `maxAttempts` prematurely). Running it here resets the retry slice every\n * turn — a clean retry slice across the whole run.\n * 2. The LOOP: fold the parsed `AgentTurn` (`msg.result.output`) through\n * `turn`, which scatters this turn's tools (or advances the pipeline on an\n * empty turn). One re-entered settle Msg now advances BOTH the resilient\n * slice AND the conversation, so the loop actually progresses to a\n * terminal `done`.\n *\n * PURE — `at` is the only clock.\n */\n function succeed(\n s: State,\n key: string,\n msg: AgentLlmOkMsg<P, O>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n // 1) Advance the retry layer — resets retry[key], closes the breaker.\n const [resilience, retryCmds] = llm.succeed(s.resilience, key, msg);\n const settled: State = { ...s, resilience };\n // 2) Fold the parsed turn into the loop (scatter tools / advance the stage).\n // `msg.result.output` is `O[P]`, and the `O extends Record<P, AgentTurn>`\n // bound pins every purpose's output to an `AgentTurn` — so it feeds `turn`\n // with NO cast. The rule lives in the type (invariant 8: no `as` past the\n // boundary), not in a doc-comment the compiler cannot enforce.\n const [withTurn, turnCmds] = turn(settled, msg.result.output, at);\n return [withTurn, [...retryCmds, ...turnCmds]];\n }\n\n /**\n * Record a brain-call failure: back off via the inherited retry (re-arming\n * the retry timer), or — when retry is exhausted / absent — the resilient\n * slice settles the call `failed`. The agent also stamps an `llm` failure on\n * its own slice so a consumer can render the terminal cause. PURE.\n */\n function fail(\n s: State,\n key: string,\n msg: AgentLlmErrMsg<P>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [resilience, cmds] = llm.fail(s.resilience, key, msg);\n // If the resilient slice settled this call terminally (no retry pending),\n // surface the agent-level llm failure too. A `waiting_retry` phase means a\n // retry is armed → not terminal → leave `failure` untouched.\n const call = resilience.calls[key];\n const failure: AgentFailure | null =\n call?.phase === \"failed\"\n ? { reason: \"llm\", error: msg.error, at }\n : s.failure;\n return [{ ...s, resilience, failure }, cmds];\n }\n\n // === Verb: compactOk / compactErr (compaction resilient settles) =========\n\n /**\n * Fold the compaction SUMMARY back (#85, design A1) — the entry the re-entered\n * `compact_ok` settle Msg drives. Two halves, in order:\n *\n * 1. The RETRY layer: `compactRc.succeed` closes the compaction breaker and\n * DROPS the `$compact` retry counter (the same reset the brain `succeed`\n * does, on the dedicated compaction slice).\n * 2. The FOLD-BACK: replace `turns[0..folding]` AND every `toolRecord` whose\n * `turn < folding` with a SINGLE synthetic summary `AgentTurn` (no tool\n * calls, carrying the summary text), then RE-INDEX the surviving records'\n * `turn` so the new head (the summary) is index 0. `turnCount` is\n * UNCHANGED (compaction is not a model round-trip — decision C), and\n * `awaiting` flips back to `llm`. The next brain call fires on the shrunk\n * transcript — the loop the trigger paused resumes here.\n *\n * A no-op if the run is settled or not awaiting compaction (a stale settle).\n * PURE — `at` is the only clock.\n */\n function compactOk(\n s: State,\n key: string,\n msg: AgentCompactOkMsg,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n // 1) Advance the compaction retry layer — resets retry[$compact], closes the\n // compaction breaker. Reuses llm-call's `succeed` on the dedicated slice;\n // the enriched `LlmSucceedMsg` is the `compact_ok` payload as-is.\n const [compaction, retryCmds] = compact.succeed(s.compaction, key, {\n type: MsgType.ResilientOk,\n key: msg.key,\n result: msg.result,\n at: msg.at,\n });\n const settledRetry: State = { ...s, compaction };\n\n // Stale settle (the run is settled, or advanced/rebooted past this\n // compaction). The retry slice still resets above; emit only its cmds\n // (`succeed` never emits a run Cmd, so `retryCmds` is empty here).\n const conv = requireAwaiting(settledRetry, \"compacting\");\n if (conv === null) return [settledRetry, retryCmds];\n\n // 2) Fold-back. `folding` is the count the trigger pinned on `awaiting`; the\n // summary turn replaces those oldest turns + their records.\n const folding = conv.awaiting.folding;\n const summaryTurn: AgentTurn = {\n content: msg.result.output.summary,\n toolCalls: [],\n };\n const foldedConv = foldSummary(conv, folding, summaryTurn);\n // Resume the loop: fire the next brain call on the shrunk transcript.\n const [fired, llmCmds] = fireBrainCall(\n { ...settledRetry, conversation: foldedConv },\n at,\n );\n return [fired, [...retryCmds, ...llmCmds]];\n }\n\n /**\n * Record a compaction FAILURE (#85). Back off via the compaction slice's\n * inherited retry (re-arming the `$compact` retry timer), or — when retry is\n * exhausted / absent — PROCEED WITHOUT COMPACTING: flip `awaiting` back to\n * `llm` and fire the brain call on the (un-compacted) transcript. Compaction is\n * an OPTIMIZATION, not correctness: a failed summarize must not wedge or fail\n * the whole run (errors are data). This is the chosen option of design B1's\n * `compact_err` fork — it is strictly weaker than failing the run, and the\n * brain call's OWN resilient retry / the deadline watchdog still bound the\n * un-compacted continuation. A consumer that wants compaction failure to be\n * terminal can detect it on the `compaction` slice's `failed` phase. PURE.\n */\n function compactErr(\n s: State,\n key: string,\n msg: AgentCompactErrMsg,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [compaction, cmds] = compact.fail(s.compaction, key, {\n type: MsgType.ResilientErr,\n key: msg.key,\n error: msg.error,\n at: msg.at,\n });\n const settledRetry: State = { ...s, compaction };\n const call = compaction.calls[key];\n\n // A retry is armed (`waiting_retry`) → not terminal → keep awaiting the\n // re-issued compaction call (the re-keyed run Cmd, if any, rides here).\n if (call?.phase === \"waiting_retry\") {\n return [settledRetry, cmds];\n }\n\n // Stale settle (run settled, or advanced/rebooted past this compaction).\n // Past the `waiting_retry` guard `fail` emits no run Cmd, so `cmds` is empty.\n const conv = requireAwaiting(settledRetry, \"compacting\");\n if (conv === null) return [settledRetry, cmds];\n\n // Exhausted retry (or no retry) → proceed WITHOUT compacting: drop the\n // `compacting` state, fire the next brain call on the un-compacted transcript.\n const resumedConv: Conversation<R> = { ...conv, awaiting: { kind: \"llm\" } };\n const [fired, llmCmds] = fireBrainCall(\n { ...settledRetry, conversation: resumedConv },\n at,\n );\n return [fired, [...cmds, ...llmCmds]];\n }\n\n // === Verb: onTimer =======================================================\n\n /**\n * A timer fired — disambiguated by Sub id across the composed bricks:\n *\n * - a `monitored:safety:*` id → the no-progress watchdog → fail the run via\n * the inherited monitored-run `onDeadline`.\n * - a `resilient:*:$compact` id → a COMPACTION retry/deadline timer →\n * re-run the compaction call via the compaction slice's `onTimer`, re-keying\n * its re-issued `resilient_run` to the dedicated `compact_run` (#85).\n * - any other `resilient:*` id → a brain-call retry timer → re-run the brain\n * call via the inherited llm-call `onTimer`.\n *\n * Each brick `onTimer` / `onDeadline` verb tolerates a stale fire for another's\n * id (it no-ops on a non-matching id), so the routing is by id prefix/suffix.\n * PURE.\n */\n function onTimer(\n s: State,\n msg: AgentTimerMsg,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n if (msg.id.startsWith(\"monitored:\")) {\n const [runSlice] = run.onDeadline(s.run, msg);\n return [{ ...s, run: runSlice }, []];\n }\n // The compaction slice's timers are keyed on the reserved `$compact` purpose\n // (`resilient:retry:$compact` / `resilient:deadline:$compact`), distinct from\n // every brain purpose, so the suffix routes the fire to the right slice.\n if (msg.id.endsWith(`:${COMPACTION_PURPOSE}`)) {\n const [compaction, cmds] = compact.onTimer(s.compaction, msg);\n return [{ ...s, compaction }, cmds];\n }\n const [resilience, cmds] = llm.onTimer(s.resilience, msg);\n return [{ ...s, resilience }, cmds];\n }\n\n // === Verb: boot ==========================================================\n\n /**\n * Resume after a reload (cold wake) — the seed's boot reconcile, generalized.\n * Re-seeds the watchdog clock to `at` (a cold wake is not a no-progress wedge)\n * via monitored-run `boot`, then RE-EMITS the ONE outstanding effect derived\n * from `phase × awaiting`:\n *\n * - awaiting `llm` → re-fire the current stage's brain call (idempotent:\n * had the response been processed, the durable Model would already have\n * advanced + persisted, so boot re-emits the NEXT effect).\n * - awaiting `tools` → re-fire every in-flight tool Cmd (idempotent via\n * `callId` — the consumer's tool runner dedupes a re-issued call).\n * - awaiting `compacting` → re-fire the in-flight compaction call (#85),\n * idempotent at the compaction slice's gate exactly like the brain call.\n * - no conversation (between stages / settled) → no effect.\n *\n * A no-op on a settled run. PURE.\n */\n function boot(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice] = run.boot(s.run, at);\n const rebooted: State = { ...s, run: runSlice };\n if (isSettled(rebooted)) return [rebooted, []];\n\n const conv = rebooted.conversation;\n if (conv === null) return [rebooted, []];\n\n if (conv.awaiting.kind === \"llm\") {\n // Re-fire the brain call. The resilient slice already tracks it `running`;\n // re-issuing the same key is idempotent at the gate (re-emits the run Cmd).\n return fireBrainCall(rebooted, at);\n }\n\n if (conv.awaiting.kind === \"compacting\") {\n // Re-fire the in-flight compaction round-trip (#85). The compaction slice\n // already tracks `$compact` running; re-issuing the same key is idempotent\n // at the gate, and the re-emitted `resilient_run` is re-keyed to `compact_run`.\n const input = compactionCall(conv, conv.awaiting.folding);\n const [compaction, cmds] = compact.attempt(\n rebooted.compaction,\n COMPACTION_PURPOSE,\n input,\n at,\n );\n return [{ ...rebooted, compaction }, cmds];\n }\n\n // awaiting tools → re-fire every running tool's effect Cmd.\n const cmds = rebooted.tools.running.map((call) => config.toolOf(call));\n return [rebooted, cmds];\n }\n\n // === Subs ================================================================\n\n /**\n * The merged subscription set — the brain-call retry timers (`../llm-call`),\n * the COMPACTION retry timers (the dedicated `$compact` slice, #85), and the\n * no-progress safety deadline (`../monitored-run`). All are `DeadlineSub`s\n * reconciled by id (the compaction timers are keyed `resilient:*:$compact`,\n * distinct from every brain timer), wired with one `subscribe: { deadline:\n * subscribeDeadline }` cell. PURE.\n */\n function subs(s: State): readonly DeadlineSub[] {\n return [\n ...llm.subs(s.resilience),\n ...compactRc.subs(s.compaction),\n ...run.subs(s.run),\n ];\n }\n\n // === Handlers ============================================================\n\n /**\n * The brain-call interpret handler — DETACHED, inherited from `../llm-call`.\n * It assembles messages, binds the purpose schema, invokes (retry composed),\n * parses, and dispatches the consumer's `onOk` / `onErr` Msg (carrying the\n * parsed `AgentTurn` for `onOk`).\n *\n * UNSAFE — kept ONLY as a deliberate escape hatch for the consumer that wires\n * the verbs by hand and wants the fire-and-forget dispatch shape. It does NOT\n * drive the inherited retry loop (it never re-enters the `resilient_ok` settle\n * Msg, so `succeed` / `fail` never run — the breaker never closes, the retry\n * counter never resets). The `unsafe` prefix is the warning the name carries:\n * `toMachine` is THE wired path (it uses the FIXED `brainHandlers` below, which\n * returns the settle Msg for re-entry and drives the loop correctly), and this\n * detached form is named `unsafeDetachedHandlers` so the broken-by-design\n * behaviour is visible at the call site, not buried in a doc-comment a consumer\n * meets only after autocomplete already offered it. A consumer reaches for it\n * only when it has accepted owning the retry wiring itself. See llm-call's\n * `handlers` doc (the same retry-loop gap).\n *\n * Returns the inherited detached shape verbatim (`AgentDetachedHandlers`) — a\n * fire-and-forget `resilient_run` cell, NOT an `Interpret` (it returns `void`\n * and takes the structural `{ waitUntil, dispatch }` ctx the detached form\n * runs the invoke against). The type is named precisely so no cast launders a\n * `void`-returning cell into the re-entry `Interpret` contract.\n *\n * The per-tool effects are NOT handled here — `config.toolOf` produces a Cmd\n * the consumer's OWN interpret performs (the agent never owns the tool I/O;\n * the seed's `send_tool_call` handler is the consumer's), routing Ok/Err back\n * to `toolOk` / `toolErr`. This matches fan-out's \"the consumer owns `of`'s\n * interpret\" discipline.\n */\n function unsafeDetachedHandlers<M>(\n ports: AgentPorts<P, O, M>,\n ): AgentDetachedHandlers<P, M> {\n return llm.handlers(ports);\n }\n\n /**\n * The FIXED brain-call interpret handler — the no-arg `../llm-call` form that\n * RETURNS the enriched resilient settle Msg (`resilient_ok` carrying the\n * parsed `LlmOk`, or `resilient_err` carrying the typed `LlmErr`). The\n * substrate enqueues an interpret handler's returned Msg as a FOLLOW-UP\n * (re-entry) onto the dispatch tail, so the machine's `resilient_ok` /\n * `resilient_err` reducer arms run `succeed` / `fail`, advancing the inherited\n * retry loop (succeed/fail → backoff → onTimer → re-issue) AND folding the\n * parsed turn into the conversation. This is the wiring that lets the loop\n * reach a clean terminal `done` with a reset retry slice — the headline L3 fix.\n */\n function brainHandlers<Ctx>(): Interpret<\n LlmSucceedMsg<P, O> | LlmFailMsg<P>,\n AgentLlmRunCmd<P>,\n Ctx\n > {\n // `llm.handlers()` is `{ resilient_run: (cmd: LlmRunCmd<P>) => Promise<\n // LlmSucceedMsg<P,O> | LlmFailMsg<P>> }`. That is structurally an\n // `Interpret` over the single `resilient_run` Cmd: the cell may ignore the\n // `ctx` param (a handler taking fewer args is assignable), and its returned\n // settle Msg is the exact `M` subset. No cast — the precise type holds.\n return llm.handlers();\n }\n\n /**\n * Wire the agent into a single runnable `defineMachine`. The host Msg union is\n * the closed set of verb entry points; `update` routes each to the matching\n * verb, `subscriptions` merges the two bricks' subs, `subscribe` wires the one\n * deadline cell, and `interpret` is the FIXED brain-call handler.\n *\n * The brain call uses the FIXED no-arg `../llm-call` handler (`brainHandlers`):\n * its returned `resilient_ok` / `resilient_err` settle Msg RE-ENTERS the\n * reducer, where the `resilient_ok` arm runs `succeed` (reset retry + close\n * breaker + fold the parsed turn) and the `resilient_err` arm runs `fail`\n * (back off via retry, re-arm the timer). This is what drives the loop to a\n * clean terminal `done` with a reset retry slice — fixing the L3 break where\n * the old detached handler dispatched the turn directly, never re-entered the\n * settle Msg, and so `succeed` never ran (stuck `running`, accumulating retry).\n *\n * The consumer supplies only the per-tool interpret (the agent owns the brain\n * interpret now; no `ports` to supply — the parsed turn is folded by `succeed`,\n * not by a consumer-built Msg).\n *\n * `HostMsg` is fixed to the agent's own verb-driven Msg union so the machine\n * is self-contained; a consumer needing extra Msgs wires the verbs by hand\n * instead (the knob contract is the escape hatch).\n */\n function toMachine<Ctx = object>(opts?: {\n /**\n * The consumer's interpret for the non-brain Cmds — the per-tool effect\n * `TC`, plus (ONLY when checkpointing is configured) the monitored-run\n * `snapshot_write` checkpoint cell. The brain `resilient_run` cell the agent\n * owns is merged in below, so the consumer supplies only the rest of the\n * config-derived `AgentCmd<P, TC, Snap>` union.\n *\n * The snapshot obligation is CONFIG-DERIVED (#55): `SnapshotInterpret`\n * resolves to a REQUIRED `snapshot_write` cell when `config.snapshotEvery`\n * is set (a real checkpoint write MUST be wired — never a silent no-op), and\n * to `{ snapshot_write?: never }` (the cell is FORBIDDEN — it can never fire)\n * when checkpointing is off. There is no default no-op: a non-checkpointing\n * consumer cannot even mention `snapshot_write`, and a checkpointing one must.\n */\n readonly toolInterpret?: Interpret<AgentMachineMsg<P, O, R>, TC, Ctx> &\n SnapshotInterpret<AgentMachineMsg<P, O, R>, boolean, Ctx> &\n CompactInterpret<AgentMachineMsg<P, O, R>, boolean, Ctx>;\n }): Machine<\n State,\n AgentMachineMsg<P, O, R>,\n AgentCmd<P, TC, boolean, boolean>,\n DeadlineSub,\n Ctx\n > {\n type M = AgentMachineMsg<P, O, R>;\n // The implementation is typed at `Snap = boolean` — the SUPERSET that\n // always includes the monitored-run checkpoint Cmd; the public OVERLOADS\n // narrow it to `true` / `false` and hand the consumer the precise obligation\n // (#55). `NonBrainCmd` is the consumer's per-tool `TC` plus that checkpoint\n // Cmd, and `ACmd` unions it with the brain Cmd — fully concrete (no pending\n // conditional), union-equal to `AgentCmd<P, TC, boolean>`, and built from the\n // SAME pieces `mergeInterpret` joins so the merge result is syntactically\n // `Interpret<M, ACmd, Ctx>` with no `Exclude`/conditional TS refuses to reduce.\n // `NonBrainCmd` is the consumer's half of the merged interpret — the per-tool\n // `TC`, the monitored-run checkpoint Cmd, AND the compaction `compact_run`\n // Cmd (#85). The consumer owns the `compact_run` cell (the summarize I/O,\n // returning `compact_ok` / `compact_err` for re-entry), exactly as it owns the\n // tool cells; the agent owns only the retry ORCHESTRATION (the slice verbs).\n // At `boolean` this is the SUPERSET; the overloads config-derive `compact_run`\n // IN (policy) or OUT (`{ compact_run?: never }`) of the obligation (#55 reuse).\n type NonBrainCmd = TC | MonitoredRunCmd<unknown> | AgentCompactRunCmd;\n type ACmd = AgentLlmRunCmd<P> | NonBrainCmd;\n // The FIXED brain handler returns the settle Msg for re-entry; the substrate\n // enqueues it as a follow-up dispatched back into `update` (the `resilient_*`\n // arms below). It is PRECISELY an `Interpret` over the brain Cmd\n // (`AgentLlmRunCmd<P>`); the consumer's `toolInterpret` is PRECISELY an\n // `Interpret` over the rest of the config-derived union (`TC`, and\n // `snapshot_write` only when snapshotting). `mergeInterpret` joins the two\n // disjoint halves into the full `Interpret<M, ACmd, Ctx>` — each key maps\n // precisely (`resilient_run` → the brain cell, `TC[\"type\"]` / `snapshot_write`\n // → the consumer's cells), with the one sound mapped-type identity isolated in\n // the helper rather than laundered through `as unknown as` here.\n //\n // No no-op `snapshot_write` default: with checkpointing off `SnapCmd` is\n // `never`, so the Cmd is config-derived OUT of `ACmd`, the consumer never\n // wires it, and the monitored-run slice never emits it — the\n // `snapshot_write: async () => undefined` ceremony (and the type lie it\n // masked) is gone (#55).\n const consumerInterpret = (opts?.toolInterpret ?? {}) as Interpret<\n M,\n NonBrainCmd,\n Ctx\n >;\n const interpret: Interpret<M, ACmd, Ctx> = mergeInterpret<\n M,\n NonBrainCmd,\n AgentLlmRunCmd<P>,\n Ctx\n >(consumerInterpret, brainHandlers<Ctx>());\n\n // Type the dispatch table explicitly so each cell gets its narrowed Msg\n // and the Reducer-form overload of `defineMachine` matches cleanly (the\n // agent State is not a discriminated union, so the Transitions overload's\n // `update` field collapses to `never` and would otherwise mask inference).\n // The verbs return `AgentCmd<P, TC>` — the `Snap = true` superset, because\n // they FORWARD whatever monitored-run emits and the verbs are not themselves\n // config-typed. The machine declares the config-derived `ACmd`; the one\n // narrowing (`update` below) is SOUND because a non-snapshotting run's\n // monitored-run slice provably never emits a `snapshot_write` Cmd, so the\n // forwarded array never carries the variant `ACmd` excludes.\n const update: Reducer<State, M, AgentCmd<P, TC>> = {\n [MsgType.AgentStart]: (s, m) => start(s, m.runId, m.at),\n [MsgType.AgentToolOk]: (s, m) => toolOk(s, m.callId, m.result, m.at),\n [MsgType.AgentToolErr]: (s, m) => toolErr(s, m.callId, m.reason, m.at),\n // The re-entered brain-call settle Msgs (from `brainHandlers`): success\n // runs `succeed` (reset retry + fold the turn), failure runs `fail`.\n [MsgType.ResilientOk]: (s, m) => succeed(s, m.key, m, m.at),\n [MsgType.ResilientErr]: (s, m) => fail(s, m.key, m, m.at),\n // The re-entered compaction settle Msgs (from the consumer's `compact_run`\n // cell, #85): `compact_ok` folds the summary back (drop oldest turns +\n // their records, fire the next brain call), `compact_err` backs off via the\n // compaction retry or proceeds without compacting.\n [MsgType.CompactOk]: (s, m) => compactOk(s, m.key, m, m.at),\n [MsgType.CompactErr]: (s, m) => compactErr(s, m.key, m, m.at),\n deadline_exceeded: (s, m) => onTimer(s, m),\n [MsgType.AgentBoot]: (s, m) => boot(s, m.at),\n };\n\n // Build the machine as a fully-typed `Machine<...>` const, then pass it\n // through `defineMachine`'s identity. Annotating the const resolves the\n // `Machine` type's conditional `interpret` requirement against the concrete\n // type params here; calling `defineMachine` with explicit type args instead\n // would defer that conditional over the generic `TC` and fail the overload.\n //\n // The machine's Cmd type is the config-derived `ACmd`. `update` is the\n // `AgentCmd<P, TC>` superset reducer; narrowing it to `Reducer<State, M,\n // ACmd>` is the SINGLE sound assertion of the snapshot derivation — a\n // non-snapshotting run never emits the `MonitoredRunCmd` variant `ACmd`\n // drops, so the reducer's emitted arrays provably stay within `ACmd[]`. This\n // is the same shape as `mergeInterpret`'s one sound mapped-type identity: the\n // soundness lives in a documented seam, not smuggled at every verb.\n const machine: Machine<State, M, ACmd, DeadlineSub, Ctx> = {\n init: (loaded) => (loaded !== null ? [loaded, []] : [init(), []]),\n update: update as Reducer<State, M, ACmd>,\n subscriptions: (s) => subs(s),\n subscribe: { deadline: subscribeDeadline },\n interpret,\n };\n return defineMachine(machine);\n }\n\n return {\n init,\n start,\n turn,\n toolOk,\n toolErr,\n succeed,\n fail,\n compactOk,\n compactErr,\n onTimer,\n boot,\n isSettled,\n currentStage,\n brainCall,\n subs,\n // `toMachine` is THE wired path. `unsafeDetachedHandlers` is the\n // hand-wiring escape hatch — named to advertise the retry-loop gap so it is\n // never mistaken for the loop driver (#54).\n toMachine,\n unsafeDetachedHandlers,\n };\n}\n\n/**\n * Re-export the deadline Sub primitives so consumers (and tests) wire one\n * import: `subscribeDeadline` is the `subscribe` cell, `deadlineSub` builds the\n * Sub literal both composed bricks' `subs` emit.\n */\nexport { subscribeDeadline, deadlineSub };\nexport type {\n LlmCall,\n LlmErr,\n LlmFailMsg,\n LlmOk,\n LlmRunCmd,\n LlmSucceedMsg,\n MessageLoader,\n ModelFactory,\n Schema,\n} from \"../llm-call\";\nexport type {\n DeadlineSub,\n MonitoredRunCmd,\n RunFailure,\n} from \"../monitored-run\";\n"]}
1
+ {"version":3,"sources":["../src/agent/schema.ts","../src/agent/compaction.ts","../src/agent/internal.ts","../src/agent/machine.ts","../src/agent/types.ts","../src/agent/index.ts"],"names":["runSlice","cmds"],"mappings":"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","file":"chunk-KEFMI24G.js","sourcesContent":["/**\n * @demlik/tea/agent — internal structured-output schema helper.\n *\n * NOT part of the public `./agent` barrel: `schemaFromGuard` is the shared\n * zod-style `parse` throw-wrapper the two owned structured-output schemas\n * (`agentTurnSchema`, `compactionSummarySchema`) are built from. It lives in its\n * own module so both `types.ts` and `compaction.ts` can import it without either\n * re-exporting it (the barrel `index.ts` never re-exports this file, so the\n * helper stays internal).\n */\n\nimport type { Schema } from \"../llm-call\";\n\n/**\n * Build a `Schema<T>` from a type guard — the zod-style `parse` throw-wrapper the\n * llm-call handler relies on, factored so tea's two owned structured-output\n * schemas ({@link agentTurnSchema}, {@link compactionSummarySchema}) share one\n * shape. On a\n * value the guard rejects it throws `structured-output parse failed: not <name>`\n * (a `*_err` at the boundary — errors are data); otherwise it narrows through.\n * `name` is the full noun phrase incl. article (\"an AgentTurn\").\n */\nexport function schemaFromGuard<T>(\n guard: (value: unknown) => value is T,\n name: string,\n): Schema<T> {\n return {\n parse: (value: unknown): T => {\n if (!guard(value)) {\n throw new Error(`structured-output parse failed: not ${name}`);\n }\n return value;\n },\n };\n}\n","/**\n * @demlik/tea/agent — the context-compaction seam (#85).\n *\n * The opt-in transcript snapshot-and-compact policy, shaped exactly like\n * `AgentSnapshotConfig` (see `./types`) so a short agent pays nothing and cannot\n * even mention the machinery. This module owns the whole `$compact` vocabulary:\n * the reserved purpose, the summary schema, the consumer policy, the config\n * discriminant, and the dedicated `compact_run` / `compact_ok` / `compact_err`\n * Cmd + Msgs re-keyed off the composed resilient call at the agent boundary.\n */\n\nimport type { Cmd, Interpret } from \"../index\";\nimport type {\n LlmCall,\n LlmErr,\n LlmOk,\n MessageLoader,\n Schema,\n} from \"../llm-call\";\nimport type { MsgType } from \"../protocol\";\nimport { schemaFromGuard } from \"./schema\";\nimport type { Conversation } from \"./types\";\n\n/**\n * The reserved purpose the compaction round-trip runs under (#85). Compaction\n * is a DEDICATED resilient LLM call (design B1), NOT one of the consumer's brain\n * purposes `P` — so it carries its own purpose literal, kept in the agent's\n * private `$`-namespace (the same reserved-namespace discipline `with-resilience`\n * uses) so it never collides with a consumer purpose. A consumer never names it.\n */\nexport type CompactionPurpose = \"$compact\";\n\n/** The reserved compaction purpose's value — the single in-flight summarize call's key. */\nexport const COMPACTION_PURPOSE: CompactionPurpose = \"$compact\";\n\n/**\n * The purpose→output map for the compaction LLM call — the single reserved\n * `$compact` purpose mapping to a {@link CompactionSummary}. Mirrors the brain\n * call's `O` map, scoped to the one compaction purpose, so the composed\n * `createLlmCall` parses the summarize output under the same structured-output\n * contract the brain call uses.\n */\nexport interface CompactionOutputs extends Record<CompactionPurpose, unknown> {\n readonly $compact: CompactionSummary;\n}\n\n/**\n * Narrow an unknown to a {@link CompactionSummary} — the runtime witness for the\n * compaction call's structured output. Checks the one load-bearing field\n * (`summary` is a string). PURE — allocates no Error.\n */\nexport function isCompactionSummary(\n value: unknown,\n): value is CompactionSummary {\n if (value === null || typeof value !== \"object\") return false;\n return typeof (value as { summary?: unknown }).summary === \"string\";\n}\n\n/**\n * The `Schema<CompactionSummary>` the compaction call binds — tea's own parse\n * target for the summarize round-trip (it OWNS the `$compact` purpose's output).\n * Throws on a non-summary (the zod-style `parse` contract the llm-call handler\n * relies on), so a malformed summary is a `compact_err` (errors are data), never\n * a corrupt fold-back.\n */\nexport const compactionSummarySchema: Schema<CompactionSummary> =\n schemaFromGuard(isCompactionSummary, \"a CompactionSummary\");\n\n/**\n * The result a compaction round-trip produces — the model's summary of the\n * folded-away turns. Tea OWNS this shape (the `$compact` purpose's output): the\n * fold-back (`compact_ok`) writes `summary` into a synthetic head `AgentTurn`\n * (design A1), so a consumer's `loadMessages` reads it as a normal turn with no\n * watermark to learn. Generic-free — the summary is always plain text.\n */\nexport interface CompactionSummary {\n /** The model's summary of the folded-away (oldest) turns + their tool records. */\n readonly summary: string;\n}\n\n/**\n * The consumer's compaction policy (#85). One PURE trigger; the impure\n * summarize round-trip is composed by the agent (a dedicated resilient LLM call\n * under the reserved `$compact` purpose, inheriting retry/backoff — design B1),\n * so the policy never reaches the model itself.\n *\n * - `planCompaction` — PURE: given the live conversation ABOUT to fire a brain\n * call, return how many of the OLDEST turns to fold into a summary, or `0`\n * to skip. No clock, no RNG → replay re-decides identically (design D). A\n * char-length / turn-count / real deterministic-tokenizer heuristic all\n * qualify. Returning `>= turns.length` is clamped to \"fold all but keep the\n * loop alive\" by the trigger (it never folds the turn currently in flight).\n * - `payloadOf` — build the per-call prompt payload the compaction\n * `MessageLoader` reads (the turns being folded). Omit → `null` (the loader,\n * if any, reads the conversation off the agent's own state). Opaque to the\n * agent, exactly like the brain call's `payloadOf`.\n */\nexport interface CompactionPolicy<R, Msg = unknown> {\n /** PURE trigger: how many OLDEST turns to fold (`0` = skip). No clock/RNG. */\n readonly planCompaction: (conversation: Conversation<R>) => number;\n /** Build the summarize call's prompt payload from the turns being folded. Omit → `null`. */\n readonly payloadOf?: (\n conversation: Conversation<R>,\n folding: number,\n ) => unknown;\n /** DI port — the SDK / message loader for the summarize call. Omit → invoke with `[]`. */\n readonly loadMessages?: MessageLoader<CompactionPurpose, Msg>;\n}\n\n/**\n * The compaction discriminant (#85), shaped exactly like {@link\n * AgentSnapshotConfig}. Compaction is either OFF —\n * `compaction` is structurally absent and the agent never emits a `compact_run`\n * Cmd — or ON, in which case `compaction` is a {@link CompactionPolicy}. A `{\n * compaction?: never }` member (rather than a bare optional) makes the OFF case\n * load-bearing: it forbids passing `compaction` at all, so `toMachine`\n * config-derives whether the `compact_run` interpret cell is REQUIRED (ON) or\n * FORBIDDEN (OFF) — never a silent no-op cell, the #55 type-lie-killer reused.\n */\nexport type AgentCompactionConfig<R, Msg> =\n | { readonly compaction?: never }\n | { readonly compaction: CompactionPolicy<R, Msg> };\n\n/**\n * The \"summarize the oldest N turns\" effect Cmd — the compaction round-trip's\n * carrier (#85). It mirrors the brain `resilient_run` Cmd's shape (a `key` + the\n * plain `LlmCall<CompactionPurpose>` input, no closures) but under the dedicated\n * `compact_run` discriminant so it routes to the compaction interpret cell, not\n * the brain one. The cell composes the resilient brick (retry/backoff) and\n * returns the re-keyed `compact_ok` / `compact_err` settle for re-entry.\n */\nexport type AgentCompactRunCmd = Cmd<typeof MsgType.CompactRun> & {\n readonly key: CompactionPurpose;\n readonly input: LlmCall<CompactionPurpose>;\n};\n\n/** The compaction round-trip success settle Msg — carries the parsed {@link CompactionSummary}. */\nexport type AgentCompactOkMsg = {\n readonly type: typeof MsgType.CompactOk;\n readonly key: CompactionPurpose;\n readonly result: LlmOk<CompactionPurpose, CompactionOutputs>;\n readonly at: number;\n};\n\n/** The compaction round-trip failure settle Msg — carries the typed {@link LlmErr}. */\nexport type AgentCompactErrMsg = {\n readonly type: typeof MsgType.CompactErr;\n readonly key: CompactionPurpose;\n readonly error: LlmErr<CompactionPurpose>;\n readonly at: number;\n};\n\n/**\n * The CONFIG-DERIVED compaction obligation on `toMachine`'s `toolInterpret`\n * (#85), the exact twin of {@link SnapshotInterpret}.\n * Resolves on the `Compact` discriminant the compaction overload of\n * `createAgent` fixes:\n *\n * - compaction ON → a REQUIRED `compact_run` cell\n * (`Interpret<M, AgentCompactRunCmd, Ctx>`). The summarize round-trip MUST be\n * wired — the agent never defaults it to a no-op.\n * - compaction OFF → `{ compact_run?: never }`. The cell is FORBIDDEN: with no\n * policy the agent never emits a `compact_run` Cmd, so wiring it would be\n * dead code. The consumer cannot even mention `compact_run`.\n *\n * Same type-lie-killer as the snapshot derivation: the obligation is present\n * EXACTLY when the Cmd can fire, never as a silent gap the agent backfills.\n */\nexport type CompactInterpret<\n M extends { type: string },\n Compact extends boolean,\n Ctx,\n> = Compact extends true\n ? Interpret<M, AgentCompactRunCmd, Ctx>\n : { readonly compact_run?: never };\n","/**\n * @demlik/tea/agent — the closure-free PURE reducer helpers.\n *\n * NOT part of the public `./agent` barrel: these are the reducer core's pure\n * conversation / state operations, factored OUT of the `createAgent` closure so\n * the factory module holds only the verbs that genuinely close over the composed\n * bricks (`run` / `llm` / `fan` / `compactRc` / `config`). Each function here is\n * pure and generic over the same `Stage / P / O / R` params the closure fixes,\n * so the call sites inside `createAgent` read identically (TS infers the params\n * from the state argument). The barrel `index.ts` never re-exports this file, so\n * everything stays internal.\n */\n\nimport type { LlmRunCmd } from \"../llm-call\";\nimport { MsgType } from \"../protocol\";\nimport type { AgentCompactRunCmd, CompactionPurpose } from \"./compaction\";\nimport { COMPACTION_PURPOSE } from \"./compaction\";\nimport type {\n AgentState,\n AgentTurn,\n Awaiting,\n Conversation,\n ToolCall,\n} from \"./types\";\n\n/** The narrowed `awaiting` variant for a given `kind`. */\nexport type AwaitingOf<K extends Awaiting[\"kind\"]> = Extract<\n Awaiting,\n { kind: K }\n>;\n\n/** A fresh conversation entering the agentic loop — awaiting the first brain call. */\nexport function freshConversation<R>(): Conversation<R> {\n return {\n turns: [],\n toolRecords: [],\n turnCount: 0,\n awaiting: { kind: \"llm\" },\n };\n}\n\n/**\n * Collapse a turn's tool calls to one per `callId` (first occurrence wins).\n * `callId` is the fan-out identity (`idOf`); duplicates in one batch are a\n * model defect that, un-deduped, would double-execute the tool and wedge the\n * batch (one settle Msg cannot close two same-id `running` entries). PURE —\n * preserves order, allocates no Error.\n */\nexport function dedupeByCallId(\n calls: readonly ToolCall[],\n): readonly ToolCall[] {\n const seen = new Set<string>();\n const out: ToolCall[] = [];\n for (const call of calls) {\n if (seen.has(call.callId)) continue;\n seen.add(call.callId);\n out.push(call);\n }\n return out;\n}\n\n/**\n * Fold the oldest `folding` turns of a conversation into a single synthetic\n * `summaryTurn` (#85, design A1) — PURE. The summary becomes the new head turn\n * (index 0); the surviving turns (`turns.slice(folding)`) follow. Every tool\n * record whose producing turn was folded (`turn < folding`) is DROPPED; each\n * survivor's `turn` is RE-INDEXED by `-folding + 1` so it still equals the new\n * index in `turns` of its producing turn (the summary occupies one slot where\n * `folding` turns stood, so survivors shift left by `folding` then right by 1).\n * `turnCount` is UNCHANGED — compaction is not a model round-trip (decision C).\n *\n * Caller guarantees `2 <= folding <= turns.length` (the trigger clamps + skips\n * `< 2`), so the result is strictly shorter (`length - folding + 1`).\n */\nexport function foldSummary<R>(\n conv: Conversation<R>,\n folding: number,\n summaryTurn: AgentTurn,\n): Conversation<R> {\n const shift = folding - 1; // survivors move left by this many slots.\n const survivingTurns = conv.turns.slice(folding);\n const survivingRecords = conv.toolRecords\n .filter((rec) => rec.turn >= folding)\n .map((rec) => ({ ...rec, turn: rec.turn - shift }));\n return {\n ...conv,\n turns: [summaryTurn, ...survivingTurns],\n toolRecords: survivingRecords,\n awaiting: { kind: \"llm\" },\n };\n}\n\n/** The current pipeline stage value (`undefined` for a single-shot run). */\nexport function currentStage<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): Stage | undefined {\n return s.run.stepStates.find((i) => i.status === \"running\")?.input;\n}\n\n/** True iff the run is in a terminal state (monitored-run done/failed, or agent failure). */\nexport function isSettled<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): boolean {\n return (\n s.run.phase === \"done\" || s.run.phase === \"failed\" || s.failure !== null\n );\n}\n\n/**\n * The stale-settle guard shared by the awaiting-scoped verbs (`turn` /\n * `settleTool` / `compactOk` / `compactErr`): return the live conversation\n * ALREADY narrowed to the given `awaiting.kind`, or `null` when the verb must\n * no-op — the run is settled, there is no conversation, or it is awaiting\n * something else (a stale settle after boot / advance). Collapses the\n * `isSettled → conv === null → awaiting.kind` triple that recurred verbatim\n * across the four verbs; each caller supplies its own no-op return. PURE.\n */\nexport function requireAwaiting<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n K extends Awaiting[\"kind\"],\n>(\n s: AgentState<Stage, P, O, R>,\n kind: K,\n): (Conversation<R> & { readonly awaiting: AwaitingOf<K> }) | null {\n if (isSettled(s)) return null;\n const conv = s.conversation;\n if (conv === null || conv.awaiting.kind !== kind) return null;\n return conv as Conversation<R> & { readonly awaiting: AwaitingOf<K> };\n}\n\n/** Re-key a composed compaction `resilient_run` Cmd to the dedicated `compact_run`. */\nexport function toCompactRunCmd(\n cmd: LlmRunCmd<CompactionPurpose>,\n): AgentCompactRunCmd {\n return {\n type: MsgType.CompactRun,\n key: COMPACTION_PURPOSE,\n input: cmd.input,\n };\n}\n","/**\n * @demlik/tea/agent — the wired-machine surface.\n *\n * The Cmd / Msg vocabulary the knob speaks, the knob interface `createAgent`\n * returns (`AgentKnob` / `AgentToMachine`), the do↔agent boot port, the\n * semantic lifecycle event stream + its projector (`agentEvents`), and the two\n * pure wiring helpers `mergeInterpret` / `liftAgent`. The reducer core (the\n * `createAgent` factory that implements this surface) lives in `./index`.\n */\n\nimport type { Cmd, Interpret, Machine } from \"../index\";\nimport type {\n LlmCall,\n LlmCallPorts,\n LlmFailMsg,\n LlmRunCmd,\n LlmSucceedMsg,\n LlmTimerMsg,\n} from \"../llm-call\";\nimport type { DeadlineSub, MonitoredRunCmd } from \"../monitored-run\";\nimport { MsgType } from \"../protocol\";\nimport type {\n AgentCompactErrMsg,\n AgentCompactOkMsg,\n AgentCompactRunCmd,\n CompactInterpret,\n} from \"./compaction\";\nimport type { AgentState, AgentTurn } from \"./types\";\n\n// ===========================================================================\n// Cmds + Msgs the knob speaks. Generic over the composed bricks' shapes.\n// ===========================================================================\n\n/** The brain-call effect Cmd, inherited from `../llm-call`. */\nexport type AgentLlmRunCmd<P extends string> = LlmRunCmd<P>;\n\n/**\n * The Cmd union the agent emits, as a CLOSED discriminated union (precise `TC`,\n * not the open `Cmd`) so `Interpret<M, AgentCmd<P, TC>, Ctx>` maps each key\n * precisely and `toMachine` merges the interpret halves with no laundering cast:\n *\n * - `AgentLlmRunCmd<P>` — the brain-call run Cmd (`resilient_run`), folded\n * by the wired `brainHandlers` cell.\n * - `MonitoredRunCmd<unknown>` — the durable checkpoint write the monitored-run\n * slice emits, present in the union ONLY when\n * checkpointing is on (`Snap = true`). With\n * checkpointing off the monitored-run slice never\n * emits a `snapshot_write` Cmd, so it is config-derived\n * OUT of the emitted set — the consumer is never asked\n * to interpret a Cmd that can never fire (#55).\n * - `TC` — the consumer's per-tool effect, mapped to the\n * consumer's own tool interpret cell.\n *\n * `Snap` defaults to `true` so the verb-internal usage (which forwards whatever\n * monitored-run emits) and the published type stay a safe superset; the wired\n * machine `toMachine` returns is parametrized on the overload-fixed `Snap` so its\n * Cmd set is exact (`MonitoredRunCmd` present only when checkpointing is on).\n */\nexport type AgentCmd<\n P extends string,\n TC extends Cmd = Cmd,\n Snap extends boolean = true,\n Compact extends boolean = true,\n> =\n | AgentLlmRunCmd<P>\n | (Snap extends true ? MonitoredRunCmd<unknown> : never)\n | (Compact extends true ? AgentCompactRunCmd : never)\n | TC;\n\n/**\n * The CONFIG-DERIVED snapshot obligation on `toMachine`'s `toolInterpret` (#55).\n * Resolves on the `Snap` discriminant the snapshotting overload of `createAgent`\n * fixes (`true` checkpointing-on / `false` off):\n *\n * - checkpointing ON → a REQUIRED `snapshot_write` cell\n * (`Interpret<M, MonitoredRunCmd<unknown>, Ctx>`). A real checkpoint write\n * MUST be wired — the agent never defaults it to a no-op.\n * - checkpointing OFF → `{ snapshot_write?: never }`. The cell is FORBIDDEN:\n * the Cmd is config-derived out of the emitted set, so wiring it would be\n * dead code. The consumer cannot even mention `snapshot_write`.\n *\n * This is the type that kills the `snapshot_write: async () => undefined`\n * ceremony: the obligation is present in the contract EXACTLY when the Cmd can\n * fire, never as a silent gap the agent backfills.\n */\nexport type SnapshotInterpret<\n M extends { type: string },\n Snap extends boolean,\n Ctx,\n> = Snap extends true\n ? Interpret<M, MonitoredRunCmd<unknown>, Ctx>\n : { readonly snapshot_write?: never };\n\n/**\n * The `toMachine` signature, parametrized on the `Snap` + `Compact` discriminants\n * so the snapshotting / compaction overloads of `createAgent` hand back the right\n * obligations. The `toolInterpret` requires (ON) or forbids (OFF) the\n * `snapshot_write` cell via {@link SnapshotInterpret} and the `compact_run` cell\n * via {@link CompactInterpret}, and the machine's Cmd type is the config-derived\n * `AgentCmd<P, TC, Snap, Compact>`.\n */\nexport type AgentToMachine<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Snap extends boolean,\n Compact extends boolean,\n> = <Ctx = object>(opts?: {\n readonly toolInterpret?: Interpret<AgentMachineMsg<P, O, R>, TC, Ctx> &\n SnapshotInterpret<AgentMachineMsg<P, O, R>, Snap, Ctx> &\n CompactInterpret<AgentMachineMsg<P, O, R>, Compact, Ctx>;\n}) => Machine<\n AgentState<Stage, P, O, R>,\n AgentMachineMsg<P, O, R>,\n AgentCmd<P, TC, Snap, Compact>,\n DeadlineSub,\n Ctx\n>;\n\n/**\n * The agent knob `createAgent` returns — the uniform verb contract every tea\n * composition exposes, plus the wired `toMachine` and the `unsafeDetachedHandlers`\n * escape hatch. `Snap` flows ONLY into `toMachine`'s `toolInterpret` obligation\n * (the snapshot derivation, #55); every verb is snapshot-agnostic. The model\n * message shape `Msg` does not appear on the knob surface (it is internal to the\n * brain call's loader), so it is not a type parameter here — only `createAgent`\n * carries it, to thread the config's `loadMessages` / `model` ports.\n */\nexport interface AgentKnob<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Snap extends boolean,\n Compact extends boolean,\n> {\n readonly init: () => AgentState<Stage, P, O, R>;\n readonly start: AgentVerb1<Stage, P, O, R, TC, [runId: string, at: number]>;\n readonly turn: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [result: AgentTurn, at: number]\n >;\n readonly toolOk: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [callId: string, result: R, at: number]\n >;\n readonly toolErr: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [callId: string, reason: string, at: number]\n >;\n readonly succeed: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentLlmOkMsg<P, O>, at: number]\n >;\n readonly fail: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentLlmErrMsg<P>, at: number]\n >;\n readonly compactOk: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentCompactOkMsg, at: number]\n >;\n readonly compactErr: AgentVerb1<\n Stage,\n P,\n O,\n R,\n TC,\n [key: string, msg: AgentCompactErrMsg, at: number]\n >;\n readonly onTimer: AgentVerb1<Stage, P, O, R, TC, [msg: AgentTimerMsg]>;\n readonly boot: AgentVerb1<Stage, P, O, R, TC, [at: number]>;\n readonly isSettled: (s: AgentState<Stage, P, O, R>) => boolean;\n readonly currentStage: (s: AgentState<Stage, P, O, R>) => Stage | undefined;\n readonly brainCall: (s: AgentState<Stage, P, O, R>) => LlmCall<P>;\n readonly subs: (s: AgentState<Stage, P, O, R>) => readonly DeadlineSub[];\n readonly toMachine: AgentToMachine<Stage, P, O, R, TC, Snap, Compact>;\n readonly unsafeDetachedHandlers: <M>(\n ports: AgentPorts<P, O, M>,\n ) => AgentDetachedHandlers<P, M>;\n}\n\n/** A verb taking the state + `Args`, returning the knob's `[State, Cmd[]]` tuple. */\ntype AgentVerb1<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd,\n Args extends readonly unknown[],\n> = (\n s: AgentState<Stage, P, O, R>,\n ...args: Args\n) => readonly [AgentState<Stage, P, O, R>, readonly AgentCmd<P, TC>[]];\n\n/** The brain-call success / failure settle Msgs, inherited from `../llm-call`. */\nexport type AgentLlmOkMsg<\n P extends string,\n O extends Record<P, unknown>,\n> = LlmSucceedMsg<P, O>;\nexport type AgentLlmErrMsg<P extends string> = LlmFailMsg<P>;\n\n/**\n * The timer Msg (retry + safety deadline) — `DeadlineExceeded`, the shared\n * shape of both bricks' timer Msgs (`LlmTimerMsg` and `MonitoredRunTimerMsg`\n * are both `DeadlineExceeded`). One Msg variant covers both timers; `onTimer`\n * disambiguates by Sub id. This is also the machine Msg the `subscribeDeadline`\n * cell dispatches directly (no wrapping), matching the sibling gold standard.\n */\nexport type AgentTimerMsg = LlmTimerMsg;\n\n/** Ports the consumer supplies to the llm-call handler — re-exported shape. */\nexport type AgentPorts<\n P extends string,\n O extends Record<P, unknown>,\n M,\n> = LlmCallPorts<P, O, M>;\n\n/**\n * The LEGACY detached brain-call handler dictionary `handlers(ports)` returns —\n * the inherited `../llm-call` detached form's exact shape, NOT an `Interpret`.\n * The `resilient_run` cell runs the invoke inside `ctx.waitUntil` and dispatches\n * the consumer's `onOk` / `onErr` Msg directly (returning `void`), so it is a\n * fire-and-forget handler with a structural `{ waitUntil, dispatch }` ctx — it\n * does not re-enter the resilient settle Msg and so does not drive the retry\n * loop. Naming the type precisely (rather than laundering it through\n * `as unknown as Interpret<...>`) keeps `agent.unsafeDetachedHandlers(ports)` honest: the\n * consumer that wires the verbs by hand gets the real detached shape, and its\n * `resilient_run` is callable with a plain Cmd + a `{ waitUntil, dispatch }` ctx\n * with no `as never` at the call site.\n */\nexport type AgentDetachedHandlers<P extends string, M> = {\n readonly resilient_run: (\n cmd: AgentLlmRunCmd<P>,\n ctx: {\n waitUntil(p: Promise<unknown>): void;\n dispatch(msg: M): unknown;\n },\n ) => void;\n};\n\n// ===========================================================================\n// AgentBootPort — the typed do↔agent boot seam (issue #60).\n// ===========================================================================\n//\n// A run that rehydrated mid-loop must re-fire its one outstanding effect on\n// activation. `do/host`'s `autoBoot` is the firing side; this agent reducer's\n// `boot` verb is the receiving side. The coupling used to be a RAW string:\n// host built `{ type: \"agent_boot\", at }` by hand and the agent string-matched\n// it — a literal duplicated across the seam with nothing tying the two ends.\n//\n// `AgentBootPort` promotes that coupling to a typed contract OWNED by the agent\n// (which owns the boot Msg shape): the `AgentBootMsg` type and the\n// `agentBootMsg` constructor. `do/host` imports the constructor instead of\n// hand-writing the literal. Adding a field to boot (or renaming it) is now a\n// one-file change here with the constructor's signature flagging every caller,\n// not a silent cross-module string drift.\n\n/** The Msg `do/host`'s `autoBoot` fires to re-enter the agent's `boot` verb on rehydrate. */\nexport type AgentBootMsg = {\n readonly type: typeof MsgType.AgentBoot;\n readonly at: number;\n};\n\n/**\n * The do↔agent boot port: construct the `agent_boot` Msg `autoBoot` dispatches\n * on a resumable rehydrate. The agent owns this constructor so the boot Msg\n * shape lives in ONE place — the host fires it through here, never as a raw\n * `{ type: \"agent_boot\" }` literal.\n */\nexport function agentBootMsg(at: number): AgentBootMsg {\n return { type: MsgType.AgentBoot, at };\n}\n\n// ===========================================================================\n// The machine Msg union — the closed set of verb entry points `toMachine` wires.\n// ===========================================================================\n\n/**\n * The agent machine's Msg union — one variant per reducer entry point. A\n * consumer using `toMachine` dispatches `agent_start` to begin and `agent_tool_ok`\n * / `agent_tool_err` to route settled tools back; the brain-call settle Msgs\n * (`resilient_ok` / `resilient_err`) RE-ENTER from the FIXED `brainHandlers`\n * (the substrate enqueues an interpret handler's returned Msg as a follow-up),\n * driving `succeed` / `fail`. Time enters via `at` on every variant — the\n * reducer never reads the clock.\n *\n * There is deliberately NO `agent_turn` variant here. The wired loop folds a\n * model turn INSIDE `succeed` from the re-entered `resilient_ok` — a single\n * settle Msg advances both the retry slice and the conversation (the L3 fix).\n * Exposing `agent_turn` as a dispatchable Msg re-opened the stuck-`running` bug:\n * a hand-fed turn folds the conversation without ever re-entering `resilient_ok`,\n * so `succeed` never runs and the resilient slice stays `running` (#54). The\n * `turn` verb remains on the knob for the consumer that wires the verbs by hand\n * (manual wiring), but it is not part of the one wired machine's Msg surface.\n */\nexport type AgentMachineMsg<P extends string, O extends Record<P, unknown>, R> =\n | {\n readonly type: typeof MsgType.AgentStart;\n readonly runId: string;\n readonly at: number;\n }\n | {\n readonly type: typeof MsgType.AgentToolOk;\n readonly callId: string;\n readonly result: R;\n readonly at: number;\n }\n | {\n readonly type: typeof MsgType.AgentToolErr;\n readonly callId: string;\n readonly reason: string;\n readonly at: number;\n }\n // The brain-call settle Msgs RE-ENTER straight from `brainHandlers` (no\n // wrapping) — `resilient_ok` runs `succeed` (reset retry + fold the turn),\n // `resilient_err` runs `fail` (back off via retry). This is the inherited\n // llm-call settle shape, dispatched verbatim by the substrate's re-entry.\n | AgentLlmOkMsg<P, O>\n | AgentLlmErrMsg<P>\n // The compaction settle Msgs RE-ENTER from the compaction interpret cell\n // (#85) — `compact_ok` folds the summary back (drops the oldest N turns +\n // their tool records, then fires the next brain call), `compact_err` backs off\n // via the compaction slice's retry or — on exhaustion — proceeds without\n // compacting (errors are data). Dedicated discriminants, re-keyed off the\n // composed resilient settle at the cell boundary.\n | AgentCompactOkMsg\n | AgentCompactErrMsg\n // The timer Msg is `DeadlineExceeded` itself (not wrapped) so the\n // `subscribeDeadline` cell dispatches it straight into `update`, exactly as\n // the resilient-call / llm-call / monitored-run gold standards wire it.\n | AgentTimerMsg\n | AgentBootMsg;\n\n// ===========================================================================\n// AgentEvent — the SEMANTIC lifecycle event stream (issue #47).\n// ===========================================================================\n\n/**\n * The agent's PUBLIC lifecycle events — the semantic stream a consumer\n * subscribes to via `runtime.on(type, …)` (#47). This is the seam that\n * DECOUPLES observability/SSE code from the agent's PRIVATE retry/loop Msg\n * vocabulary: where the old code switched on `resilient_ok` / `agent_tool_ok`\n * (the inherited resilient-call / tool-fan-out plumbing) off the raw `observe`\n * firehose, a consumer now folds these named events. The private Msg names live\n * ONLY inside `agentEvents` (the projector) — they appear nowhere in this union\n * or any exported type, so a UI built on `TurnSettled` does not break the day\n * the retry plumbing is renamed.\n *\n * - `TurnSettled` — a brain turn settled (the model produced an `AgentTurn`).\n * Projected off the private `resilient_ok` settle Msg; carries the parsed\n * `turn` (the narration + tool calls the model asked for).\n * - `ToolSettled` — a tool call settled OK. Projected off the private\n * `agent_tool_ok` Msg; carries the `callId` and the tool `result`.\n * - `RunDone` — the run finished. Projected off the post-transition State\n * reaching `run.phase === \"done\"`; carries the run's `output` (the terminal\n * model turn, or `null`) — the same first-class result `Runtime.result()`\n * reads (#46), surfaced as an event for the streaming consumer.\n */\nexport type AgentEvent<R> =\n | { readonly type: \"TurnSettled\"; readonly turn: AgentTurn }\n | {\n readonly type: \"ToolSettled\";\n readonly callId: string;\n readonly result: R;\n }\n | { readonly type: \"RunDone\"; readonly output: AgentTurn | null };\n\n/**\n * Project one APPLIED agent transition `(msg, state)` to its semantic\n * {@link AgentEvent}s (#47) — the `events` projector a consumer passes to\n * `run(machine, { events: agentEvents() })` to light up `runtime.on(...)`.\n *\n * This is the ONE place the agent's PRIVATE Msg names are read: it maps\n * `resilient_ok` → `TurnSettled` and `agent_tool_ok` → `ToolSettled`, and reads\n * the post-transition `run.phase` for `RunDone`. The mapping is total over the\n * Msg union (a `default`-free switch on the discriminant) and returns `[]` for\n * the transitions that carry no public event (start / boot / timer / the error\n * arms), so a private name never escapes into `AgentEvent`.\n *\n * A single transition may emit more than one event: the brain turn that retires\n * the final stage settles a turn (`TurnSettled`) AND finishes the run\n * (`RunDone`) — both are projected from that one `resilient_ok` transition.\n * `RunDone` is gated on `run.phase === \"done\"`, which the wired loop reaches\n * exactly once (the agent is terminal there and dispatches no further\n * transition), so the event fires once per run.\n *\n * PURE — reads only the passed `(msg, state)`; no clock, no RNG, no throw.\n *\n * @typeParam P Brain-call purposes.\n * @typeParam O Per-purpose outputs (bound to `AgentTurn`, the agentic shape).\n * @typeParam R Tool result type.\n * @typeParam Stage Pipeline stage type.\n */\nexport function agentEvents<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n>(): (\n msg: AgentMachineMsg<P, O, R>,\n state: AgentState<Stage, P, O, R>,\n) => readonly AgentEvent<R>[] {\n return (msg, state) => {\n const events: AgentEvent<R>[] = [];\n switch (msg.type) {\n case MsgType.ResilientOk:\n // The PRIVATE brain-call settle Msg → the public TurnSettled. Its\n // `result.output` is the parsed `AgentTurn` (the `O extends Record<P,\n // AgentTurn>` bound pins every purpose's output to an `AgentTurn`, the\n // same reasoning `state.output` relies on, #46/#48).\n events.push({ type: \"TurnSettled\", turn: msg.result.output });\n break;\n case MsgType.AgentToolOk:\n // The PRIVATE tool-fan-out settle Msg → the public ToolSettled.\n events.push({\n type: \"ToolSettled\",\n callId: msg.callId,\n result: msg.result,\n });\n break;\n // start / boot / timer / the *_err arms / the compaction settles carry no\n // public event — return []. (No `default`: the switch is exhaustive over\n // the Msg discriminant, so a new Msg variant forces a decision here at\n // compile time.) Compaction is an internal optimization, not a semantic\n // lifecycle moment a UI folds — its settles are deliberately silent here.\n case MsgType.AgentStart:\n case MsgType.AgentToolErr:\n case MsgType.ResilientErr:\n case MsgType.CompactOk:\n case MsgType.CompactErr:\n case \"deadline_exceeded\":\n case MsgType.AgentBoot:\n break;\n }\n // RunDone is a STATE-shaped event (the run's terminal output, #46), not a\n // Msg-shaped one: the transition that lands `done` is the final brain turn\n // (which also emits TurnSettled above). Gate on the post-transition phase so\n // the same projector reports both.\n if (state.run.phase === \"done\") {\n events.push({ type: \"RunDone\", output: state.output });\n }\n return events;\n };\n}\n\n/**\n * Join two `Interpret` dictionaries over DISJOINT Cmd subsets `A` and `B` (over\n * the same Msg union `M` and Ctx) into the full `Interpret<M, A | B, Ctx>`. The\n * agent uses it to merge the consumer's per-tool / snapshot interpret (`A`) with\n * the agent-owned brain-call handler (`B = AgentLlmRunCmd`) into the wired\n * machine's single interpret table.\n *\n * The runtime result is exactly the spread of the two key-disjoint records. The\n * single `as` is a SOUND mapped-type identity, not a laundering cast: `Interpret`\n * is a homomorphic mapped type keyed by `Cmd[\"type\"]`, so\n * `Interpret<M, A, Ctx> & Interpret<M, B, Ctx>` IS `Interpret<M, A | B, Ctx>`\n * (`(A | B)[\"type\"] = A[\"type\"] | B[\"type\"]`). TypeScript does not reduce that\n * intersection of two GENERIC mapped types on its own, so the equality is\n * asserted ONCE here — preserving `M` and `Ctx` exactly — rather than smuggled\n * through `as unknown as Interpret<...>` at every wiring site. Pure.\n */\nexport function mergeInterpret<\n M extends { type: string },\n A extends Cmd,\n B extends Cmd,\n Ctx,\n>(\n a: Interpret<M, A, Ctx> | undefined,\n b: Interpret<M, B, Ctx>,\n): Interpret<M, A | B, Ctx> {\n return { ...(a ?? {}), ...b } as Interpret<M, A | B, Ctx>;\n}\n\n/**\n * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the slice\n * lives at `state.agent`. Convenience for a host that nests the agent slice\n * under a named field; the single-slice host uses the verbs' tuple directly.\n * PURE — a thin record rebuild, no clock / RNG.\n */\nexport function liftAgent<\n S extends { agent: AgentState<Stage, P, O, R> },\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n C extends Cmd,\n>(\n state: S,\n [slice, cmds]: readonly [AgentState<Stage, P, O, R>, readonly C[]],\n): readonly [S, readonly C[]] {\n return [{ ...state, agent: slice }, cmds];\n}\n","/**\n * @demlik/tea/agent — the domain data model: the tool + turn shapes the consumer\n * supplies, the agentic-stage conversation, the `createAgent` config knob, and\n * the durable agent slice + its lifecycle status.\n *\n * Everything here is plain data (durable + replayable): the composed bricks'\n * slices, the conversation, and the config are all JSON-serializable. The\n * compaction (#85) vocabulary lives in `./compaction`; this module imports its\n * types where the slice / config reference them. The reducer core (the verbs +\n * the wired `toMachine`) lives in `./index`.\n */\n\nimport type { FanOutState } from \"../fan-out\";\nimport type { Cmd } from \"../index\";\nimport type {\n LlmCall,\n LlmOk,\n MessageLoader,\n ModelFactory,\n ResilientState,\n Schema,\n} from \"../llm-call\";\nimport type { MonitoredRunState, RunFailure } from \"../monitored-run\";\nimport type { RetryPolicy } from \"../retry-backoff\";\nimport type {\n AgentCompactionConfig,\n CompactionOutputs,\n CompactionPurpose,\n} from \"./compaction\";\nimport { schemaFromGuard } from \"./schema\";\n\n// ===========================================================================\n// Domain seams the consumer supplies — the tool + turn shapes.\n// ===========================================================================\n\n/**\n * One tool the model asked to call this turn — the seed's `ToolCall`, stripped\n * of the audit-specific args typing. Plain data so it round-trips through the\n * durable fan-out ledger: a stable `callId` (the fan-out identity), the tool\n * `name`, and the opaque `args` the consumer's own interpret reads.\n */\nexport interface ToolCall {\n /** Stable id the model minted; the fan-out item identity (`idOf`). */\n readonly callId: string;\n /** The tool to invoke. The consumer's `toolOf` maps it to an effect Cmd. */\n readonly name: string;\n /** Args the model emitted, opaque to the agent. */\n readonly args: Readonly<Record<string, unknown>>;\n}\n\n/**\n * One model turn — the seed's `AiTurn`, generalized: the narration `content`\n * the model produced and the `toolCalls` it asked us to run. An empty\n * `toolCalls` means the model is done with this stage (advance the pipeline).\n * This is the parsed output of a brain call; the consumer's schema produces it.\n */\nexport interface AgentTurn {\n /** Free-text narration the model produced this turn (folded into the conversation). */\n readonly content: string;\n /** The tools the model asked us to run; empty = stage done. */\n readonly toolCalls: readonly ToolCall[];\n}\n\n/**\n * Narrow an unknown to a `ToolCall` — the per-element witness `isAgentTurn`\n * folds over the `toolCalls` array. Checks the three load-bearing fields:\n * `callId`/`name` are strings, `args` is a non-null object. PURE — allocates no\n * Error. Without this the array-of-`ToolCall` narrow would be validation\n * masquerading as parse: `toolCalls: [1, 2, 3]` would pass, then the downstream\n * `dedupeByCallId` / `fan.scatter` read an `undefined` `callId` and wedge the\n * fan-out batch.\n */\nfunction isToolCall(value: unknown): value is ToolCall {\n if (value === null || typeof value !== \"object\") return false;\n const t = value as { callId?: unknown; name?: unknown; args?: unknown };\n return (\n typeof t.callId === \"string\" &&\n typeof t.name === \"string\" &&\n t.args !== null &&\n typeof t.args === \"object\"\n );\n}\n\n/**\n * Narrow an unknown to an `AgentTurn` — the runtime witness for tea's own\n * structured-output type. A consumer's brain schema parses the model's output\n * into an `AgentTurn` (the agentic purpose's output); rather than every consumer\n * hand-rolling this guard + a `Schema<AgentTurn>` for a type the agent OWNS, the\n * agent exports both. Checks the load-bearing fields: `content` is a string and\n * `toolCalls` is an array of `ToolCall` (each element guarded — the narrow is a\n * real parse of the boundary, not a shallow `Array.isArray`). PURE — allocates\n * no Error.\n */\nexport function isAgentTurn(value: unknown): value is AgentTurn {\n if (value === null || typeof value !== \"object\") return false;\n const t = value as { content?: unknown; toolCalls?: unknown };\n return (\n typeof t.content === \"string\" &&\n Array.isArray(t.toolCalls) &&\n t.toolCalls.every(isToolCall)\n );\n}\n\n/**\n * The `Schema<AgentTurn>` for tea's own turn type — the parse target a brain\n * call binds when the agentic purpose's output is a bare `AgentTurn` (the common\n * case). Throws on a non-`AgentTurn` (the zod-style `parse` contract the\n * llm-call handler relies on). Deletes the consumer's hand-rolled\n * `auditSchema` / `isAgentTurn` pair.\n *\n * A consumer whose turn type EXTENDS `AgentTurn` with extra fields still writes\n * its own schema (it must validate the extra fields); this is for the plain case.\n */\nexport const agentTurnSchema: Schema<AgentTurn> = schemaFromGuard(\n isAgentTurn,\n \"an AgentTurn\",\n);\n\n/**\n * One settled tool outcome the consumer routes back into the loop — the seed's\n * `ToolOutcome`. `ok` carries the result the consumer's interpret produced;\n * `error` carries a reason the model sees (so it recovers rather than stalls —\n * \"errors are data\").\n */\nexport type ToolOutcome<R> =\n | { readonly kind: \"ok\"; readonly result: R }\n | { readonly kind: \"error\"; readonly reason: string };\n\n/**\n * A folded tool record kept on the conversation once a tool settles — the\n * call + its outcome, in settle order. The consumer's message loader reads\n * these (plus `turns`) to assemble the next brain call's prompt.\n *\n * `turn` is the `turnCount` at the time the record was folded — the association\n * compaction needs to drop the RIGHT records (#85 / design A1). When compaction\n * folds `turns[0..N]` into a summary, it must also drop every tool record that\n * belonged to those turns; without a turn stamp on the record there is no honest\n * way to know which. It is the round-trip index, not a wall clock — small and\n * JSON-stable, preserving the durability invariant.\n */\nexport interface ToolRecord<R> {\n readonly call: ToolCall;\n readonly outcome: ToolOutcome<R>;\n /** The `turnCount` at fold time — which round-trip this record belongs to (#85, A1). */\n readonly turn: number;\n}\n\n// ===========================================================================\n// Conversation — the agentic-stage loop state (the seed's `Conversation`).\n// ===========================================================================\n\n/**\n * Whether the agentic stage is waiting on the model (`llm`), on tools\n * (`tools`), or on a compaction round-trip (`compacting`, #85). The in-flight\n * fan-out batch exists ONLY in the `tools` variant — \"awaiting llm with tools\n * pending\" is structurally impossible (the seed's canon §2.6 / Rule 1\n * impossible-states pin). Discriminated on `kind`.\n *\n * `compacting` is the honest state for the dedicated compaction round-trip\n * (design B1): the transcript grew, the policy asked to fold `folding` of the\n * OLDEST turns, and the summarize call is in flight INSTEAD of the next brain\n * call. `folding` is the count `planCompaction` returned — the fold-back\n * (`compact_ok`) drops exactly that many head turns + their tool records.\n */\nexport type Awaiting =\n | { readonly kind: \"llm\" }\n | { readonly kind: \"tools\"; readonly batchTurn: number }\n | { readonly kind: \"compacting\"; readonly folding: number };\n\n/**\n * The agentic-stage conversation — durable inside the agent slice so an\n * eviction mid-loop resumes the exact turn. The model turns + folded tool\n * records are the consumer's prompt source (via the llm-call message loader);\n * `turnCount` drives the livelock guard; `awaiting` carries the ONE outstanding\n * effect for the agentic stage.\n *\n * Generic over the consumer's tool-result type `R` (what `toolOk` carries).\n */\nexport interface Conversation<R> {\n /** Model turns this stage has produced, in order. */\n readonly turns: readonly AgentTurn[];\n /** Settled tool records, in settle order — the model sees these next turn. */\n readonly toolRecords: readonly ToolRecord<R>[];\n /** Monotonic round-trip count; the livelock guard compares it to `maxTurns`. */\n readonly turnCount: number;\n /** What the loop is waiting for next. */\n readonly awaiting: Awaiting;\n}\n\n// ===========================================================================\n// Config — the knob. The domain seams (tools / schemas / model / stages) are\n// required; everything cross-cutting (retry / deadline / concurrency / loader /\n// maxTurns) is optional, per the resilient-call \"omit a brick → omit its gate\".\n// ===========================================================================\n\n/**\n * The snapshotting discriminant (#55). Checkpointing is either OFF — in which\n * case `snapshotEvery` is structurally absent and the monitored-run slice never\n * emits a `snapshot_write` Cmd — or ON, in which case `snapshotEvery` is a\n * `number`. A `{ snapshotEvery?: never }` member (rather than a bare optional)\n * makes the OFF case load-bearing: it forbids passing `snapshotEvery` at all, so\n * `toMachine` can config-derive whether the `snapshot_write` interpret cell is\n * REQUIRED (ON) or FORBIDDEN (OFF) instead of defaulting it to a silent no-op.\n *\n * This is what kills the type lie: with checkpointing off, `snapshot_write` is\n * absent from the consumer's interpret contract entirely — never a\n * `snapshot_write: async () => undefined` ceremony that masks a real wiring bug.\n */\nexport type AgentSnapshotConfig =\n | { readonly snapshotEvery?: never }\n | { readonly snapshotEvery: number };\n\n/**\n * The core (non-snapshot, non-compaction) agent knob. The full `AgentConfig`\n * intersects this with the `AgentSnapshotConfig` + `AgentCompactionConfig`\n * discriminants — see those types for why the cadence / policy are discriminated\n * unions rather than bare optionals.\n *\n * Type parameters:\n * - `Stage` — the consumer's pipeline stage id (any JSON value).\n * - `P` — the brain-call purpose union (`\"plan\" | \"act\" | ...`).\n * - `O` — the purpose→output map. Every purpose drives the agentic loop,\n * so each output is pinned to `AgentTurn` (or a subtype) by the\n * `O extends Record<P, AgentTurn>` bound — that is what the loop\n * folds. An `Outputs` whose purpose output is NOT an `AgentTurn`\n * fails to compile here; the rule lives in the type, not a cast.\n * - `R` — the consumer's tool-result type (what `toolOk` carries).\n * - `TC` — the consumer's per-tool effect Cmd, the discriminated variant\n * `toolOf` produces. Kept PRECISE (a closed Cmd variant, not the\n * open `Cmd`) so `AgentCmd<P, TC>` stays a closed discriminated\n * union and the wired machine's interpret merge type-checks per\n * key — the brain cell maps to `resilient_run`, the tool cell to\n * `TC[\"type\"]` — with no laundering cast. Defaults to `Cmd` for\n * the consumer that does not care to name its tool Cmd.\n * - `Msg` — the model's message shape (threaded through the llm-call loader).\n */\nexport interface AgentConfigCore<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n> {\n // ---- monitored-run seam (the outer pipeline) ----------------------------\n /** The ordered stages. Omit / empty → a single-shot run (one agentic stage). */\n readonly stages?: readonly Stage[];\n /** No-progress watchdog budget, in ms. Omit → no watchdog. */\n readonly deadlineMs?: number;\n\n // ---- llm-call seam (the brain) ------------------------------------------\n /** DI port — the model factory `(modelId) => Llm`. */\n readonly model: ModelFactory<Msg>;\n /** One structured-output schema per purpose; the parse target per brain call. */\n readonly schemas: { readonly [K in P]: Schema<O[K]> };\n /** Backoff policy for brain calls, composed into `../llm-call`. Omit → no backoff. */\n readonly retry?: RetryPolicy;\n /** DI port — the SDK / message loader. Omit → brain calls invoke with `[]`. */\n readonly loadMessages?: MessageLoader<P, Msg>;\n\n // ---- fan-out seam (the tools) -------------------------------------------\n /** Map one tool call to the effect Cmd the consumer's interpret performs. */\n readonly toolOf: (call: ToolCall) => TC;\n /** Max tools in flight at once. Omit / `1` → serial dispatch (the seed's behavior). */\n readonly toolConcurrency?: number;\n\n // ---- the loop wiring -----------------------------------------------------\n /**\n * Which brain-call purpose a given stage runs. The agent fires\n * `call_llm{ turnOf(stage) }` to drive the agentic stage's loop. The purpose's\n * schema output is an `AgentTurn` — enforced by the `O extends Record<P,\n * AgentTurn>` bound, not left to a doc-comment.\n */\n readonly turnOf: (stage: Stage | undefined) => P;\n /** Build the per-purpose brain-call payload from the conversation. Omit → `null`. */\n readonly payloadOf?: (\n stage: Stage | undefined,\n conversation: Conversation<R>,\n ) => unknown;\n /** The model id every brain call invokes. Omit → `null` (the host's default). */\n readonly modelId?: string | null;\n /**\n * Livelock guard: bound on model round-trips within one run. On\n * `turnCount >= maxTurns` the run fails `{ reason: \"turn_limit\" }`. Omit → no\n * turn guard (only the deadline watchdog bounds the loop).\n */\n readonly maxTurns?: number;\n\n // ---- determinism seam ----------------------------------------------------\n /**\n * The impurity-injection seam for the inherited brain-call retry jitter — the\n * ONE place this otherwise-pure machine reads randomness. Pass a fixed\n * `() => 0` to pin backoff (tests, replay, durability proofs). Omit →\n * `Math.random`, read only at the resilient-call verb boundary.\n */\n readonly rng?: () => number;\n}\n\n/**\n * The agent knob — the core seams intersected with the snapshotting discriminant\n * (`AgentSnapshotConfig`). Type parameters are documented on `AgentConfigCore`;\n * the only addition here is that `snapshotEvery` is the discriminant that drives\n * whether `toMachine` requires (or forbids) the `snapshot_write` interpret cell.\n */\nexport type AgentConfig<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n> = AgentConfigCore<Stage, P, O, R, TC, Msg> &\n AgentSnapshotConfig &\n AgentCompactionConfig<R, Msg>;\n\n// ===========================================================================\n// Slice — the Model field this knob owns. Three composed slices + the loop's\n// conversation. Plain data end to end → durable + replayable.\n// ===========================================================================\n\n/**\n * Why a run terminated as `failed`, beyond monitored-run's own reasons. The\n * `turn_limit` reason is the agent's livelock guard; deadline / stage failures\n * surface through the monitored-run slice's own `failure`.\n */\nexport type AgentFailure =\n | { readonly reason: \"turn_limit\"; readonly at: number }\n | { readonly reason: \"llm\"; readonly error: unknown; readonly at: number };\n\n/**\n * The agent slice — every composed brick's slice plus the loop's conversation\n * and the agent-specific failure annotation.\n *\n * - `run` — the `../monitored-run` slice (pipeline position +\n * lifecycle + watchdog). The OUTER lifecycle truth.\n * - `resilience` — the `../llm-call` (= resilient-call) slice (brain-call\n * retry / backoff). Per-purpose retry lives here.\n * - `tools` — the `../fan-out` ledger for the current turn's tools.\n * - `conversation` — the agentic-stage loop state. `null` until the loop is\n * entered (the consumer seeds it at the agentic stage).\n * - `failure` — the agent-specific terminal annotation (turn-limit /\n * llm), null otherwise. Distinct from `run.failure`.\n */\nexport interface AgentState<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n> {\n readonly run: MonitoredRunState<Stage>;\n readonly resilience: ResilientState<LlmCall<P>, LlmOk<P, O>>;\n readonly tools: FanOutState<ToolCall, ToolOutcome<R>>;\n readonly conversation: Conversation<R> | null;\n /**\n * The compaction round-trip's resilient slice (#85, design B1) — a DEDICATED\n * resilient-call slice for the reserved `$compact` purpose, separate from the\n * brain `resilience` slice so a compaction retry/backoff never disturbs the\n * brain call's breaker or retry counter. Always present (empty `calls` when no\n * compaction is in flight, or when no policy is configured) so the slice stays\n * a flat plain-data record — durable + replayable like every composed brick.\n */\n readonly compaction: ResilientState<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >;\n readonly failure: AgentFailure | null;\n /**\n * The run's terminal output — the FIRST-CLASS result (issue #46). `null`\n * until the pipeline finishes; set to the last model turn (the empty-tool\n * turn that retired the final stage) the instant `run.phase` becomes `\"done\"`.\n *\n * This survives the `conversation` clear on stage retire: clearing the\n * conversation is correct durability hygiene (a finished stage's transcript\n * is not live state), but the run's PRODUCT is, so it lives here on the\n * durable slice rather than being scraped off the `observe` firehose by\n * matching the private `resilient_ok` Msg and racing the clear (the old\n * `captureLastTurn` dance this field deletes). A consumer reads\n * `runtime.result()?.output` / `(await runtime.done()).output`.\n *\n * Typed `AgentTurn | null` (not `O[P]`): the run's output is always a model\n * turn — the `O extends Record<P, AgentTurn>` knob bound pins every purpose's\n * output to an `AgentTurn`, and the terminating turn is the one with no tool\n * calls. The wider `Record<P, unknown>` bound on `AgentState` itself does not\n * constrain `O[P]`, so naming the concrete `AgentTurn` keeps this field's type\n * total without a purpose-indexing narrow.\n */\n readonly output: AgentTurn | null;\n}\n\n// ===========================================================================\n// Lifecycle status — the ONE typed channel callers read instead of re-deriving\n// the private slice shape (issue #49).\n// ===========================================================================\n\n/**\n * The unified terminal failure (issue #49). The agent terminates `failed`\n * through TWO independent slice channels:\n *\n * - `state.failure` (`AgentFailure`) — the AGENT'S OWN annotation\n * (`turn_limit` livelock guard / `llm` exhausted-retry). Set WITHOUT moving\n * `run.phase` (it stays `running`); `isSettled` treats a non-null `failure`\n * as terminal regardless of `run.phase`.\n * - `state.run.failure` (`RunFailure`) — the monitored-run channel\n * (`deadline` watchdog / `stage` failure), present iff `run.phase` is\n * `\"failed\"`.\n *\n * Callers used to union these by hand at every status question. `status`\n * collapses them into ONE `failure`, so a consumer reads `status(s).failure`\n * without knowing which channel produced it.\n */\nexport type AgentTerminalFailure<Stage> = AgentFailure | RunFailure<Stage>;\n\n/**\n * The agent's lifecycle status — THE single typed channel for \"what is this run\n * doing?\" (issue #49). A discriminated union on `kind` so any change to the\n * private slice shape (`Awaiting`, the failure channels, `run.phase`) forces a\n * compile error at the call sites that switch on it, instead of silently\n * breaking a hand-rolled re-derivation. Make-invalid-states-unrepresentable:\n *\n * - `running` — live, NOT awaiting tools (a brain call is in flight, or the\n * run is between stages). Not resumable on cold wake by\n * itself — the in-flight brain call re-fires from `boot`.\n * - `suspended` — the RESUMABLE case: running + a live conversation +\n * `awaiting.kind === \"tools\"`. `pending` is the outstanding\n * tool calls (`conversation.awaiting` … the in-flight batch),\n * read off `tools.running`. This is exactly the shape\n * `agentIsResumable` re-derived by hand.\n * - `done` — the pipeline finished; `output` is the terminal model turn\n * stamped on `state.output` (issue #46), `null` if the run\n * produced no turn.\n * - `failed` — terminal failure; `failure` is the UNIFIED channel\n * (`AgentTerminalFailure`), absorbing the `state.failure` vs\n * `state.run.failure` dual channel so callers stop unioning.\n */\nexport type AgentStatus<Stage> =\n | { readonly kind: \"running\" }\n | { readonly kind: \"suspended\"; readonly pending: readonly ToolCall[] }\n | { readonly kind: \"done\"; readonly output: AgentTurn | null }\n | { readonly kind: \"failed\"; readonly failure: AgentTerminalFailure<Stage> };\n\n/**\n * Derive the agent's lifecycle `status` from its durable slice — the pure\n * status function that REPLACES every caller's hand re-derivation of the private\n * shape (issue #49). PURE — reads no clock / RNG, allocates one small record.\n *\n * Ordering is terminal-first so a settled run never reports `running`:\n *\n * 1. `state.failure` (the agent's own annotation, set WITHOUT moving\n * `run.phase`) → `failed`. Checked first because `turn_limit` / `llm`\n * leave `run.phase === \"running\"`; reading `run.phase` first would\n * misreport such a run as `running`. This is the canonical failure source\n * when present.\n * 2. `run.phase === \"failed\"` → `failed`, carrying `run.failure` (deadline /\n * stage). The fallback channel.\n * 3. `run.phase === \"done\"` → `done` with `state.output` (#46).\n * 4. running + conversation + `awaiting.kind === \"tools\"` → `suspended` with\n * the outstanding tool calls (`tools.running`). THE resumability condition.\n * 5. otherwise → `running`.\n */\nexport function status<\n Stage,\n P extends string,\n O extends Record<P, unknown>,\n R,\n>(s: AgentState<Stage, P, O, R>): AgentStatus<Stage> {\n // 1) The agent's own failure annotation is canonical — it is set without\n // moving `run.phase` (turn_limit / llm leave the run `running`), so it\n // MUST be read before `run.phase` or such a failure reports as `running`.\n if (s.failure !== null) {\n return { kind: \"failed\", failure: s.failure };\n }\n // 2) The monitored-run terminal failure (deadline / stage). `run.failure` now\n // rides ONLY the `failed` arm of the discriminated union, so narrowing on\n // `phase === \"failed\"` surfaces it with no nullable side field and no\n // fabricated fallback — the old \"failed-yet-failure-null\" state is\n // unrepresentable.\n if (s.run.phase === \"failed\") {\n return { kind: \"failed\", failure: s.run.failure };\n }\n // 3) The pipeline finished — the terminal output landed on `state.output`.\n if (s.run.phase === \"done\") {\n return { kind: \"done\", output: s.output };\n }\n // 4) Running + a live conversation awaiting tools → suspended (resumable).\n // The outstanding calls are the in-flight fan-out batch (`tools.running`).\n if (s.conversation !== null && s.conversation.awaiting.kind === \"tools\") {\n return { kind: \"suspended\", pending: s.tools.running };\n }\n // 5) Otherwise the run is live and not awaiting tools.\n return { kind: \"running\" };\n}\n","/**\n * @packageDocumentation\n * @demlik/tea/agent — THE headline Level-3 machine: a durable, crash-recoverable\n * AI agent that runs an ordered stage pipeline, and inside the agentic stage\n * drives the classic loop `llm → tools → fold → llm` until the model stops\n * asking for tools.\n *\n * This is the `seed/audit-agent-machine` reducer generalized: the seed's audit /\n * glyph / violation domain specifics are stripped, and what remains — the loop,\n * the durability, the boot-reconcile crash recovery, the serial-vs-fanned tool\n * dispatch — is yours. The consumer supplies the only things that are genuinely\n * domain: the tools, the prompts (via the llm-call message loader), the schemas,\n * and the model. `createAgent(config)` returns the uniform knob contract every\n * composition exposes (`init` / verbs returning `readonly [State, Cmd[]]` /\n * `subs`) AND a ready-to-`run` `defineMachine` (`toMachine`) — THE one wired\n * path. (`unsafeDetachedHandlers` is the hand-wiring escape hatch; its name\n * advertises that it does not drive the retry loop — see #54.)\n *\n * ## The composition (three siblings wired into ONE machine)\n *\n * - `../monitored-run` — the OUTER pipeline + lifecycle + safety watchdog.\n * The agent's stages (`plan → act → report`, say) are its stages; the\n * position survives eviction, the no-progress deadline auto-fails a wedged\n * run, and `boot` resumes mid-pipeline. The agent slice OWNS this slice and\n * delegates `start` / `advance` / `progress` / `onDeadline` / `boot` to it.\n * - `../llm-call` — every brain call (the seed's `call_llm{purpose}`). One\n * `LlmCall` per turn, structured-output parsed, retry composed in. The agent\n * delegates the resilient slice + verbs and reuses the detached handler.\n * - `../fan-out` — the tool calls a turn produced. The seed dispatched tools\n * SERIALLY (concurrency 1); fan-out generalizes that to bounded concurrency\n * `config.toolConcurrency` (default 1 = the seed's serial behavior). Each\n * tool is an `of(call)` Cmd the consumer's own interpret performs; results\n * route back through `toolOk` / `toolErr`. When the batch drains, the agent\n * folds the gathered results back into the conversation and fires the next\n * brain call (`fold → llm`).\n *\n * ## The flow loop, as TEA (generalized from the seed's `applyAiTurn`)\n *\n * 1. `start` enters the pipeline; the consumer wires the per-stage outstanding\n * effect (often a `call_llm` for the agentic stage) off the current stage.\n * 2. `turn(msg)` folds one model turn:\n * - no tool calls → the loop is done for this stage → `advance` the\n * pipeline (next stage, or finish to `done`).\n * - tool calls → `scatter` them across fan-out (≤ concurrency in flight),\n * emitting the per-tool effect Cmds. The conversation records the model\n * turn; `awaiting` flips to `tools`.\n * 3. `toolOk` / `toolErr` fold each settled tool back, launching the next\n * queued tool. When the batch drains, fold the gathered outcomes into the\n * conversation, bump the turn count (livelock guard), and fire the next\n * brain call — `awaiting` flips back to `llm`.\n * 4. The watchdog + turn-limit guard bound the loop; the deadline fires\n * `failed`, the turn limit fires `failed { turn_limit }`.\n *\n * ## Boot reconcile (crash recovery — the seed's `outstandingEffect`)\n *\n * Cold wake re-derives the ONE outstanding effect from `phase × awaiting`: a\n * brain call in flight re-fires `call_llm`; tools in flight re-fire the in-flight\n * tool Cmds. Re-fire is Model-idempotent — had the prior effect's result been\n * processed, the durable Model would already have advanced and boot re-emits the\n * NEXT effect. `boot` re-seeds the watchdog clock to NOW (a cold wake is not a\n * no-progress wedge) via the inherited monitored-run `boot`.\n *\n * ## The two non-negotiables (canon, inherited)\n *\n * - **Durable** — the whole slice is plain data: the monitored-run slice, the\n * resilient (retry) slice, the fan-out ledger, and the conversation are all\n * JSON-serializable. It survives DO eviction / reload.\n * - **Replayable** — every transition is a pure verb returning new state +\n * Cmds; nothing here reads the clock or RNG. Time arrives as an `at`\n * parameter, jitter RNG is injected once at `createAgent`, and the only clock\n * reads live inside the spliced handlers (the effect boundary).\n *\n * ## Typical wiring\n *\n * // Type params: <Stage, Purpose, Outputs, Result, ToolCmd, Msg>. `ToolCmd`\n * // is the discriminated Cmd `toolOf` returns — keep it precise (not the open\n * // `Cmd`) so the wired machine's interpret merge type-checks per key.\n * type RunTool = { readonly type: \"run_tool\" } & ToolCall;\n * const agent = createAgent<Stage, Purpose, Outputs, Result, RunTool, Msg>({\n * stages: [\"plan\", \"act\", \"report\"],\n * model: (id) => createChatModel(env, id),\n * schemas: { plan: planSchema, act: turnSchema, report: reportSchema },\n * turnOf: (stage) => stageToPurpose[stage], // which brain call a stage runs\n * toolOf: (call): RunTool => ({ type: \"run_tool\", ...call }),\n * toolConcurrency: 1, // serial like the seed (default)\n * deadlineMs: 10 * 60_000,\n * maxTurns: 60,\n * retry: defaultRetryPolicy,\n * loadMessages,\n * });\n * // The consumer supplies the per-tool (+ snapshot) interpret; the agent owns\n * // the brain interpret and merges them in `toMachine`.\n * const machine = agent.toMachine({ toolInterpret });\n * const runtime = run(machine, { ctx, store });\n */\n\nimport { createFanOut, initFanOut } from \"../fan-out\";\nimport {\n type Cmd,\n defineMachine,\n type Interpret,\n type Machine,\n type Reducer,\n} from \"../index\";\nimport {\n createLlmCall,\n deadlineSub,\n type LlmCall,\n type LlmFailMsg,\n type LlmOk,\n type LlmRunCmd,\n type LlmSucceedMsg,\n type ResilientState,\n subscribeDeadline,\n} from \"../llm-call\";\nimport {\n createMonitoredRun,\n type DeadlineSub,\n type MonitoredRunCmd,\n} from \"../monitored-run\";\nimport { MsgType } from \"../protocol\";\nimport { createResilientCall } from \"../resilient-call\";\nimport {\n type AgentCompactErrMsg,\n type AgentCompactOkMsg,\n type AgentCompactRunCmd,\n COMPACTION_PURPOSE,\n type CompactInterpret,\n type CompactionOutputs,\n type CompactionPolicy,\n type CompactionPurpose,\n} from \"./compaction\";\nimport {\n currentStage,\n dedupeByCallId,\n foldSummary,\n freshConversation,\n isSettled,\n requireAwaiting,\n toCompactRunCmd,\n} from \"./internal\";\nimport {\n type AgentCmd,\n type AgentDetachedHandlers,\n type AgentKnob,\n type AgentLlmErrMsg,\n type AgentLlmOkMsg,\n type AgentLlmRunCmd,\n type AgentMachineMsg,\n type AgentPorts,\n type AgentTimerMsg,\n mergeInterpret,\n type SnapshotInterpret,\n} from \"./machine\";\nimport type {\n AgentConfig,\n AgentConfigCore,\n AgentFailure,\n AgentState,\n AgentTurn,\n Conversation,\n ToolCall,\n ToolOutcome,\n} from \"./types\";\n\n// Re-export the concern modules so the public `@demlik/tea/agent` barrel is\n// unchanged after the split into `./types` (domain + conversation + config +\n// state/status), `./compaction` (the #85 seam), and `./machine` (the Cmd/Msg\n// vocabulary + wiring helpers). The reducer core — `createAgent` — stays here.\nexport * from \"./compaction\";\nexport * from \"./machine\";\nexport * from \"./types\";\n\n// ===========================================================================\n// The knob factory.\n// ===========================================================================\n\n/**\n * Build an agent knob from `config`. The determinism seam — `config.rng`,\n * injected for the inherited brain-call retry jitter — lives as a named field\n * on the config (pass a fixed `() => 0` to pin backoff in tests; omit → defaults\n * to `Math.random`, read only at the resilient-call verb boundary).\n *\n * Returns the uniform knob contract (`init` / verbs / `subs`) plus `toMachine()`\n * — a `defineMachine` wiring all of it into one runnable machine — and the\n * `unsafeDetachedHandlers` hand-wiring escape hatch.\n *\n * `createAgent` is OVERLOADED on TWO independent discriminants — the snapshotting\n * (#55) and the compaction (#85) one — so each `toMachine` obligation is derived\n * from the `config` VALUE, never inferred. `{ snapshotEvery: number }` REQUIRES\n * the `snapshot_write` cell, `{ snapshotEvery?: never }` FORBIDS it; `{ compaction:\n * policy }` REQUIRES the `compact_run` cell, `{ compaction?: never }` FORBIDS it.\n * The four overloads enumerate the snapshot × compaction grid: overload resolution\n * reads the two fields off `config`, so the right `Snap`/`Compact` pair is fixed\n * even when the call site passes explicit type arguments (TS does not infer\n * trailing type params — a `Cfg`-inference scheme would silently fall back to OFF\n * at every explicit-type-arg call site). The overloads fix both concretely.\n */\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery: number;\n readonly compaction: CompactionPolicy<R, Msg>;\n },\n): AgentKnob<Stage, P, O, R, TC, true, true>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery: number;\n readonly compaction?: never;\n },\n): AgentKnob<Stage, P, O, R, TC, true, false>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery?: never;\n readonly compaction: CompactionPolicy<R, Msg>;\n },\n): AgentKnob<Stage, P, O, R, TC, false, true>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfigCore<Stage, P, O, R, TC, Msg> & {\n readonly snapshotEvery?: never;\n readonly compaction?: never;\n },\n): AgentKnob<Stage, P, O, R, TC, false, false>;\nexport function createAgent<\n Stage,\n P extends string,\n O extends Record<P, AgentTurn>,\n R,\n TC extends Cmd = Cmd,\n Msg = unknown,\n>(\n config: AgentConfig<Stage, P, O, R, TC, Msg>,\n): AgentKnob<Stage, P, O, R, TC, boolean, boolean> {\n const rng = config.rng ?? Math.random;\n // ---- The three composed sub-knobs --------------------------------------\n\n const run = createMonitoredRun<Stage, unknown>({\n ...(config.stages !== undefined ? { stages: config.stages } : {}),\n ...(config.deadlineMs !== undefined\n ? { deadlineMs: config.deadlineMs }\n : {}),\n ...(config.snapshotEvery !== undefined\n ? { snapshotEvery: config.snapshotEvery }\n : {}),\n });\n\n const llm = createLlmCall<P, O, Msg>(\n {\n model: config.model,\n schemas: config.schemas,\n ...(config.retry !== undefined ? { retry: config.retry } : {}),\n ...(config.loadMessages !== undefined\n ? { loadMessages: config.loadMessages }\n : {}),\n },\n rng,\n );\n\n // The DEDICATED compaction round-trip's resilient slice (#85, design B1) — a\n // SECOND resilient-call slice keyed on the reserved `$compact` purpose, so the\n // summarize call inherits the SAME retry/backoff machinery as the brain call\n // WITHOUT sharing its slice (a compaction retry never touches the brain breaker\n // / retry counter). The agent owns the retry ORCHESTRATION (trigger → settle →\n // backoff → re-issue); the consumer's `compact_run` interpret cell owns the\n // summarize I/O (the model round-trip + parse), exactly as the consumer owns\n // tool I/O via `toolOf`. The slice's `input` is the plain `LlmCall<$compact>`\n // request, its `result` the parsed `LlmOk` the consumer's cell returns. Always\n // built; never driven when no policy is configured (the trigger never fires).\n const compactRc = createResilientCall<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >({ ...(config.retry !== undefined ? { retry: config.retry } : {}) }, rng);\n\n // Tools fan out at `toolConcurrency` (default 1 = the seed's serial dispatch).\n // The fan-out item is the `ToolCall`; its identity is `callId`; each launch is\n // the consumer's `toolOf(call)` effect. No `join` — the agent reads completion\n // off `isComplete` at the settle boundary (it must fold + fire the next brain\n // call, not emit a single completion Cmd).\n // `TC` is the fan-out's launch-Cmd type and `never` its join-Cmd type (the\n // agent fires no `join` — it reads completion off `isComplete`), so `scatter`\n // / `itemOk` / `itemErr` return `readonly TC[]` (not the widened `Cmd[]`). The\n // agent's verb tuples stay precisely `AgentCmd<P, TC>` with no widening cast\n // on the launch cmds.\n const fan = createFanOut<ToolCall, ToolOutcome<R>, TC, never>({\n concurrency: config.toolConcurrency ?? 1,\n idOf: (call) => call.callId,\n of: (call) => config.toolOf(call),\n });\n\n type State = AgentState<Stage, P, O, R>;\n\n /** The starting slice — every brick's `init`, no conversation yet. */\n function init(): State {\n return {\n run: run.init(),\n resilience: llm.init(),\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n conversation: null,\n compaction: compactRc.init(),\n failure: null,\n output: null,\n };\n }\n\n /** Build the brain-call request for the current stage + conversation. PURE. */\n function brainCall(s: State): LlmCall<P> {\n const stage = currentStage(s);\n const conversation = s.conversation ?? freshConversation<R>();\n return {\n purpose: config.turnOf(stage),\n model: config.modelId ?? null,\n payload: config.payloadOf ? config.payloadOf(stage, conversation) : null,\n };\n }\n\n /**\n * Fire the current stage's brain call: build the request ({@link brainCall}),\n * thread it through the resilient retry layer, and return the resilience-updated\n * state + the llm run Cmds. THE shared epilogue of every verb that (re-)enters\n * the brain path — `start`, `advanceStage`, `settleTool`'s drain, `compactOk`,\n * `compactErr`, `boot` — each concats its OWN leading Cmds onto the returned llm\n * Cmds. PURE — `at` is the only clock.\n */\n function fireBrainCall(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const call = brainCall(s);\n const [resilience, cmds] = llm.attempt(s.resilience, call, at);\n return [{ ...s, resilience }, cmds];\n }\n\n /**\n * Build the compaction summarize request for a conversation + fold count — the\n * `$compact` sibling of {@link brainCall}, so the summarize-request shape lives\n * in ONE spot and both the trigger (`maybeCompact`) and the boot re-fire emit a\n * byte-identical `LlmCall<$compact>`. PURE.\n */\n function compactionCall(\n conv: Conversation<R>,\n folding: number,\n ): LlmCall<CompactionPurpose> {\n const payloadOf = config.compaction?.payloadOf;\n return {\n purpose: COMPACTION_PURPOSE,\n model: config.modelId ?? null,\n payload: payloadOf ? payloadOf(conv, folding) : null,\n };\n }\n\n /** The dedicated compaction round-trip's resilient slice type (#85, design B1). */\n type CompactionSlice = ResilientState<\n LlmCall<CompactionPurpose>,\n LlmOk<CompactionPurpose, CompactionOutputs>\n >;\n\n /**\n * Re-key a compaction verb's `[slice, resilient_run Cmds]` result so the emitted\n * Cmds carry the dedicated `compact_run` discriminant. The one place the\n * `with-resilience` boundary re-key ({@link toCompactRunCmd}) lives.\n */\n function reKeyCompactCmds(\n result: readonly [CompactionSlice, readonly LlmRunCmd<CompactionPurpose>[]],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] {\n const [slice, cmds] = result;\n return [slice, cmds.map(toCompactRunCmd)];\n }\n\n /**\n * The compaction slice's four cmd-emitting verbs, wrapped so each returns its\n * `resilient_run` Cmds ALREADY re-keyed to the dedicated `compact_run`\n * discriminant. The re-key is an INVARIANT of talking to `compactRc` — its Cmds\n * must route to the compaction interpret cell, never the brain `resilient_run`\n * one — so it lives here ONCE instead of at every call boundary, where a single\n * forgotten `.map` would misroute a compaction run Cmd to the brain cell. PURE —\n * pure delegation + re-key. (`init` / `subs` emit no run Cmds → used on\n * `compactRc` directly.)\n */\n const compact = {\n attempt: (\n slice: CompactionSlice,\n key: CompactionPurpose,\n input: LlmCall<CompactionPurpose>,\n at: number,\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.attempt(slice, key, input, at)),\n succeed: (\n slice: CompactionSlice,\n key: string,\n msg: Parameters<typeof compactRc.succeed>[2],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.succeed(slice, key, msg)),\n fail: (\n slice: CompactionSlice,\n key: string,\n msg: Parameters<typeof compactRc.fail>[2],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.fail(slice, key, msg)),\n onTimer: (\n slice: CompactionSlice,\n msg: Parameters<typeof compactRc.onTimer>[1],\n ): readonly [CompactionSlice, readonly AgentCompactRunCmd[]] =>\n reKeyCompactCmds(compactRc.onTimer(slice, msg)),\n };\n\n // === Verb: start =========================================================\n\n /**\n * Start (or restart) the run for `runId` at `at`, entering the agentic loop:\n * seed the pipeline (via monitored-run), seed a fresh conversation, and fire\n * the first brain call. PURE — `at` is the only clock.\n */\n function start(\n s: State,\n runId: string,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice] = run.start(s.run, runId, at);\n const conversation = freshConversation<R>();\n const withRun: State = {\n ...s,\n run: runSlice,\n conversation,\n failure: null,\n // A restart clears the prior run's terminal output — `result()` reads\n // `undefined` again until THIS run finishes (#46).\n output: null,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n // A restart also clears any prior compaction slice — a fresh run never\n // inherits the previous run's summarize retry bookkeeping (#85).\n compaction: compactRc.init(),\n };\n return fireBrainCall(withRun, at);\n }\n\n // === Verb: turn ==========================================================\n\n /**\n * Fold ONE model turn (the brain call resolved with an `AgentTurn`). The core\n * of the loop — the seed's `applyAiTurn`, generalized:\n *\n * - empty `toolCalls` → the loop is done for this stage → `advance` the\n * pipeline (next stage seeds a fresh conversation + brain call, or finish\n * to `done`).\n * - non-empty `toolCalls` → `scatter` them across fan-out (≤ concurrency in\n * flight), recording the turn and flipping `awaiting` to `tools`. The\n * returned Cmds are the launched per-tool effects.\n *\n * A no-op when the run is settled or the slice is not awaiting a brain call\n * (stale settle after boot / advance). PURE — `at` is the only clock.\n */\n function turn(\n s: State,\n result: AgentTurn,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const conv = requireAwaiting(s, \"llm\");\n if (conv === null) return [s, []];\n\n const withTurn: Conversation<R> = {\n ...conv,\n turns: [...conv.turns, result],\n };\n\n // ── No tool calls → the stage's loop is done → advance the pipeline. ──\n // `result` is the terminating turn — threaded into `advanceStage` so it can\n // be stamped as the run's `output` when this retire finishes the pipeline.\n if (result.toolCalls.length === 0) {\n return advanceStage({ ...s, conversation: withTurn }, result, at);\n }\n\n // ── Tool calls → scatter across fan-out (serial by default). ──\n // The fan-out item identity IS `callId` (`idOf`). A model that emits the\n // SAME `callId` twice in one turn is a defect: scattering both would launch\n // the consumer's `toolOf(call)` effect twice for one identity (the dup runs\n // TWICE) while a single settle Msg can only close ONE of the two `running`\n // entries — the other stays in flight forever and the batch never drains.\n // Collapse duplicates by `callId` (keep first occurrence) so every distinct\n // tool launches exactly once and each `callId` settles exactly once.\n const batch = dedupeByCallId(result.toolCalls);\n const [tools, launchCmds] = fan.scatter(\n initFanOut<ToolCall, ToolOutcome<R>>(),\n batch,\n );\n const nextConv: Conversation<R> = {\n ...withTurn,\n awaiting: { kind: \"tools\", batchTurn: withTurn.turnCount },\n };\n // An advance of the loop is progress — bump the monitored-run watchdog.\n const [runSlice] = run.progress(s.run, undefined, at);\n return [{ ...s, run: runSlice, tools, conversation: nextConv }, launchCmds];\n }\n\n /**\n * Advance the outer pipeline on a finished stage loop. Retire the current\n * stage (monitored-run `advance`); if the pipeline finished → `done`, else\n * seed a fresh conversation for the next stage and fire its first brain call.\n * Shared by `turn` (empty tool calls) so the loop-end → next-stage move lives\n * in one place. PURE.\n *\n * `terminatingTurn` is the empty-tool model turn that ended the current\n * stage's loop. When THIS retire finishes the whole pipeline (`done`), it is\n * the run's terminal output — stamped on `state.output` so it survives the\n * conversation clear and `runtime.result()` can read it (#46).\n */\n function advanceStage(\n s: State,\n terminatingTurn: AgentTurn,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice, runCmds] = run.advance(\n s.run,\n undefined,\n { kind: \"ok\" },\n at,\n );\n // Pipeline finished (or single-shot done) → no further brain call. The\n // terminating turn is the run's output; record it before clearing the\n // conversation so the result survives the retire (the field the deleted\n // `captureLastTurn` host hook used to reconstruct off the stream).\n if (runSlice.phase === \"done\") {\n return [\n { ...s, run: runSlice, conversation: null, output: terminatingTurn },\n runCmds,\n ];\n }\n // Next stage → fresh conversation + its first brain call.\n const conversation = freshConversation<R>();\n const moved: State = {\n ...s,\n run: runSlice,\n conversation,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n };\n const [fired, llmCmds] = fireBrainCall(moved, at);\n return [fired, [...runCmds, ...llmCmds]];\n }\n\n // === Verb: toolOk / toolErr ==============================================\n\n /**\n * Record a tool's success for `callId` and launch the next queued tool to\n * backfill the freed slot (the seed's queue-drain → next-tool). When the batch\n * drains, fold every gathered outcome into the conversation, bump the turn\n * count (livelock guard), and fire the next brain call — `awaiting` flips back\n * to `llm` (\"fold → llm\"). PURE.\n */\n function toolOk(\n s: State,\n callId: string,\n result: R,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return settleTool(s, callId, { kind: \"ok\", result }, at);\n }\n\n /**\n * Record a tool's failure for `callId` — symmetric to `toolOk`. A failed tool\n * still counts toward batch completion (the model sees the error reason and\n * recovers — \"errors are data\"); same fold → llm tail when the batch drains.\n * PURE.\n */\n function toolErr(\n s: State,\n callId: string,\n reason: string,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return settleTool(s, callId, { kind: \"error\", reason }, at);\n }\n\n /**\n * Shared tool-settle body: route the outcome into fan-out, fold the matching\n * call+outcome onto the conversation, and — if the batch is now complete —\n * fold the turn and fire the next brain call. PURE.\n */\n function settleTool(\n s: State,\n callId: string,\n outcome: ToolOutcome<R>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const conv = requireAwaiting(s, \"tools\");\n if (conv === null) return [s, []];\n\n // Find the original call (by id) so the folded record carries it. A settle\n // for an unknown / already-settled id is a no-op (fan-out also no-ops it).\n const call = s.tools.running.find((c) => c.callId === callId);\n if (call === undefined) return [s, []];\n\n const [tools, launchCmds] =\n outcome.kind === \"ok\"\n ? fan.itemOk(s.tools, callId, outcome)\n : fan.itemErr(s.tools, callId, outcome);\n\n const foldedConv: Conversation<R> = {\n ...conv,\n // Stamp the producing-turn index on the record (#85, A1). At settle time\n // `conv.turnCount` equals the index in `turns` of the turn that scattered\n // this batch (each prior drained batch bumped `turnCount` exactly once, and\n // each tool-bearing turn appended exactly one entry to `turns`), so a record\n // carrying `turn: conv.turnCount` is dropped iff its producing turn is folded\n // (`turn < N`) — the association the fold-back relies on.\n toolRecords: [\n ...conv.toolRecords,\n { call, outcome, turn: conv.turnCount },\n ],\n };\n\n // Batch still draining → record + keep launching the next queued tool.\n if (!fan.isComplete(tools)) {\n const [runSlice] = run.progress(s.run, undefined, at);\n return [\n { ...s, run: runSlice, tools, conversation: foldedConv },\n launchCmds,\n ];\n }\n\n // ── Batch drained → fold the turn → fire the next brain call. ──\n const turnedConv: Conversation<R> = {\n ...foldedConv,\n turnCount: foldedConv.turnCount + 1,\n awaiting: { kind: \"llm\" },\n };\n\n // Livelock guard: the bumped turn count crossing maxTurns → terminal fail.\n if (\n config.maxTurns !== undefined &&\n turnedConv.turnCount >= config.maxTurns\n ) {\n return failTurnLimit({ ...s, tools, conversation: turnedConv }, at);\n }\n\n // The tool ledger resets for the next turn's batch regardless of which\n // effect (compaction or brain call) fires next.\n const drained: State = {\n ...s,\n tools: initFanOut<ToolCall, ToolOutcome<R>>(),\n conversation: turnedConv,\n };\n\n // ── Compaction trigger (#85, design B1). BEFORE the next brain call, ask\n // the PURE policy how many oldest turns to fold. N > 0 → fire the dedicated\n // compaction round-trip INSTEAD of the brain call and flip awaiting to\n // `compacting`; the fold-back (`compact_ok`) then fires the brain call. The\n // trigger bumps the watchdog (compaction IS liveness, decision C) but does\n // NOT bump `turnCount` — it already bumped once for this drained batch, and\n // compaction is not model reasoning progress, so it never trips `maxTurns`.\n const compacting = maybeCompact(drained, at);\n if (compacting !== null) return compacting;\n\n // ── No compaction → fire the next brain call. ──\n // An advance of the loop is progress — bump the watchdog, then fire.\n const [runSlice] = run.progress(drained.run, undefined, at);\n const [fired, llmCmds] = fireBrainCall({ ...drained, run: runSlice }, at);\n return [fired, [...launchCmds, ...llmCmds]];\n }\n\n /**\n * The compaction trigger (#85, design B1) — PURE. Given the drained-batch\n * state about to fire a brain call, consult `config.compaction.planCompaction`\n * (the consumer's PURE heuristic). Returns:\n *\n * - `null` — no policy, or the policy returned `0`, or there is nothing to\n * fold (`< 2` turns: folding 0 or 1 turns into a summary cannot shrink the\n * transcript, so it is a no-op the trigger skips rather than spend a round\n * trip). The caller fires the brain call as normal.\n * - `[state, cmds]` — fire the dedicated compaction round-trip: flip\n * `awaiting` to `compacting { folding: N }`, bump the watchdog (liveness,\n * decision C — NOT `turnCount`, so `maxTurns` is untouched), and emit the\n * re-keyed `compact_run` Cmd. `compact_ok` folds the summary back; the loop\n * resumes with the next brain call there.\n *\n * `folding` is clamped to `turns.length` so a policy returning a count larger\n * than the transcript folds the WHOLE transcript into one summary (never more).\n * The launched `launchCmds` from the final tool settle are NOT this function's\n * concern — the caller composes them.\n */\n function maybeCompact(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] | null {\n const policy = config.compaction;\n const conv = s.conversation;\n if (policy === undefined || conv === null) return null;\n const requested = policy.planCompaction(conv);\n // Nothing to gain: a fold of 0 or 1 turns cannot shrink the transcript\n // (`turns[0..N]` → one summary turn only shrinks when N >= 2).\n const folding = Math.min(requested, conv.turns.length);\n if (folding < 2) return null;\n\n const compactConv: Conversation<R> = {\n ...conv,\n awaiting: { kind: \"compacting\", folding },\n };\n // Compaction is forward progress (liveness) — bump the watchdog, NOT the\n // turn count (decision C: it is not model reasoning, must not trip maxTurns).\n const [runSlice] = run.progress(s.run, undefined, at);\n const input = compactionCall(conv, folding);\n // The `compact` adapter re-keys the composed `resilient_run` Cmd(s) to the\n // dedicated `compact_run` discriminant so they route to the compaction\n // interpret cell, never the brain `resilient_run` one (the `with-resilience`\n // boundary-re-key pattern).\n const [compaction, cmds] = compact.attempt(\n s.compaction,\n COMPACTION_PURPOSE,\n input,\n at,\n );\n return [\n { ...s, run: runSlice, conversation: compactConv, compaction },\n cmds,\n ];\n }\n\n /** Terminal: the livelock guard tripped. Settle the run failed. PURE. */\n function failTurnLimit(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n return [{ ...s, failure: { reason: \"turn_limit\", at } }, []];\n }\n\n // === Verb: succeed / fail (brain-call resilient settles) =================\n\n /**\n * Fold a brain-call SUCCESS — the FIXED single entry the re-entered\n * `resilient_ok` settle Msg drives. Two halves, in order:\n *\n * 1. The RETRY layer: `llm.succeed` closes the breaker and DROPS this key's\n * retry counter. This is the half the old detached wiring skipped — the\n * detached handler dispatched the parsed turn directly and never\n * re-entered `resilient_ok`, so `succeed` never ran, the resilient slice\n * stayed stuck `running`, the breaker never closed, and the retry counter\n * ACCUMULATED across the run (a later transient failure would trip\n * `maxAttempts` prematurely). Running it here resets the retry slice every\n * turn — a clean retry slice across the whole run.\n * 2. The LOOP: fold the parsed `AgentTurn` (`msg.result.output`) through\n * `turn`, which scatters this turn's tools (or advances the pipeline on an\n * empty turn). One re-entered settle Msg now advances BOTH the resilient\n * slice AND the conversation, so the loop actually progresses to a\n * terminal `done`.\n *\n * PURE — `at` is the only clock.\n */\n function succeed(\n s: State,\n key: string,\n msg: AgentLlmOkMsg<P, O>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n // 1) Advance the retry layer — resets retry[key], closes the breaker.\n const [resilience, retryCmds] = llm.succeed(s.resilience, key, msg);\n const settled: State = { ...s, resilience };\n // 2) Fold the parsed turn into the loop (scatter tools / advance the stage).\n // `msg.result.output` is `O[P]`, and the `O extends Record<P, AgentTurn>`\n // bound pins every purpose's output to an `AgentTurn` — so it feeds `turn`\n // with NO cast. The rule lives in the type (invariant 8: no `as` past the\n // boundary), not in a doc-comment the compiler cannot enforce.\n const [withTurn, turnCmds] = turn(settled, msg.result.output, at);\n return [withTurn, [...retryCmds, ...turnCmds]];\n }\n\n /**\n * Record a brain-call failure: back off via the inherited retry (re-arming\n * the retry timer), or — when retry is exhausted / absent — the resilient\n * slice settles the call `failed`. The agent also stamps an `llm` failure on\n * its own slice so a consumer can render the terminal cause. PURE.\n */\n function fail(\n s: State,\n key: string,\n msg: AgentLlmErrMsg<P>,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [resilience, cmds] = llm.fail(s.resilience, key, msg);\n // If the resilient slice settled this call terminally (no retry pending),\n // surface the agent-level llm failure too. A `waiting_retry` phase means a\n // retry is armed → not terminal → leave `failure` untouched.\n const call = resilience.calls[key];\n const failure: AgentFailure | null =\n call?.phase === \"failed\"\n ? { reason: \"llm\", error: msg.error, at }\n : s.failure;\n return [{ ...s, resilience, failure }, cmds];\n }\n\n // === Verb: compactOk / compactErr (compaction resilient settles) =========\n\n /**\n * Fold the compaction SUMMARY back (#85, design A1) — the entry the re-entered\n * `compact_ok` settle Msg drives. Two halves, in order:\n *\n * 1. The RETRY layer: `compactRc.succeed` closes the compaction breaker and\n * DROPS the `$compact` retry counter (the same reset the brain `succeed`\n * does, on the dedicated compaction slice).\n * 2. The FOLD-BACK: replace `turns[0..folding]` AND every `toolRecord` whose\n * `turn < folding` with a SINGLE synthetic summary `AgentTurn` (no tool\n * calls, carrying the summary text), then RE-INDEX the surviving records'\n * `turn` so the new head (the summary) is index 0. `turnCount` is\n * UNCHANGED (compaction is not a model round-trip — decision C), and\n * `awaiting` flips back to `llm`. The next brain call fires on the shrunk\n * transcript — the loop the trigger paused resumes here.\n *\n * A no-op if the run is settled or not awaiting compaction (a stale settle).\n * PURE — `at` is the only clock.\n */\n function compactOk(\n s: State,\n key: string,\n msg: AgentCompactOkMsg,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n // 1) Advance the compaction retry layer — resets retry[$compact], closes the\n // compaction breaker. Reuses llm-call's `succeed` on the dedicated slice;\n // the enriched `LlmSucceedMsg` is the `compact_ok` payload as-is.\n const [compaction, retryCmds] = compact.succeed(s.compaction, key, {\n type: MsgType.ResilientOk,\n key: msg.key,\n result: msg.result,\n at: msg.at,\n });\n const settledRetry: State = { ...s, compaction };\n\n // Stale settle (the run is settled, or advanced/rebooted past this\n // compaction). The retry slice still resets above; emit only its cmds\n // (`succeed` never emits a run Cmd, so `retryCmds` is empty here).\n const conv = requireAwaiting(settledRetry, \"compacting\");\n if (conv === null) return [settledRetry, retryCmds];\n\n // 2) Fold-back. `folding` is the count the trigger pinned on `awaiting`; the\n // summary turn replaces those oldest turns + their records.\n const folding = conv.awaiting.folding;\n const summaryTurn: AgentTurn = {\n content: msg.result.output.summary,\n toolCalls: [],\n };\n const foldedConv = foldSummary(conv, folding, summaryTurn);\n // Resume the loop: fire the next brain call on the shrunk transcript.\n const [fired, llmCmds] = fireBrainCall(\n { ...settledRetry, conversation: foldedConv },\n at,\n );\n return [fired, [...retryCmds, ...llmCmds]];\n }\n\n /**\n * Record a compaction FAILURE (#85). Back off via the compaction slice's\n * inherited retry (re-arming the `$compact` retry timer), or — when retry is\n * exhausted / absent — PROCEED WITHOUT COMPACTING: flip `awaiting` back to\n * `llm` and fire the brain call on the (un-compacted) transcript. Compaction is\n * an OPTIMIZATION, not correctness: a failed summarize must not wedge or fail\n * the whole run (errors are data). This is the chosen option of design B1's\n * `compact_err` fork — it is strictly weaker than failing the run, and the\n * brain call's OWN resilient retry / the deadline watchdog still bound the\n * un-compacted continuation. A consumer that wants compaction failure to be\n * terminal can detect it on the `compaction` slice's `failed` phase. PURE.\n */\n function compactErr(\n s: State,\n key: string,\n msg: AgentCompactErrMsg,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [compaction, cmds] = compact.fail(s.compaction, key, {\n type: MsgType.ResilientErr,\n key: msg.key,\n error: msg.error,\n at: msg.at,\n });\n const settledRetry: State = { ...s, compaction };\n const call = compaction.calls[key];\n\n // A retry is armed (`waiting_retry`) → not terminal → keep awaiting the\n // re-issued compaction call (the re-keyed run Cmd, if any, rides here).\n if (call?.phase === \"waiting_retry\") {\n return [settledRetry, cmds];\n }\n\n // Stale settle (run settled, or advanced/rebooted past this compaction).\n // Past the `waiting_retry` guard `fail` emits no run Cmd, so `cmds` is empty.\n const conv = requireAwaiting(settledRetry, \"compacting\");\n if (conv === null) return [settledRetry, cmds];\n\n // Exhausted retry (or no retry) → proceed WITHOUT compacting: drop the\n // `compacting` state, fire the next brain call on the un-compacted transcript.\n const resumedConv: Conversation<R> = { ...conv, awaiting: { kind: \"llm\" } };\n const [fired, llmCmds] = fireBrainCall(\n { ...settledRetry, conversation: resumedConv },\n at,\n );\n return [fired, [...cmds, ...llmCmds]];\n }\n\n // === Verb: onTimer =======================================================\n\n /**\n * A timer fired — disambiguated by Sub id across the composed bricks:\n *\n * - a `monitored:safety:*` id → the no-progress watchdog → fail the run via\n * the inherited monitored-run `onDeadline`.\n * - a `resilient:*:$compact` id → a COMPACTION retry/deadline timer →\n * re-run the compaction call via the compaction slice's `onTimer`, re-keying\n * its re-issued `resilient_run` to the dedicated `compact_run` (#85).\n * - any other `resilient:*` id → a brain-call retry timer → re-run the brain\n * call via the inherited llm-call `onTimer`.\n *\n * Each brick `onTimer` / `onDeadline` verb tolerates a stale fire for another's\n * id (it no-ops on a non-matching id), so the routing is by id prefix/suffix.\n * PURE.\n */\n function onTimer(\n s: State,\n msg: AgentTimerMsg,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n if (msg.id.startsWith(\"monitored:\")) {\n const [runSlice] = run.onDeadline(s.run, msg);\n return [{ ...s, run: runSlice }, []];\n }\n // The compaction slice's timers are keyed on the reserved `$compact` purpose\n // (`resilient:retry:$compact` / `resilient:deadline:$compact`), distinct from\n // every brain purpose, so the suffix routes the fire to the right slice.\n if (msg.id.endsWith(`:${COMPACTION_PURPOSE}`)) {\n const [compaction, cmds] = compact.onTimer(s.compaction, msg);\n return [{ ...s, compaction }, cmds];\n }\n const [resilience, cmds] = llm.onTimer(s.resilience, msg);\n return [{ ...s, resilience }, cmds];\n }\n\n // === Verb: boot ==========================================================\n\n /**\n * Resume after a reload (cold wake) — the seed's boot reconcile, generalized.\n * Re-seeds the watchdog clock to `at` (a cold wake is not a no-progress wedge)\n * via monitored-run `boot`, then RE-EMITS the ONE outstanding effect derived\n * from `phase × awaiting`:\n *\n * - awaiting `llm` → re-fire the current stage's brain call (idempotent:\n * had the response been processed, the durable Model would already have\n * advanced + persisted, so boot re-emits the NEXT effect).\n * - awaiting `tools` → re-fire every in-flight tool Cmd (idempotent via\n * `callId` — the consumer's tool runner dedupes a re-issued call).\n * - awaiting `compacting` → re-fire the in-flight compaction call (#85),\n * idempotent at the compaction slice's gate exactly like the brain call.\n * - no conversation (between stages / settled) → no effect.\n *\n * A no-op on a settled run. PURE.\n */\n function boot(\n s: State,\n at: number,\n ): readonly [State, readonly AgentCmd<P, TC>[]] {\n const [runSlice] = run.boot(s.run, at);\n const rebooted: State = { ...s, run: runSlice };\n if (isSettled(rebooted)) return [rebooted, []];\n\n const conv = rebooted.conversation;\n if (conv === null) return [rebooted, []];\n\n if (conv.awaiting.kind === \"llm\") {\n // Re-fire the brain call. The resilient slice already tracks it `running`;\n // re-issuing the same key is idempotent at the gate (re-emits the run Cmd).\n return fireBrainCall(rebooted, at);\n }\n\n if (conv.awaiting.kind === \"compacting\") {\n // Re-fire the in-flight compaction round-trip (#85). The compaction slice\n // already tracks `$compact` running; re-issuing the same key is idempotent\n // at the gate, and the re-emitted `resilient_run` is re-keyed to `compact_run`.\n const input = compactionCall(conv, conv.awaiting.folding);\n const [compaction, cmds] = compact.attempt(\n rebooted.compaction,\n COMPACTION_PURPOSE,\n input,\n at,\n );\n return [{ ...rebooted, compaction }, cmds];\n }\n\n // awaiting tools → re-fire every running tool's effect Cmd.\n const cmds = rebooted.tools.running.map((call) => config.toolOf(call));\n return [rebooted, cmds];\n }\n\n // === Subs ================================================================\n\n /**\n * The merged subscription set — the brain-call retry timers (`../llm-call`),\n * the COMPACTION retry timers (the dedicated `$compact` slice, #85), and the\n * no-progress safety deadline (`../monitored-run`). All are `DeadlineSub`s\n * reconciled by id (the compaction timers are keyed `resilient:*:$compact`,\n * distinct from every brain timer), wired with one `subscribe: { deadline:\n * subscribeDeadline }` cell. PURE.\n */\n function subs(s: State): readonly DeadlineSub[] {\n return [\n ...llm.subs(s.resilience),\n ...compactRc.subs(s.compaction),\n ...run.subs(s.run),\n ];\n }\n\n // === Handlers ============================================================\n\n /**\n * The brain-call interpret handler — DETACHED, inherited from `../llm-call`.\n * It assembles messages, binds the purpose schema, invokes (retry composed),\n * parses, and dispatches the consumer's `onOk` / `onErr` Msg (carrying the\n * parsed `AgentTurn` for `onOk`).\n *\n * UNSAFE — kept ONLY as a deliberate escape hatch for the consumer that wires\n * the verbs by hand and wants the fire-and-forget dispatch shape. It does NOT\n * drive the inherited retry loop (it never re-enters the `resilient_ok` settle\n * Msg, so `succeed` / `fail` never run — the breaker never closes, the retry\n * counter never resets). The `unsafe` prefix is the warning the name carries:\n * `toMachine` is THE wired path (it uses the FIXED `brainHandlers` below, which\n * returns the settle Msg for re-entry and drives the loop correctly), and this\n * detached form is named `unsafeDetachedHandlers` so the broken-by-design\n * behaviour is visible at the call site, not buried in a doc-comment a consumer\n * meets only after autocomplete already offered it. A consumer reaches for it\n * only when it has accepted owning the retry wiring itself. See llm-call's\n * `handlers` doc (the same retry-loop gap).\n *\n * Returns the inherited detached shape verbatim (`AgentDetachedHandlers`) — a\n * fire-and-forget `resilient_run` cell, NOT an `Interpret` (it returns `void`\n * and takes the structural `{ waitUntil, dispatch }` ctx the detached form\n * runs the invoke against). The type is named precisely so no cast launders a\n * `void`-returning cell into the re-entry `Interpret` contract.\n *\n * The per-tool effects are NOT handled here — `config.toolOf` produces a Cmd\n * the consumer's OWN interpret performs (the agent never owns the tool I/O;\n * the seed's `send_tool_call` handler is the consumer's), routing Ok/Err back\n * to `toolOk` / `toolErr`. This matches fan-out's \"the consumer owns `of`'s\n * interpret\" discipline.\n */\n function unsafeDetachedHandlers<M>(\n ports: AgentPorts<P, O, M>,\n ): AgentDetachedHandlers<P, M> {\n return llm.handlers(ports);\n }\n\n /**\n * The FIXED brain-call interpret handler — the no-arg `../llm-call` form that\n * RETURNS the enriched resilient settle Msg (`resilient_ok` carrying the\n * parsed `LlmOk`, or `resilient_err` carrying the typed `LlmErr`). The\n * substrate enqueues an interpret handler's returned Msg as a FOLLOW-UP\n * (re-entry) onto the dispatch tail, so the machine's `resilient_ok` /\n * `resilient_err` reducer arms run `succeed` / `fail`, advancing the inherited\n * retry loop (succeed/fail → backoff → onTimer → re-issue) AND folding the\n * parsed turn into the conversation. This is the wiring that lets the loop\n * reach a clean terminal `done` with a reset retry slice — the headline L3 fix.\n */\n function brainHandlers<Ctx>(): Interpret<\n LlmSucceedMsg<P, O> | LlmFailMsg<P>,\n AgentLlmRunCmd<P>,\n Ctx\n > {\n // `llm.handlers()` is `{ resilient_run: (cmd: LlmRunCmd<P>) => Promise<\n // LlmSucceedMsg<P,O> | LlmFailMsg<P>> }`. That is structurally an\n // `Interpret` over the single `resilient_run` Cmd: the cell may ignore the\n // `ctx` param (a handler taking fewer args is assignable), and its returned\n // settle Msg is the exact `M` subset. No cast — the precise type holds.\n return llm.handlers();\n }\n\n /**\n * Wire the agent into a single runnable `defineMachine`. The host Msg union is\n * the closed set of verb entry points; `update` routes each to the matching\n * verb, `subscriptions` merges the two bricks' subs, `subscribe` wires the one\n * deadline cell, and `interpret` is the FIXED brain-call handler.\n *\n * The brain call uses the FIXED no-arg `../llm-call` handler (`brainHandlers`):\n * its returned `resilient_ok` / `resilient_err` settle Msg RE-ENTERS the\n * reducer, where the `resilient_ok` arm runs `succeed` (reset retry + close\n * breaker + fold the parsed turn) and the `resilient_err` arm runs `fail`\n * (back off via retry, re-arm the timer). This is what drives the loop to a\n * clean terminal `done` with a reset retry slice — fixing the L3 break where\n * the old detached handler dispatched the turn directly, never re-entered the\n * settle Msg, and so `succeed` never ran (stuck `running`, accumulating retry).\n *\n * The consumer supplies only the per-tool interpret (the agent owns the brain\n * interpret now; no `ports` to supply — the parsed turn is folded by `succeed`,\n * not by a consumer-built Msg).\n *\n * `HostMsg` is fixed to the agent's own verb-driven Msg union so the machine\n * is self-contained; a consumer needing extra Msgs wires the verbs by hand\n * instead (the knob contract is the escape hatch).\n */\n function toMachine<Ctx = object>(opts?: {\n /**\n * The consumer's interpret for the non-brain Cmds — the per-tool effect\n * `TC`, plus (ONLY when checkpointing is configured) the monitored-run\n * `snapshot_write` checkpoint cell. The brain `resilient_run` cell the agent\n * owns is merged in below, so the consumer supplies only the rest of the\n * config-derived `AgentCmd<P, TC, Snap>` union.\n *\n * The snapshot obligation is CONFIG-DERIVED (#55): `SnapshotInterpret`\n * resolves to a REQUIRED `snapshot_write` cell when `config.snapshotEvery`\n * is set (a real checkpoint write MUST be wired — never a silent no-op), and\n * to `{ snapshot_write?: never }` (the cell is FORBIDDEN — it can never fire)\n * when checkpointing is off. There is no default no-op: a non-checkpointing\n * consumer cannot even mention `snapshot_write`, and a checkpointing one must.\n */\n readonly toolInterpret?: Interpret<AgentMachineMsg<P, O, R>, TC, Ctx> &\n SnapshotInterpret<AgentMachineMsg<P, O, R>, boolean, Ctx> &\n CompactInterpret<AgentMachineMsg<P, O, R>, boolean, Ctx>;\n }): Machine<\n State,\n AgentMachineMsg<P, O, R>,\n AgentCmd<P, TC, boolean, boolean>,\n DeadlineSub,\n Ctx\n > {\n type M = AgentMachineMsg<P, O, R>;\n // The implementation is typed at `Snap = boolean` — the SUPERSET that\n // always includes the monitored-run checkpoint Cmd; the public OVERLOADS\n // narrow it to `true` / `false` and hand the consumer the precise obligation\n // (#55). `NonBrainCmd` is the consumer's per-tool `TC` plus that checkpoint\n // Cmd, and `ACmd` unions it with the brain Cmd — fully concrete (no pending\n // conditional), union-equal to `AgentCmd<P, TC, boolean>`, and built from the\n // SAME pieces `mergeInterpret` joins so the merge result is syntactically\n // `Interpret<M, ACmd, Ctx>` with no `Exclude`/conditional TS refuses to reduce.\n // `NonBrainCmd` is the consumer's half of the merged interpret — the per-tool\n // `TC`, the monitored-run checkpoint Cmd, AND the compaction `compact_run`\n // Cmd (#85). The consumer owns the `compact_run` cell (the summarize I/O,\n // returning `compact_ok` / `compact_err` for re-entry), exactly as it owns the\n // tool cells; the agent owns only the retry ORCHESTRATION (the slice verbs).\n // At `boolean` this is the SUPERSET; the overloads config-derive `compact_run`\n // IN (policy) or OUT (`{ compact_run?: never }`) of the obligation (#55 reuse).\n type NonBrainCmd = TC | MonitoredRunCmd<unknown> | AgentCompactRunCmd;\n type ACmd = AgentLlmRunCmd<P> | NonBrainCmd;\n // The FIXED brain handler returns the settle Msg for re-entry; the substrate\n // enqueues it as a follow-up dispatched back into `update` (the `resilient_*`\n // arms below). It is PRECISELY an `Interpret` over the brain Cmd\n // (`AgentLlmRunCmd<P>`); the consumer's `toolInterpret` is PRECISELY an\n // `Interpret` over the rest of the config-derived union (`TC`, and\n // `snapshot_write` only when snapshotting). `mergeInterpret` joins the two\n // disjoint halves into the full `Interpret<M, ACmd, Ctx>` — each key maps\n // precisely (`resilient_run` → the brain cell, `TC[\"type\"]` / `snapshot_write`\n // → the consumer's cells), with the one sound mapped-type identity isolated in\n // the helper rather than laundered through `as unknown as` here.\n //\n // No no-op `snapshot_write` default: with checkpointing off `SnapCmd` is\n // `never`, so the Cmd is config-derived OUT of `ACmd`, the consumer never\n // wires it, and the monitored-run slice never emits it — the\n // `snapshot_write: async () => undefined` ceremony (and the type lie it\n // masked) is gone (#55).\n const consumerInterpret = (opts?.toolInterpret ?? {}) as Interpret<\n M,\n NonBrainCmd,\n Ctx\n >;\n const interpret: Interpret<M, ACmd, Ctx> = mergeInterpret<\n M,\n NonBrainCmd,\n AgentLlmRunCmd<P>,\n Ctx\n >(consumerInterpret, brainHandlers<Ctx>());\n\n // Type the dispatch table explicitly so each cell gets its narrowed Msg\n // and the Reducer-form overload of `defineMachine` matches cleanly (the\n // agent State is not a discriminated union, so the Transitions overload's\n // `update` field collapses to `never` and would otherwise mask inference).\n // The verbs return `AgentCmd<P, TC>` — the `Snap = true` superset, because\n // they FORWARD whatever monitored-run emits and the verbs are not themselves\n // config-typed. The machine declares the config-derived `ACmd`; the one\n // narrowing (`update` below) is SOUND because a non-snapshotting run's\n // monitored-run slice provably never emits a `snapshot_write` Cmd, so the\n // forwarded array never carries the variant `ACmd` excludes.\n const update: Reducer<State, M, AgentCmd<P, TC>> = {\n [MsgType.AgentStart]: (s, m) => start(s, m.runId, m.at),\n [MsgType.AgentToolOk]: (s, m) => toolOk(s, m.callId, m.result, m.at),\n [MsgType.AgentToolErr]: (s, m) => toolErr(s, m.callId, m.reason, m.at),\n // The re-entered brain-call settle Msgs (from `brainHandlers`): success\n // runs `succeed` (reset retry + fold the turn), failure runs `fail`.\n [MsgType.ResilientOk]: (s, m) => succeed(s, m.key, m, m.at),\n [MsgType.ResilientErr]: (s, m) => fail(s, m.key, m, m.at),\n // The re-entered compaction settle Msgs (from the consumer's `compact_run`\n // cell, #85): `compact_ok` folds the summary back (drop oldest turns +\n // their records, fire the next brain call), `compact_err` backs off via the\n // compaction retry or proceeds without compacting.\n [MsgType.CompactOk]: (s, m) => compactOk(s, m.key, m, m.at),\n [MsgType.CompactErr]: (s, m) => compactErr(s, m.key, m, m.at),\n deadline_exceeded: (s, m) => onTimer(s, m),\n [MsgType.AgentBoot]: (s, m) => boot(s, m.at),\n };\n\n // Build the machine as a fully-typed `Machine<...>` const, then pass it\n // through `defineMachine`'s identity. Annotating the const resolves the\n // `Machine` type's conditional `interpret` requirement against the concrete\n // type params here; calling `defineMachine` with explicit type args instead\n // would defer that conditional over the generic `TC` and fail the overload.\n //\n // The machine's Cmd type is the config-derived `ACmd`. `update` is the\n // `AgentCmd<P, TC>` superset reducer; narrowing it to `Reducer<State, M,\n // ACmd>` is the SINGLE sound assertion of the snapshot derivation — a\n // non-snapshotting run never emits the `MonitoredRunCmd` variant `ACmd`\n // drops, so the reducer's emitted arrays provably stay within `ACmd[]`. This\n // is the same shape as `mergeInterpret`'s one sound mapped-type identity: the\n // soundness lives in a documented seam, not smuggled at every verb.\n const machine: Machine<State, M, ACmd, DeadlineSub, Ctx> = {\n init: (loaded) => (loaded !== null ? [loaded, []] : [init(), []]),\n update: update as Reducer<State, M, ACmd>,\n subscriptions: (s) => subs(s),\n subscribe: { deadline: subscribeDeadline },\n interpret,\n };\n return defineMachine(machine);\n }\n\n return {\n init,\n start,\n turn,\n toolOk,\n toolErr,\n succeed,\n fail,\n compactOk,\n compactErr,\n onTimer,\n boot,\n isSettled,\n currentStage,\n brainCall,\n subs,\n // `toMachine` is THE wired path. `unsafeDetachedHandlers` is the\n // hand-wiring escape hatch — named to advertise the retry-loop gap so it is\n // never mistaken for the loop driver (#54).\n toMachine,\n unsafeDetachedHandlers,\n };\n}\n\n/**\n * Re-export the deadline Sub primitives so consumers (and tests) wire one\n * import: `subscribeDeadline` is the `subscribe` cell, `deadlineSub` builds the\n * Sub literal both composed bricks' `subs` emit.\n */\nexport { subscribeDeadline, deadlineSub };\nexport type {\n LlmCall,\n LlmErr,\n LlmFailMsg,\n LlmOk,\n LlmRunCmd,\n LlmSucceedMsg,\n MessageLoader,\n ModelFactory,\n Schema,\n} from \"../llm-call\";\nexport type {\n DeadlineSub,\n MonitoredRunCmd,\n RunFailure,\n} from \"../monitored-run\";\n"]}