@tangle-network/agent-runtime 0.343.4 → 0.348.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{activation-C5rFWXGj.js → activation-BEGalhOL.js} +2 -2
- package/dist/{activation-C5rFWXGj.js.map → activation-BEGalhOL.js.map} +1 -1
- package/dist/{activation-NJiV0MHb.d.ts → activation-NQZP_mdI.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -3
- package/dist/{coordination-manager-T98ZbsEt.js → coordination-manager-Bm6leXc6.js} +22 -19
- package/dist/coordination-manager-Bm6leXc6.js.map +1 -0
- package/dist/{delegate-CjdtLf1v.js → delegate-Cp5-PsaX.js} +2 -2
- package/dist/{delegate-CjdtLf1v.js.map → delegate-Cp5-PsaX.js.map} +1 -1
- package/dist/durable.d.ts +7 -2
- package/dist/durable.js +127 -115
- package/dist/durable.js.map +1 -1
- package/dist/{graph-kgzTaNMA.js → graph-CE_pzU31.js} +5 -4
- package/dist/graph-CE_pzU31.js.map +1 -0
- package/dist/{improve-DevAd83a.js → improve-wT11zteg.js} +6 -6
- package/dist/{improve-DevAd83a.js.map → improve-wT11zteg.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -7
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +3 -3
- package/dist/kernel.d.ts +2 -2
- package/dist/kernel.js +11 -11
- package/dist/{loop-runner-D56Rpd2z.d.ts → loop-runner-CY5HHhtR.d.ts} +2 -2
- package/dist/{loop-runner-CyUoVMkv.js → loop-runner-CZzeeJTG.js} +2 -2
- package/dist/{loop-runner-CyUoVMkv.js.map → loop-runner-CZzeeJTG.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +5 -5
- package/dist/mcp/index.js.map +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{provision-supervisor-CysVhSqV.js → provision-supervisor-CC0HdOHo.js} +5 -5
- package/dist/{provision-supervisor-CysVhSqV.js.map → provision-supervisor-CC0HdOHo.js.map} +1 -1
- package/dist/{durable-file-DLcrzrjL.js → record-events-D93DkpAx.js} +100 -3
- package/dist/record-events-D93DkpAx.js.map +1 -0
- package/dist/{run-cancellation-CEDiqfhC.js → run-cancellation-CzFhQGMa.js} +11 -9
- package/dist/run-cancellation-CzFhQGMa.js.map +1 -0
- package/dist/{runtime-CefFtXC2.js → runtime-B_40dXlF.js} +270 -57
- package/dist/runtime-B_40dXlF.js.map +1 -0
- package/dist/{search-executor-t05_9Wwk.js → search-executor-COd2F2wp.js} +2 -2
- package/dist/{search-executor-t05_9Wwk.js.map → search-executor-COd2F2wp.js.map} +1 -1
- package/dist/{server-DjrVWzH2.js → server-BGB4R4wQ.js} +3 -3
- package/dist/{server-DjrVWzH2.js.map → server-BGB4R4wQ.js.map} +1 -1
- package/dist/{structural-rollout-CpJknIaL.js → structural-rollout-Wl_rCuzM.js} +2 -2
- package/dist/{structural-rollout-CpJknIaL.js.map → structural-rollout-Wl_rCuzM.js.map} +1 -1
- package/dist/{supervise-BuVVC7Bl.js → supervise-BUOeThuB.js} +122 -63
- package/dist/supervise-BUOeThuB.js.map +1 -0
- package/dist/{supervisor-D3M9ab1v.js → supervisor-DDy0aEtR.js} +438 -170
- package/dist/supervisor-DDy0aEtR.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +11 -11
- package/dist/{top-snapshot-BGYI6G6K.js → top-snapshot-CflmaDgk.js} +6 -4
- package/dist/top-snapshot-CflmaDgk.js.map +1 -0
- package/dist/tui/bin.js +2 -2
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +2 -2
- package/dist/{types-D0ZRqIJh.d.ts → types-hc4cmSc7.d.ts} +102 -13
- package/package.json +11 -11
- package/skills/agent-graphs/SKILL.md +38 -2
- package/dist/coordination-manager-T98ZbsEt.js.map +0 -1
- package/dist/durable-file-DLcrzrjL.js.map +0 -1
- package/dist/graph-kgzTaNMA.js.map +0 -1
- package/dist/run-cancellation-CEDiqfhC.js.map +0 -1
- package/dist/runtime-CefFtXC2.js.map +0 -1
- package/dist/supervise-BuVVC7Bl.js.map +0 -1
- package/dist/supervisor-D3M9ab1v.js.map +0 -1
- package/dist/top-snapshot-BGYI6G6K.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"durable-file-DLcrzrjL.js","names":["fsConstants"],"sources":["../src/content-digest.ts","../src/runtime/supervise/durable-file.ts"],"sourcesContent":["import { createHash } from 'node:crypto'\n\nexport function sha256(value: string): string {\n return createHash('sha256').update(value).digest('hex')\n}\n","/**\n * Small filesystem durability primitives for Runtime-owned state.\n *\n * Callers must validate their path and parent directory before invoking these functions.\n * The exclusive writer protects a no-clobber publication race; the atomic writer replaces one\n * state file after its temporary contents reach stable storage.\n *\n * @internal\n */\n\nimport { randomUUID } from 'node:crypto'\nimport {\n type BigIntStats,\n closeSync,\n existsSync,\n fchmodSync,\n constants as fsConstants,\n fstatSync,\n fsyncSync,\n linkSync,\n lstatSync,\n openSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n writeSync,\n} from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\n\ninterface DurableFileOptions {\n readonly mode?: number\n}\n\n/**\n * File content, or content computed from the new file's own stat when it must name the file's\n * inode (a lock record that later proves it was written for this very file).\n */\ntype DurableFileContent = string | ((file: BigIntStats) => string)\n\n/**\n * Publish a new file without replacing a concurrent winner. The published entry is a hard link\n * of the temporary file, so a content function sees the published file's inode.\n */\nexport function publishExclusiveDurableFile(\n filePath: string,\n content: DurableFileContent,\n options: DurableFileOptions = {},\n): boolean {\n const temporaryPath = `${filePath}.${randomUUID()}.tmp`\n let operationFailed = false\n let operationError: unknown\n let published = false\n try {\n writeExclusiveDurableFile(temporaryPath, content, options)\n try {\n linkSync(temporaryPath, filePath)\n syncDurableDirectory(dirname(filePath))\n published = true\n } catch (error) {\n if (!isAlreadyExistsError(error)) throw error\n }\n } catch (error) {\n operationFailed = true\n operationError = error\n }\n let cleanupError: unknown\n try {\n unlinkSync(temporaryPath)\n } catch (error) {\n if (!isNoEntryError(error)) cleanupError = error\n }\n if (operationFailed) throw operationError\n if (cleanupError !== undefined) throw cleanupError\n return published\n}\n\n/** Fsync a directory after publishing a durable file entry. */\nexport function syncDurableDirectory(directoryPath: string): void {\n const fd = openSync(directoryPath, 'r')\n try {\n fsyncSync(fd)\n } finally {\n closeSync(fd)\n }\n}\n\n/** Fsync one durable file after its contents reach stable storage. */\nfunction syncDurableFile(filePath: string, exactMode?: number): void {\n const fd = openSync(filePath, 'r')\n try {\n if (exactMode !== undefined && process.platform !== 'win32') fchmodSync(fd, exactMode)\n fsyncSync(fd)\n } finally {\n closeSync(fd)\n }\n}\n\n/** Append one record with O_APPEND, then fsync the file and containing directory. */\nexport function appendDurableFile(\n filePath: string,\n content: string,\n options: DurableFileOptions = {},\n): void {\n const flags =\n fsConstants.O_APPEND |\n fsConstants.O_CREAT |\n fsConstants.O_WRONLY |\n (typeof fsConstants.O_NOFOLLOW === 'number' ? fsConstants.O_NOFOLLOW : 0)\n const fd = openSync(filePath, flags, options.mode ?? 0o600)\n try {\n if (process.platform !== 'win32') fchmodSync(fd, options.mode ?? 0o600)\n const expectedBytes = Buffer.byteLength(content, 'utf8')\n const writtenBytes = writeSync(fd, content, undefined, 'utf8')\n if (writtenBytes !== expectedBytes) {\n throw new Error(\n `durable append wrote ${writtenBytes} of ${expectedBytes} bytes to '${filePath}'`,\n )\n }\n fsyncSync(fd)\n } finally {\n closeSync(fd)\n }\n syncDurableDirectory(dirname(filePath))\n}\n\n/** Reject a path that escapes its run directory or traverses a symbolic link. */\nexport function assertNoSymlinkDescendant(root: string, target: string, label = 'path'): void {\n const base = resolve(root)\n const exact = resolve(target)\n const rel = relative(base, exact)\n if (rel === '..' || rel.startsWith(`..${process.platform === 'win32' ? '\\\\' : '/'}`)) {\n throw new Error(`${label} path escapes its run directory`)\n }\n if (existsSync(base) && lstatSync(base).isSymbolicLink()) {\n throw new Error(`${label} path contains a symbolic link: ${base}`)\n }\n let current = base\n for (const part of rel.split(/[\\\\/]/u).filter(Boolean)) {\n current = join(current, part)\n if (!existsSync(current)) continue\n if (lstatSync(current).isSymbolicLink()) {\n throw new Error(`${label} path contains a symbolic link: ${current}`)\n }\n }\n}\n\n/** Write, fsync, atomically replace, and fsync one Runtime-owned state file.\n * preserveMode retains ordinary access permissions despite the current umask; a new\n * file keeps normal creation semantics. Callers still own path validation and write exclusion. */\nexport function writeAtomicDurableFile(\n filePath: string,\n content: string,\n options: DurableFileOptions & { readonly preserveMode?: boolean } = {},\n): void {\n const temporaryPath = `${filePath}.${randomUUID()}.tmp`\n let operationFailed = false\n let operationError: unknown\n try {\n let mode = options.mode\n let exactMode = false\n if (options.preserveMode) {\n try {\n mode = statSync(filePath).mode & 0o777\n exactMode = true\n } catch (error) {\n if (!isNoEntryError(error)) throw error\n }\n }\n writeExclusiveDurableFile(temporaryPath, content, { mode }, exactMode)\n renameSync(temporaryPath, filePath)\n syncDurableDirectory(dirname(filePath))\n } catch (error) {\n operationFailed = true\n operationError = error\n }\n let cleanupError: unknown\n try {\n unlinkSync(temporaryPath)\n } catch (error) {\n if (!isNoEntryError(error)) cleanupError = error\n // A successful rename removes the temporary directory entry.\n }\n if (operationFailed) throw operationError\n if (cleanupError !== undefined) throw cleanupError\n}\n\nfunction writeExclusiveDurableFile(\n filePath: string,\n content: DurableFileContent,\n options: DurableFileOptions,\n exactMode = false,\n): void {\n const fd = openSync(filePath, 'wx', options.mode ?? 0o666)\n try {\n const text = typeof content === 'string' ? content : content(fstatSync(fd, { bigint: true }))\n writeFileSync(fd, text, 'utf8')\n } finally {\n closeSync(fd)\n }\n syncDurableFile(filePath, exactMode ? options.mode : undefined)\n}\n\nfunction isAlreadyExistsError(error: unknown): boolean {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'EEXIST'\n )\n}\n\nfunction isNoEntryError(error: unknown): boolean {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ENOENT'\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-kgzTaNMA.js","names":[],"sources":["../src/runtime/supervise/graph.ts"],"sourcesContent":["/**\n *\n * `runGraph` — agent graphs: profiles as nodes, registry-backed prompt directives as edges.\n *\n * A topology is PLAIN DATA an agent can author in a few lines: nodes are canonical\n * `AgentProfile`s (the ONLY way a node is described — no role-builder functions), edges are typed\n * values carrying versioned {@link PromptHandle} directives, `deliverable` (termination) and\n * `budget` (one conserved pool) are mandatory. Driver↔worker is the two-node cyclic instance;\n * \"agent 3 analyzes 1 and 2 and reports to 1\" is ONE edge, not a framework.\n *\n * NOT A SECOND SCHEDULER. `runGraph` is an interpretation layer over what already runs:\n * `supervise()` is the execution core — the same `supervisorAgent`/`driverAgent` machinery,\n * backend-derived worker path (authorized, classified, recursive), conserved-pool budget, and\n * deliverable-gated settlement every\n * supervised run uses. (`runAgentRounds` is deliberately NOT the substrate here.) What the graph\n * layer ADDS is exactly what a bespoke driver loop never\n * had:\n *\n * 1. **Node pinning** — a spawn names a node (`profile.name` = node id) and the node's canonical\n * profile is what runs; a driver cannot smuggle capabilities into a worker it did not define.\n * 2. **Observable edges** — every delegates/analyzes/maps/routes traversal lands in an EDGE LEDGER\n * (`delivered | stripped | empty | unpropagated | failed`, with byte counts), in memory on\n * the result AND as `edge` events in the run journal. The motivating incident: a filter\n * silently replaced 1,700-char steering with 241 chars of boilerplate for three rounds and\n * NO artifact said so — an unobservable edge cannot be trusted and its directive cannot be\n * optimized.\n * 3. **Directives as data** — edge text lives in the prompt registry (`<surface>/v<n>`), so every\n * edge is a versioned optimization target, never prose hardcoded in a builder function.\n * 4. **Per-edge traversal caps** — the cyclic-graph backstop. A delegates edge whose cap is\n * exhausted REFUSES further traversals (fail loud), so a cycle cannot spin the pool dry.\n * 5. **Continuity as data** — a delegates edge may declare `continuity: 'resume'`, so each spawn\n * after the node's first re-attaches to its latest SETTLED session (the spawn context hands\n * the executor seam `resume: { ofWorker, sequence }`; the kernel keeps identity, ordering,\n * ledger truth, and the one conserved pool). Every ledger row states how its hop continued:\n * `'fresh' | 'resume'` for spawns, `'steer'` for mid-run deliveries — fresh respawns, session\n * resumes, and live steers are all plain data, each a ledgered fact.\n * 6. **Fan-out over a run-time list** — a `maps` edge takes the array a JSON pointer selects in a\n * node's settled result and runs one item per element, then hands the ordered results to a\n * join node. The runtime spawns every item and the join when the source settles, so the\n * driver spends no model turn on them; each item is a spawn through the same authorized path,\n * reserving from the same conserved pool, and every expansion, item and join is a ledger row.\n * 7. **Flow graphs** — with `entry` set, no node is a root: Runtime spawns the entries and fires\n * `routes` edges on each settle (`graph-flow.ts`), so a fixed order, a branch, a bounded repair\n * loop and a stop rule are graph data. The root manager is Runtime's own and never calls a\n * model; every entry and route spawn takes the same authorized path a map item takes.\n *\n * ORACLES ARE ENVIRONMENT, NEVER WORKERS. Graders/verifiers must not be spawnable in the graph —\n * a delegates edge to them leaks the rubric. An `analyzes` edge names its analyst in one of two\n * forms: a LENS id from the environment's registry (a pure function over trace evidence), or the\n * id of a graph NODE — a tool-equipped analyst AGENT spawned on each matching settle with the\n * node's pinned profile, whose settle output IS the findings. Either way the oracle doctrine\n * holds: an analyst node can never be a delegates target (refused loudly), so no driver can hand\n * it work, and an id living in both the registry and the nodes is refused as ambiguous.\n *\n * @experimental\n */\n\nimport { resolve } from 'node:path'\nimport { type AgentProfile, canonicalCandidateDigest } from '@tangle-network/agent-interface'\nimport { InMemoryResultBlobStore, InMemorySpawnJournal } from '../../durable/in-memory-spawn-stores'\nimport { FileSpawnJournal } from '../../durable/spawn-journal/journal-store'\nimport { FileResultBlobStore } from '../../durable/spawn-journal/result-blob-store'\nimport { ConfigError, ValidationError } from '../../errors'\nimport type { AnalystRegistry } from '../../mcp/tools/coordination-analysts'\nimport type { MakeWorkerAgent } from '../../mcp/tools/coordination-contracts'\nimport type { MapItemFailurePolicy } from '../../mcp/tools/coordination-map-contracts'\nimport type { ContinuityMode } from '../../mcp/tools/coordination-messages'\nimport type {\n GateDecision,\n GateDecisionRecord,\n GateRequest,\n RouteGate,\n RouteWhen,\n} from '../../mcp/tools/coordination-route-contracts'\nimport { composeRuntimeHooks, type RuntimeHooks } from '../../runtime-hooks'\nimport { harnessRunsAgent } from '../harness-role'\nimport type { ToolLoopChat } from '../tool-loop'\nimport type { DeliverableSpec } from './completion-gate'\nimport { runtimeFlowBrain } from './flow-brain'\nimport {\n createFlowRun,\n flowRootProfile,\n GraphRouteError,\n journaledGateDecider,\n routeFlowOf,\n validateFlowGraph,\n} from './graph-flow'\nimport { createGraphOverlay } from './graph-overlay'\nimport {\n graphRootProfile,\n type RootValidatedGraph,\n type ValidatedGraph,\n validateGraphTopology,\n} from './graph-topology'\nimport { kernelPromptRegistry, type PromptHandle, type PromptRegistry } from './prompt-registry'\nimport { withRunContext } from './run-context'\nimport {\n profileGuidanceComposer,\n type SuperviseOptions,\n supervise,\n superviseWithTestBrain,\n} from './supervise'\nimport type { Budget, NodeId, ResultBlobStore, SpawnJournal, SupervisedResult } from './types'\n\nexport type { MapItemFailurePolicy } from '../../mcp/tools/coordination-map-contracts'\nexport type {\n GateDecision,\n GateRequest,\n JsonScalar,\n RouteGate as GraphGate,\n RouteMatch,\n RouteWhen,\n} from '../../mcp/tools/coordination-route-contracts'\nexport { GraphRouteError } from './graph-flow'\nexport { defaultEdgeTraversalCap } from './graph-topology'\n\n// ── The algebra ────────────────────────────────────────────────────────────────\n\n/** A graph node: an id and a canonical `AgentProfile`. The profile is the ONLY way a node is\n * described — its `prompt.systemPrompt` is the standing role (the 0.117 canonical resolution;\n * never a legacy top-level-only reduction), its tools/mcp/resources are its capabilities. */\nexport interface GraphNode {\n readonly id: NodeId\n readonly profile: AgentProfile\n}\n\nexport type GraphEdge =\n /** Work flows down. The delegation directive is DATA → versionable, sweepable, optimizable.\n * Each spawn of `to` by `from` — and each mid-run steer from `from` to a live `to` worker —\n * is one traversal. */\n | {\n readonly kind: 'delegates'\n readonly from: NodeId\n readonly to: NodeId\n readonly directive: PromptHandle\n /** Cyclic-graph backstop: traversals beyond this REFUSE (fail loud). Default\n * {@link defaultEdgeTraversalCap}. */\n readonly maxTraversals?: number\n /** Default continuity for this edge's SPAWN traversals. `'resume'` makes every spawn after\n * the node's first re-attach to its most recent SETTLED worker: a NEW live worker whose\n * spawn context carries `resume: { ofWorker, sequence }` for the executor seam, spending\n * from the same conserved pool — the node's first spawn is effectively `'fresh'`, and a\n * spawn while a prior worker is still live refuses loudly (steer is the live channel).\n * The driver's per-call `spawn_worker` `continuity` argument overrides either way. Omit =\n * `'fresh'` (today's behavior, byte-identical). Caps count resumes exactly like fresh\n * spawns. */\n readonly continuity?: ContinuityMode\n }\n /** Findings flow anywhere: an analyst over N nodes' settled traces, delivered to ONE node.\n * With a LENS analyst the directive wraps the findings for the recipient; with a NODE analyst\n * the directive is the analyst agent's task and the findings are its settle output. */\n | {\n readonly kind: 'analyzes'\n /** The analyst REFERENCE, in one of two forms: a lens id resolved against\n * `RunGraphOptions.analysts` (environment), or the id of a graph NODE with no delegates\n * edge pointing at it — then each matching settle spawns that node's pinned profile as a\n * tool-equipped analyst WORKER (same spawn machinery, conserved budget, trace join) whose\n * task is this edge's directive plus the settled worker's trace evidence and whose settle\n * output is the findings. An id that is both a node and a registry lens is refused. */\n readonly analyst: string\n readonly over: ReadonlyArray<NodeId>\n readonly to: NodeId\n readonly directive: PromptHandle\n /** Observability cap: traversals beyond this are LEDGERED as exhausted (`unpropagated`).\n * Only delegates caps refuse traversal — they are what close the spawn cycle. */\n readonly maxTraversals?: number\n }\n /**\n * Fan-out over a list that exists only at run time, then one join. When `from` settles `done`,\n * the array at `pointer` in its result is expanded: each element becomes the TASK of one item\n * run, at most `concurrency` at a time, and once every item settled the `join` node runs with\n * `{ map, source, items, results: [{ index, item, result }], failures: [{ index, item, outcome,\n * reason }] }`, results in item order. The runtime spawns the items and the join (`from`'s\n * driver spends no turn on them) through the same authorized spawn path a delegates spawn\n * takes: each item reserves its budget from the one conserved pool and is pinned to the edge's\n * profile, so an item's content can never choose what runs.\n *\n * An item is either the node `to` (its pinned profile plus this edge's directive) or the nested\n * `graph`, started per item exactly as `run_graph` starts a graph. Refusals are loud and\n * ledgered, and the driver is woken with them: a pointer that does not resolve to an array, more\n * elements than `maxItems`, or a `concurrency` the run's worker-slot bound can never honor.\n * `concurrency` otherwise THROTTLES (items wait for a free place); it never refuses an item.\n *\n * An edge rather than a node-level spec, because every kernel invariant a map must keep already\n * attaches to edge traversal: pinning admits only the edge's item and join nodes (the spawn\n * context carries a runtime-authored `map` marker), each item is admitted like a spawn and\n * reserves from the conserved pool, each item settles under its own deliverable check, and each\n * expansion, item and join is a ledger row with its journal twin. Topology stays static; only the\n * traversal count is dynamic, so validation and the one-node-one-profile rule are unchanged.\n */\n | {\n readonly kind: 'maps'\n /** The source node: a delegates target, or the join of another maps edge. Each of its `done`\n * settles expands the map once. */\n readonly from: NodeId\n /** RFC 6901 JSON pointer into `from`'s settled result (`''` is the whole result). */\n readonly pointer: string\n /** The item node, run once per element with the element as its task. Exactly one of `to`\n * and `graph`. Reachable only through this edge: never a delegates target. */\n readonly to?: NodeId\n /** A graph run per element as one subtask, through the `run_graph` path. */\n readonly graph?: GraphTopology\n /** Receives the ordered results once every item settled. Reachable only through this edge. */\n readonly join: NodeId\n /** The item directive, appended to the item node's instructions per traversal. */\n readonly directive: PromptHandle\n /** Lists longer than this are refused before any item runs. */\n readonly maxItems: number\n /** How many items run at once. */\n readonly concurrency: number\n readonly onItemFailure: MapItemFailurePolicy\n /** Each item's budget, merged over the per-worker default as `spawn_worker`'s `budget` is. */\n readonly itemBudget?: Partial<Budget>\n }\n /**\n * A route in a flow graph (one with `entry`): Runtime traverses it when `from` settles, so no\n * root decides the order, the branch, the repair loop or the stop. On each usable settle of\n * `from` its outgoing routes edges are tried in declaration order and the first whose `when`\n * holds fires; an edge without `when` is the default branch and comes last. A node target is\n * spawned with `{ from: { node, result }, evidence: { [id]: latest usable result } }` (a join's\n * target with `{ from: { nodes }, evidence }`, see below) and the directive appended to its pinned instructions; `{ stop }` ends the run with no winner and\n * `GraphResult.stopped`; `{ finish }` makes this settle part of the run's output.\n *\n * A fork lists two or more nodes in `to`: one traversal spawns each of them at once, each under\n * its own key `route:<edge id>#<traversal>:<node>`. A join lists two or more nodes in `from`: it\n * fires once every member has settled usably since it last fired, and the target's task is\n * `{ from: { nodes: <members in declared order> }, evidence }` with each member's latest result\n * in `evidence`, so it does not depend on which member settled last and a resumed run derives the\n * same task. A routes edge that spawns a node with a settled worker in this flow (a back edge)\n * names that node's latest settled worker as the spawn's `successorOf`. A join carries no `when`, and it is the only routes edge\n * leaving each of its members. A route into a node that still has a running worker throws\n * {@link GraphRouteError} with reason `target-live`: converging branches use a join.\n */\n | {\n readonly kind: 'routes'\n readonly from: NodeId | ReadonlyArray<NodeId>\n readonly to:\n | NodeId\n | ReadonlyArray<NodeId>\n | { readonly stop: string }\n | { readonly finish: string }\n readonly directive: PromptHandle\n /** Absent on the default edge and on every join. A match reads `from` unless it names a node\n * in `evidence`. */\n readonly when?: RouteWhen\n /** Nodes whose latest usable result rides the target's task. */\n readonly evidence?: ReadonlyArray<NodeId>\n /** Traversals beyond this are skipped (ledgered `unpropagated`) and matching continues with\n * the next edge. Default {@link defaultEdgeTraversalCap}. Every routes cycle, each subcycle\n * included, must cross an edge that sets it. */\n readonly maxTraversals?: number\n /** `'resume'` re-attaches each spawn of the target to its latest settled session. Omit =\n * `'fresh'`. */\n readonly continuity?: ContinuityMode\n }\n\n/** A topology without the run's own budget and deliverable: the form a `maps` edge runs per item,\n * as `run_graph` runs it. With `entry` it is a flow graph. Inside a maps item, the item value is\n * the task of every entry whose task is the placeholder `{ item: true }`; a down settle inside the item ends\n * that item only, and the maps edge's `onItemFailure` decides the join. */\nexport interface GraphTopology {\n readonly nodes: ReadonlyArray<GraphNode>\n readonly edges: ReadonlyArray<GraphEdge>\n readonly entry?: AgentGraph['entry']\n /** Refused here: a maps item's graph and a `run_graph` subtask have no `decideGate`. */\n readonly gates?: AgentGraph['gates']\n}\n\nexport interface AgentGraph {\n readonly nodes: ReadonlyArray<GraphNode>\n readonly edges: ReadonlyArray<GraphEdge>\n /** Termination is mandatory, not optional: the independent completion oracle. */\n readonly deliverable: DeliverableSpec<unknown>\n /** One conserved pool across the whole graph — cycles without conservation never terminate. */\n readonly budget: Budget\n /** Setting it makes this a FLOW graph: Runtime spawns every entry at once, each with its task,\n * and traverses `routes` edges itself. No node is a root and no caller brain runs; the run's\n * output is `{ [node]: latest usable result }` over its terminal nodes and `finish` sources,\n * judged by `deliverable`. */\n readonly entry?: ReadonlyArray<{ readonly node: NodeId; readonly task: unknown }>\n /** Flow-graph vertices that are not agents: a routes edge into one awaits\n * `RunGraphOptions.decideGate`, and one edge per choice leaves it, matching\n * `{ pointer: '/choice', equals: <choice> }`. A `finish` leaving a gate outputs\n * `{ [gate]: { choice, by } }`. */\n readonly gates?: ReadonlyArray<RouteGate>\n}\n\n// ── The edge ledger ────────────────────────────────────────────────────────────\n\n/** `failed` is a maps item or join that ran and settled without a usable result (down, or\n * rejected by its deliverable check); a traversal that never reached a worker is `unpropagated`. */\nexport type EdgeDeliveryOutcome = 'delivered' | 'stripped' | 'empty' | 'unpropagated' | 'failed'\n\n/** How one ledgered hop CONTINUED: a spawn traversal stamps its effective spawn mode\n * (`'fresh'` | `'resume'`), and every mid-run delivery into an already-live recipient — a\n * driver steer leg and every analyzes delivery (routed steer or driver-destined finding) —\n * stamps `'steer'`. Zero ambiguity: every row carries exactly one of the three. */\nexport type TraversalContinuity = ContinuityMode | 'steer'\n\n/** One recorded edge traversal — the in-memory row; the journal twin is the `edge` SpawnEvent. */\nexport interface EdgeTraversal {\n /** Stable edge id: `delegates:<from>-><to>`, `analyzes:<analyst>:<over…>-><to>`,\n * `maps:<from>-><to | graph>-><join>`, `routes:<from>#<ordinal>-><to | stop:<reason> |\n * finish:<reason>>`, or `routes:entry-><node>` for an entry. */\n readonly edge: string\n readonly kind: 'delegates' | 'analyzes' | 'maps' | 'routes'\n readonly from: string\n readonly to: string\n /** The resolved directive reference (`<surface>/v<n>`). */\n readonly directive: string\n /** 1-based per-edge ordinal. */\n readonly traversal: number\n readonly outcome: EdgeDeliveryOutcome\n /** How this hop continued — see {@link TraversalContinuity}. */\n readonly continuity: TraversalContinuity\n /** Bytes of directive + payload that actually crossed the edge. */\n readonly bytes: number\n readonly reason?: string\n /** The concrete worker node id, once known. A maps expansion names the source worker. */\n readonly workerId?: string\n /** Present on maps rows: the expansion of the source's list, one item by its index, or the\n * join. */\n readonly map?: { readonly phase: 'expand' | 'item' | 'join'; readonly index?: number }\n /** Present on a gate's decision row (`gate:<id>`, `traversal` = visit): who decided, and what. */\n readonly gate?: GateDecisionRecord\n}\n\n/** A delegates edge exhausted its traversal cap and the run produced no winner: the cap, not the\n * task, ended it. Carries the full evidence so failing loud loses nothing. */\nexport class GraphEdgeCapError extends Error {\n readonly exhaustedEdges: ReadonlyArray<string>\n readonly ledger: ReadonlyArray<EdgeTraversal>\n readonly result: SupervisedResult<unknown>\n constructor(\n exhaustedEdges: ReadonlyArray<string>,\n ledger: ReadonlyArray<EdgeTraversal>,\n result: SupervisedResult<unknown>,\n ) {\n super(\n `runGraph: edge traversal cap exhausted on ${exhaustedEdges.join(', ')} and the run ` +\n 'delivered no winner — the cap (the cyclic-graph backstop), not the task, ended this run. ' +\n 'Raise maxTraversals on the edge or fix the cycle; the full edge ledger and the ' +\n 'supervised result ride on this error.',\n )\n this.name = 'GraphEdgeCapError'\n this.exhaustedEdges = exhaustedEdges\n this.ledger = ledger\n this.result = result\n }\n}\n\n// ── Options / result ───────────────────────────────────────────────────────────\n\n/**\n * Every `SuperviseOptions` key, partitioned by what `runGraph` does with it.\n *\n * `runGraph` starts one `supervise()` run, so every option that run honors is a graph option too\n * unless the graph itself owns the value. This used to be an opt-in list written by hand, and the\n * hand lost: 25 of 49 keys never reached `supervise()` from a graph, including `childSettleGraceMs`\n * (a root-driver failure tore down children that had ALREADY computed the deliverable) and\n * `driverRetry` (agent-runtime#963). Each absence was discovered by losing a run.\n *\n * The four lists below must cover `keyof SuperviseOptions` exactly. `everySuperviseOptionIsClassified`\n * below fails to COMPILE, naming the offender, when a key belongs to none of them — so the next\n * option added to `supervise()` cannot go missing here silently. It has to be classified, and\n * classifying it as forwarded is one word.\n */\n\n/** The graph derives these from the `AgentGraph` itself; a caller value would be overwritten. */\nconst GRAPH_OWNED_SUPERVISE_OPTIONS = [\n 'rootDriverFromBackend',\n 'resolveSpawnProfile',\n 'budget',\n 'deliverable',\n 'makeWorkerAgent',\n 'onCoordinationEvent',\n 'analyzeOnSettle',\n 'mapOnSettle',\n // A flow graph's entries and routes edges; its runtime-owned root runs them.\n 'routeFlow',\n 'continuityByProfile',\n // A graph pins every node and its delegation edges; a node never gains spawn rights it lacks.\n 'inheritSpawnRights',\n] as const\n\n/** Caller-facing on `RunGraphOptions`, but the graph wraps or defaults the value before it goes in:\n * `hooks` composes with the graph's own spawn-binding hook, `authorizeMessage` is wrapped so a\n * narrowed instruction ledgers `stripped`, `authorizeSpawn` runs AFTER the graph has pinned the\n * node (so a product sees the canonical profile, never the driver's stub), `makeLeafAgent` is the\n * caller's leaf override slotted under the graph's pinning, `analysts` rides only with analyze\n * routes, and `journal`/`blobs`/`runId` get graph defaults. */\nconst GRAPH_TRANSFORMED_SUPERVISE_OPTIONS = [\n 'hooks',\n 'authorizeMessage',\n 'authorizeSpawn',\n 'makeLeafAgent',\n 'analysts',\n 'journal',\n 'blobs',\n 'runId',\n // Replays a journaled decision before asking the caller.\n 'decideGate',\n] as const\n\n/** Not reachable from a graph, with the reason. `registry` is a NAME COLLISION, not a policy:\n * `RunGraphOptions.registry` is the directive `PromptRegistry` and `SuperviseOptions.registry` is\n * the `SuperviseRegistry` name→value table. Two different types under one name; the graph's wins.\n * Giving the supervise one a graph channel means renaming a public option, so it is recorded here\n * rather than silently dropped. */\nconst GRAPH_REFUSED_SUPERVISE_OPTIONS = ['registry'] as const\n\n/**\n * Forwarded to the root `supervise()` VERBATIM. Everything not owned, transformed, or refused\n * above belongs here — the default is \"a graph honors it\", not \"someone remembered to add it\".\n */\nconst GRAPH_FORWARDED_SUPERVISE_OPTIONS = [\n 'backend',\n // Forwarded: composes guidance into the root and into profiles a manager authors. The graph also\n // composes each PINNED node profile, because pinning replaces the composed `{ name }` stub.\n 'profileGuidance',\n // Forwarded, not graph-owned: a graph pins WHICH nodes run, never who answers a question one of\n // them raises. Without it a graph run's `ask_parent` would always report `no-parent` even when\n // the caller wired an inbox.\n 'escalateQuestion',\n 'rootHandle',\n 'signal',\n 'execution',\n 'resolveDeliverable',\n 'coordination',\n 'peerMail',\n 'peerAudit',\n 'traceTools',\n 'driverBackend',\n 'profileSecurity',\n 'authorizeSpawn',\n 'router',\n 'driveHarness',\n 'selectSeat',\n 'driverRetry',\n 'onDriverAttempt',\n 'workerRetry',\n 'onWorkerRetry',\n 'continuation',\n 'childSettleGraceMs',\n 'teardownConfirmMs',\n 'retainedAtSettlement',\n 'resolveDriveHarness',\n 'driveHarnessMaterialization',\n 'resolveSupervisorTools',\n 'extraTools',\n 'executeExtraTool',\n 'recoverExecutor',\n 'perWorker',\n 'reservationPolicy',\n 'deadlineCheckIn',\n 'budgetStopHoldMs',\n 'workerSlots',\n 'watchWorkers',\n 'stallAfterMs',\n 'wake',\n 'runDir',\n 'resume',\n 'segment',\n 'runContext',\n 'steerDir',\n 'stopRule',\n 'onProgressStop',\n 'maxDepth',\n 'maxTurns',\n 'compaction',\n 'now',\n 'allowedModels',\n 'finalizer',\n 'otel',\n // Forwarded: the registry a manager's `run_graph` resolves stored graphs against. A node of this\n // graph cannot start another graph (pinning refuses it), so it matters to no node here.\n 'graphRegistry',\n] as const\n\ntype ClassifiedSuperviseOption =\n | (typeof GRAPH_OWNED_SUPERVISE_OPTIONS)[number]\n | (typeof GRAPH_TRANSFORMED_SUPERVISE_OPTIONS)[number]\n | (typeof GRAPH_REFUSED_SUPERVISE_OPTIONS)[number]\n | (typeof GRAPH_FORWARDED_SUPERVISE_OPTIONS)[number]\n\n/**\n * Every key `RunGraphOptions` accepts, as data: the forwarded and transformed `SuperviseOptions`\n * keys, the name-colliding `registry`, and the graph's own `brain`. `GRAPH_OWNED_SUPERVISE_OPTIONS`\n * is deliberately absent — a caller value for one of those is overwritten by the graph, so it is\n * refused by name rather than discarded.\n *\n * The assignment below fails to COMPILE, naming the key, when `RunGraphOptions` declares something\n * this list does not carry.\n */\nconst runGraphOptionKeys = [\n ...GRAPH_FORWARDED_SUPERVISE_OPTIONS,\n ...GRAPH_TRANSFORMED_SUPERVISE_OPTIONS,\n ...GRAPH_REFUSED_SUPERVISE_OPTIONS,\n 'brain',\n] as const\n\ntype UnlistedRunGraphOption = Exclude<keyof RunGraphOptions, (typeof runGraphOptionKeys)[number]>\nconst everyRunGraphOptionIsListed: UnlistedRunGraphOption extends never\n ? true\n : UnlistedRunGraphOption = true\nvoid everyRunGraphOptionIsListed\n\nconst runGraphOptionKeySet: ReadonlySet<string> = new Set<string>(runGraphOptionKeys)\nconst graphOwnedOptionKeySet: ReadonlySet<string> = new Set<string>(GRAPH_OWNED_SUPERVISE_OPTIONS)\n\n/**\n * Refuse an option key the graph would not read, naming it and saying which kind it is.\n *\n * A graph-owned key is the sharper case: it type-checks against a widened `SuperviseOptions`\n * value, the graph derives its own value and overwrites the caller's, the run succeeds, and the\n * capability the caller asked for is not there. The rename of the leaf seam from `makeWorkerAgent`\n * to `makeLeafAgent` is the shape of the failure — the old name stayed a valid `SuperviseOptions`\n * key AND a graph-owned one, so a caller that kept passing it got a run with no leaf override and\n * no complaint.\n */\nfunction assertRunGraphOptionKeys(opts: RunGraphOptions): void {\n const graphOwned: string[] = []\n const unknown: string[] = []\n for (const key of Object.keys(opts)) {\n if (runGraphOptionKeySet.has(key)) continue\n if (graphOwnedOptionKeySet.has(key)) graphOwned.push(key)\n else unknown.push(key)\n }\n if (graphOwned.length > 0) {\n throw new ConfigError(\n `runGraph: ${graphOwned.sort().join(', ')} — the graph derives this from the AgentGraph ` +\n 'itself, so a caller value is overwritten and the capability it asks for would silently ' +\n 'be absent',\n )\n }\n if (unknown.length > 0) {\n throw new ConfigError(\n `runGraph: unknown option ${unknown.sort().join(', ')} — no reader consults that name, so ` +\n 'the value would be discarded and the capability it asks for would silently be absent',\n )\n }\n}\n\n/** A `SuperviseOptions` key in none of the four lists makes this assignment fail, and the compiler\n * error names the key. Classify it — `GRAPH_FORWARDED_SUPERVISE_OPTIONS` is usually the answer. */\ntype UnclassifiedSuperviseOption = Exclude<keyof SuperviseOptions, ClassifiedSuperviseOption>\nconst everySuperviseOptionIsClassified: UnclassifiedSuperviseOption extends never\n ? true\n : UnclassifiedSuperviseOption = true\nvoid everySuperviseOptionIsClassified\n\n/** `backend` and `driverBackend` keep graph-specific documentation below.\n *\n * Do not inherit and redeclare them through an indexed access type.\n * TypeScript 7 correctly treats `SuperviseOptions['backend']` as including `undefined`, which makes\n * that redeclaration wider than the exact optional property inherited from `SuperviseOptions`.\n */\ntype GraphInheritedSuperviseOption = Exclude<\n (typeof GRAPH_FORWARDED_SUPERVISE_OPTIONS)[number],\n 'backend' | 'driverBackend'\n>\n\n/** Copy every forwarded option the caller actually set. Absent stays absent: `supervise()` and the\n * graph must not disagree about what \"unset\" means. */\nfunction forwardedSuperviseOptions(\n opts: RunGraphOptions,\n): Pick<SuperviseOptions, (typeof GRAPH_FORWARDED_SUPERVISE_OPTIONS)[number]> {\n const forwarded: Record<string, unknown> = {}\n for (const key of GRAPH_FORWARDED_SUPERVISE_OPTIONS) {\n const value = (opts as Record<string, unknown>)[key]\n if (value !== undefined) forwarded[key] = value\n }\n return forwarded as Pick<SuperviseOptions, (typeof GRAPH_FORWARDED_SUPERVISE_OPTIONS)[number]>\n}\n\n/**\n * Options for one `runGraph` run.\n *\n * Extends every forwarded `SuperviseOptions` key, so a graph honors what a `supervise()` run\n * honors WITHOUT anyone restating it here. Only the graph-specific members and the ones whose\n * graph semantics differ are declared below; everything else inherits its type AND its\n * documentation from `SuperviseOptions`, which is the one owner of both.\n */\nexport interface RunGraphOptions extends Pick<SuperviseOptions, GraphInheritedSuperviseOption> {\n /** WHERE worker nodes run — the executor backend. Provide this OR `makeLeafAgent`. Forwarded to\n * `supervise()`, which derives every authorized leaf from it. A node that declares\n * `agent_runtime_coordination_spawn_worker` becomes a nested supervisor instead, whose own\n * leaves are derived the same way. */\n readonly backend?: Exclude<SuperviseOptions['backend'], undefined>\n /** WHERE the ROOT node's harness brain runs — forwarded to `supervise()` verbatim (see\n * `SuperviseOptions.driverBackend`). Needed when the root node's profile declares an external\n * harness (`codex`, `claude-code`, `opencode`): that root is driven by the harness, not by the\n * router brain, and automatic execution supports a local `bridge`. Unlike `supervise()`, this\n * does NOT default to `backend`: a graph's `backend` places WORKER nodes, so the root driver\n * is selected only by this field. Omit = no harness driver, which is correct for a root whose\n * `profile.harness` is omitted or `cli-base` (that root runs on the router brain). */\n readonly driverBackend?: Exclude<SuperviseOptions['driverBackend'], undefined>\n /** Leaf-execution override (offline tests / advanced). `runGraph` still owns node pinning,\n * directive delivery, and the edge ledger AROUND this seam — only the leaf `act` is yours.\n * Slots INSIDE the kernel's authorized path (`SuperviseOptions.makeLeafAgent`), so a node that\n * declares the spawn tool still becomes a nested supervisor even under an offline leaf. */\n readonly makeLeafAgent?: MakeWorkerAgent\n /** The ROOT driver's inference seam — a caller-owned `ToolLoopChat` that makes every root\n * model call. Use it when the root's decisions must be caller-owned orchestration (a\n * deterministic conversation driver, a persona loop with its own LLM calls) rather than a\n * router-derived model call. The graph machinery around the seam is unchanged: node pinning,\n * directive delivery, the edge ledger, and the journal twin all run the same shipped path,\n * and the root profile keeps prompt control (`prompt-control-execution` materialization —\n * `systemPrompt`/`instructions` still apply). What moves to the caller with the brain:\n * model selection and provider-identity validation (`expectedModel` cannot be enforced on a\n * call the runtime did not place) and per-turn usage reporting (a brain that reports no\n * usage meters nothing into the pool). Omit = the router brain derived from the root\n * profile — the unchanged default. Mutually exclusive with `driverBackend`, and refused\n * when the root profile declares an external harness (that root is driven BY the harness). */\n readonly brain?: ToolLoopChat\n /** Caller-side runtime hooks (telemetry, policy, product extensions). Composed AFTER the\n * graph's own spawn-binding hook on the SAME event stream — the graph never swallows the\n * seam supervise() exposes. */\n readonly hooks?: RuntimeHooks\n /** The analyst lens registry `analyzes` edges resolve against. ENVIRONMENT — needed only for\n * lens analysts; an analyzes edge naming a graph NODE as its analyst needs no registry. */\n readonly analysts?: AnalystRegistry\n /** Answers a flow gate while the process holds the run; the wait counts against its deadline.\n * ENVIRONMENT, like `analysts`; required when the graph declares gates. */\n readonly decideGate?: (request: GateRequest) => Promise<GateDecision>\n /** Directive registry. Default: the seeded kernel registry (`kernelPromptRegistry()`).\n *\n * NOT `SuperviseOptions.registry`, which is the `SuperviseRegistry` name→value table for\n * code-valued options. The two share a name and nothing else, and this one wins here — see\n * `GRAPH_REFUSED_SUPERVISE_OPTIONS`. */\n readonly registry?: PromptRegistry\n /** The run journal the edge ledger and every spawn/settle ride. Default: in-memory. */\n readonly journal?: SpawnJournal\n readonly blobs?: ResultBlobStore\n readonly runId?: string\n /** Product authority over every steer/answer instruction (the filter seam). `runGraph` observes\n * what it CHANGES: a narrowed instruction ledgers its steer traversal as `stripped`. */\n readonly authorizeMessage?: SuperviseOptions['authorizeMessage']\n}\n\nexport interface GraphResult<Out = unknown> {\n readonly result: SupervisedResult<Out>\n /** Every edge traversal, in occurrence order — the observable-edge contract. */\n readonly ledger: ReadonlyArray<EdgeTraversal>\n /** Edge ids whose traversal cap was hit — analyzes exhaustion included (observable here, never\n * a refusal). A DELEGATES cap paired with a `no-winner` result THROWS\n * ({@link GraphEdgeCapError}) instead of returning: only delegates caps refuse spawns, so only\n * they can have ended the run. A LIFECYCLE no-winner (`aborted` / `budget-exhausted`) returns\n * normally even with an exhausted delegates cap — the abort or the pool, not the cap, ended\n * that run, and the exhaustion stays observable here. */\n readonly exhaustedEdges: ReadonlyArray<string>\n readonly runId: string\n /** Why a flow graph ended early: a `stop` edge fired (`edge` names it), or a flow node settled\n * down (no `edge`; `reason` is `down: <worker reason>`) or, where a route was needed, without a\n * usable result (no `edge`; `reason` is `unusable: <why>`). Live flow workers are aborted. */\n readonly stopped?: {\n readonly edge?: string\n readonly at: NodeId\n readonly workerId: string\n readonly reason: string\n }\n}\n\n/** `RunGraphOptions` with the brain REQUIRED — the shape the `/testing` entry's\n * `runGraphWithTestBrain` keeps accepting now that `brain` is a production option. */\nexport interface RunGraphTestOptions extends RunGraphOptions {\n readonly brain: ToolLoopChat\n}\n\n// ── Validation ─────────────────────────────────────────────────────────────────\n\n/** Validate the graph and resolve every directive BEFORE any compute is spent — an invalid\n * topology or an unknown directive is a configuration fault, never a mid-run surprise. */\nfunction validateGraph(\n graph: AgentGraph,\n registry: PromptRegistry,\n analysts: AnalystRegistry | undefined,\n): ValidatedGraph {\n if (graph.entry === undefined) {\n if (!Array.isArray(graph.nodes) || graph.nodes.length === 0) {\n throw new ValidationError('runGraph: graph.nodes must be a non-empty array')\n }\n if (!Array.isArray(graph.edges) || graph.edges.length === 0) {\n throw new ValidationError('runGraph: graph.edges must be a non-empty array')\n }\n }\n if (typeof graph.deliverable?.check !== 'function') {\n throw new ValidationError('runGraph: graph.deliverable is mandatory (termination oracle)')\n }\n if (typeof graph.budget !== 'object' || graph.budget === null) {\n throw new ValidationError('runGraph: graph.budget is mandatory (the conserved pool)')\n }\n if (graph.entry !== undefined) return validateFlowGraph(graph, registry, analysts)\n if (graph.gates !== undefined)\n throw new ValidationError('runGraph: graph.gates needs graph.entry')\n return validateGraphTopology(graph.nodes, graph.edges, registry, analysts)\n}\n\n// ── The runner ─────────────────────────────────────────────────────────────────\n\n/**\n * Execute an {@link AgentGraph}. A flow graph (`entry` set) runs from its entries and routes edges\n * under a runtime-owned root that places no model call. Otherwise the root node becomes the\n * supervisor (`supervise()` — the execution core), each worker node is spawnable BY NODE ID\n * (`spawn_worker` with `profile: { name: '<node id>' }`; the node's canonical profile is pinned by\n * the graph), each\n * delegates directive is appended to the worker profile's `prompt.instructions` per traversal,\n * and each analyzes edge becomes an analyst-on-settle route with a real DESTINATION. Every\n * traversal is ledgered and journaled.\n */\nexport function runGraph(graph: AgentGraph, opts: RunGraphOptions): Promise<GraphResult> {\n const { brain, ...runtimeOptions } = opts\n return superviseAgentGraph(graph, runtimeOptions, brain)\n}\n\n/** Alias for graph tests written before `RunGraphOptions.brain` was production. The production\n * entry accepts the same shape; this wrapper only keeps the `/testing` import path working. */\nexport function runGraphWithTestBrain(\n graph: AgentGraph,\n opts: RunGraphTestOptions,\n): Promise<GraphResult> {\n const { brain, ...runtimeOptions } = opts\n return superviseAgentGraph(graph, runtimeOptions, brain)\n}\n\n/**\n * The graph supervise run, as its own entry: the engine's `run-graph` preset node executes exactly\n * this, so the preset and `runGraph` are the same code path by construction (agent-runtime#982).\n */\n/**\n * Every refusal a graph earns before any compute, in one place: the authoring contract. `runGraph`\n * calls it FIRST so a malformed graph throws synchronously, exactly as it did before the engine\n * preset (agent-runtime#982) moved execution behind a promise.\n */\nexport function assertRunGraphAuthoring(\n graph: AgentGraph,\n opts: RunGraphOptions,\n brain?: ToolLoopChat,\n): ReturnType<typeof validateGraph> {\n assertRunGraphOptionKeys(opts)\n const registry = opts.registry ?? kernelPromptRegistry()\n const validated = validateGraph(graph, registry, opts.analysts)\n const requireLeaves = (): void => {\n if (!opts.backend && !opts.makeLeafAgent) {\n throw new ValidationError(\n 'runGraph: provide opts.backend (where nodes run) or opts.makeLeafAgent',\n )\n }\n }\n if (validated.flow !== undefined) {\n // A flow's root is Runtime's own: nothing a caller sets for a root manager has a reader.\n const rootOptions = [\n ...(brain ? ['brain'] : []),\n ...(['driverBackend', 'finalizer', 'maxTurns', 'compaction'] as const).filter(\n (key) => opts[key] !== undefined,\n ),\n ]\n if (rootOptions.length > 0) {\n throw new ValidationError(\n `runGraph: ${rootOptions.join(', ')} with graph.entry — a flow graph has no root ` +\n 'manager: Runtime spawns its entries and traverses its routes edges, and the graph ' +\n \"owns the run's output\",\n )\n }\n if ((graph.gates?.length ?? 0) > 0 && opts.decideGate === undefined) {\n throw new ValidationError('runGraph: graph.gates needs opts.decideGate to answer them')\n }\n requireLeaves()\n return validated\n }\n const { root } = validated as RootValidatedGraph\n // A caller brain and a harness driver are two answers to WHO makes the root's calls: refuse the\n // contradiction before any compute, and refuse a harness-driven root outright — the harness IS\n // that root's brain, so a supplied one would be silently ignored downstream.\n if (brain && opts.driverBackend) {\n throw new ValidationError(\n 'runGraph: brain and driverBackend are mutually exclusive — a caller brain makes the root model calls, a driverBackend places a harness that makes its own',\n )\n }\n if (brain && harnessRunsAgent(root.profile.harness)) {\n throw new ValidationError(\n `runGraph: root node '${root.id}' declares harness '${root.profile.harness}', so the harness drives it — a caller brain applies only to a router-brained root (profile.harness omitted or 'cli-base')`,\n )\n }\n requireLeaves()\n return validated\n}\n\nexport function superviseAgentGraph(\n graph: AgentGraph,\n opts: RunGraphOptions,\n brain?: ToolLoopChat,\n): Promise<GraphResult> {\n const registry = opts.registry ?? kernelPromptRegistry()\n if (opts.runContext?.acquire !== undefined) {\n return withRunContext(opts.runContext, opts.signal, (runContext, signal) =>\n superviseAgentGraph(\n graph,\n {\n ...opts,\n runContext,\n ...(signal === undefined ? {} : { signal }),\n },\n brain,\n ),\n )\n }\n const validated = assertRunGraphAuthoring(graph, opts, brain)\n // A flow graph: Runtime schedules its nodes, and its root manager is Runtime's own.\n const flow = validated.flow === undefined ? undefined : createFlowRun()\n // A durable graph needs its journal AND blob store on disk. `supervise()` already resolves this\n // for its own context (`options.journal ?? createFileRunContext(runDir).journal`), but the graph\n // passes an explicit `journal`/`blobs` — the edge ledger's twin writes ride on it — so the graph\n // must do the same resolution itself or its in-memory default SHADOWS the file stores supervise\n // would have built: `runGraph({ runDir })` journaled only to the process, a second process\n // silently restarted the run from scratch, and `runDir/spawn-journal.jsonl` never existed.\n // Layout owner: `createFileRunContext` (run-context.ts); keep these paths byte-identical to it.\n const journal =\n opts.journal ??\n opts.runContext?.journal ??\n (opts.runDir !== undefined\n ? new FileSpawnJournal(`${resolve(opts.runDir)}/spawn-journal.jsonl`)\n : new InMemorySpawnJournal())\n const blobs =\n opts.blobs ??\n opts.runContext?.blobs ??\n (opts.runDir !== undefined\n ? new FileResultBlobStore(`${resolve(opts.runDir)}/blobs`)\n : new InMemoryResultBlobStore())\n const runId =\n opts.runId ??\n opts.runContext?.runId ??\n `graph-${canonicalCandidateDigest(graph.nodes.map((n) => n.id)).slice('sha256:'.length, 'sha256:'.length + 12)}`\n const now = opts.now ?? Date.now\n\n // The graph layer: node pinning, analyst routes, continuity defaults and the edge ledger. A\n // `run_graph` subtask builds the same overlay around its nested manager.\n // `profileGuidance` composes the profile a manager authors, but a graph then swaps that\n // `{ name }` stub for the pinned node profile. Compose the pinned profile too, so every node\n // that runs carries its harness and model guidance. Composition is idempotent.\n const guidance = profileGuidanceComposer(opts.profileGuidance)\n const overlay = createGraphOverlay(validated, {\n registry,\n journal,\n runId,\n now,\n ...(guidance ? { guidance } : {}),\n ...(opts.authorizeSpawn ? { authorizeSpawn: opts.authorizeSpawn } : {}),\n })\n // Always present: the kernel refuses steer/answer whenever spawn authorization is on (the\n // graph's pinning IS spawn authorization), so a graph with no caller filter passes instructions\n // through unchanged rather than losing its steer channel. Only a caller filter can strip.\n const callerAuthorizeMessage = opts.authorizeMessage\n const authorizeMessage = overlay.observeMessages<\n Parameters<NonNullable<SuperviseOptions['authorizeMessage']>>[0]\n >((input) =>\n callerAuthorizeMessage ? callerAuthorizeMessage(input) : { instruction: input.instruction },\n )\n\n // ── Spawn-hook: bind ledger rows to concrete worker ids, then journal them ──\n const graphHooks: RuntimeHooks = {\n onEvent: (event) => {\n if (event.target !== 'agent.spawn' || event.phase !== 'after') return\n const payload = event.payload as { childId?: unknown; assignmentId?: unknown } | undefined\n if (typeof payload?.childId !== 'string' || typeof payload.assignmentId !== 'string') return\n return overlay.bindSpawn(event.parentId, payload.assignmentId, payload.childId)\n },\n }\n const hooks = composeRuntimeHooks(graphHooks, opts.hooks)\n const rootProfile =\n flow === undefined\n ? graphRootProfile(validated as RootValidatedGraph, registry)\n : flowRootProfile\n const rootBrain = flow === undefined ? brain : runtimeFlowBrain()\n const task =\n flow === undefined\n ? graphTask(graph, (validated as RootValidatedGraph).root)\n : (graph.deliverable.describe ?? 'Runtime runs this flow graph from its entries.')\n\n // Every configuration fault above throws SYNCHRONOUSLY (matching `supervise()`'s own\n // contract); only the run itself is asynchronous.\n const start = async (): Promise<GraphResult> => {\n const superviseOptions = {\n // Every forwarded option the caller set, including the ones nobody thought to list here.\n // `backend` rides along: the kernel derives every authorized LEAF from it, under the graph's\n // pinning. The root driver stays an explicit `driverBackend` choice: `rootDriverFromBackend:\n // false` stops supervise() defaulting one from the other, so where workers run never selects\n // where the root runs (the axis split every graph caller relies on).\n ...forwardedSuperviseOptions(opts),\n rootDriverFromBackend: false,\n // Graph-owned values come after the spread: the graph, not the caller, decides these.\n budget: graph.budget,\n deliverable: graph.deliverable,\n authorizeSpawn: overlay.authorizeSpawn,\n resolveSpawnProfile: overlay.resolveSpawnProfile,\n inheritSpawnRights: false,\n ...(opts.makeLeafAgent ? { makeLeafAgent: opts.makeLeafAgent } : {}),\n journal,\n blobs,\n runId,\n hooks,\n onCoordinationEvent: async (\n context: { readonly depth: number },\n _eventId: unknown,\n record: { readonly event: Parameters<typeof overlay.onCoordinationEvent>[0] },\n ) => {\n // A route event belongs to the flow of the manager that published it: a flow inside a\n // maps item or a run_graph subtask ledgers and concludes its own.\n if (record.event.type === 'route' && context.depth !== 0) return\n overlay.onCoordinationEvent(record.event)\n flow?.observe(record.event)\n },\n // Lens routes resolve against the registry; agent routes carry their own analyst profile,\n // so a graph whose only analysts are nodes needs no registry at all.\n ...(overlay.routes.length > 0\n ? {\n analyzeOnSettle: overlay.routes,\n ...(opts.analysts ? { analysts: opts.analysts } : {}),\n }\n : {}),\n ...(overlay.maps.length > 0 ? { mapOnSettle: overlay.maps } : {}),\n ...(Object.keys(overlay.continuityByProfile).length > 0\n ? { continuityByProfile: overlay.continuityByProfile }\n : {}),\n // A flow root's wake batches nothing for a decision, so it ends its turn on the first event.\n ...(flow === undefined\n ? {}\n : {\n routeFlow: routeFlowOf(validated),\n ...(opts.decideGate && {\n decideGate: journaledGateDecider(opts.decideGate, journal, runId),\n }),\n finalizer: flow.finalizer,\n wake: { debounceMs: 0, ...opts.wake },\n }),\n authorizeMessage,\n } satisfies SuperviseOptions\n // The flow root reaches supervise through the same brain seam a caller brain takes.\n const supervised =\n rootBrain === undefined\n ? await supervise(rootProfile, task, superviseOptions)\n : await superviseWithTestBrain(rootProfile, task, { ...superviseOptions, brain: rootBrain })\n\n const { ledger, exhaustedEdges, exhaustedDelegates } = await overlay.settle()\n const concluded = flow?.conclude(supervised)\n if (concluded?.kind === 'unrouted') {\n throw new GraphRouteError(concluded.unrouted, ledger, supervised)\n }\n const result = concluded?.result ?? supervised\n const stopped = concluded?.stopped\n // A LIFECYCLE ending (caller abort, exhausted budget, deadline) is its own complete explanation: the\n // cap did not end that run even when it was exhausted along the way, and blaming it would\n // misattribute the ending (and turn a caller-initiated abort into a throw). The exhaustion\n // stays observable in `exhaustedEdges` either way.\n const lifecycleEnded =\n result.kind === 'no-winner' &&\n (result.reason === 'aborted' ||\n result.reason === 'cancelled' ||\n result.reason === 'budget-exhausted' ||\n result.reason === 'deadline')\n if (result.kind !== 'winner' && !lifecycleEnded && exhaustedDelegates.length > 0) {\n // Fail LOUD: the backstop, not the task, ended this run. The evidence rides on the error.\n // Only DELEGATES caps refuse spawns, so only they can be the cause named here.\n throw new GraphEdgeCapError(exhaustedDelegates, ledger, result)\n }\n return { result, ledger, exhaustedEdges, runId, ...(stopped ? { stopped } : {}) }\n }\n\n return start()\n}\n\n/** The root task: the graph's own framing. The deliverable (mandatory) is the termination; the\n * task names what the topology exists to produce. */\nfunction graphTask(graph: AgentGraph, root: GraphNode): string {\n const describe = graph.deliverable.describe\n return (\n describe ?? `Deliver the graph's deliverable by driving your worker nodes (root: '${root.id}').`\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run-cancellation-CEDiqfhC.js","names":[],"sources":["../src/runtime/supervise/run-layout.ts","../src/runtime/supervise/run-cancellation.ts"],"sourcesContent":["/**\n * The on-disk supervisor-run layout: `<root>/.agent/supervisor/<id>`.\n *\n * This is the durable, cross-process face of a supervisor run — the counterpart to the in-process\n * `Inbox` seam in `./inbox`. A run persists its state under one directory so that any OTHER process\n * can find it after the fact: `@tangle-network/traces` reads exactly this layout via\n * `traces analyze --supervisor-run-dir`, a restarted host can rehydrate a run it no longer holds\n * handles to, and a human can steer a live worker by appending one NDJSON line. Until now the\n * layout was defined only in the unpublished `loops` repo (`src/supervisor-control.ts`) — a\n * published reader depending on an unpublished writer's convention — so the contract is promoted\n * here, names preserved.\n *\n * `.agent` is the one dot-dir for ALL agent-owned state (skills already write\n * `.agent/hypotheses/`, `.agent/skill-runs.jsonl`); supervisor runs live beside them rather than\n * under a product-branded dir. Runs written by older writers used `.loops/supervisor/<id>` —\n * readers that must see those keep a legacy fallback; this writer never creates `.loops` again.\n *\n * Layout, relative to `supervisorRunDir(root, id)`:\n *\n * steers/requests/<hash>.json one exact, caller-idempotent {@link WorkerSteerRequest}\n * steers/acks/<hash>.json runtime acknowledgement for that steer operation\n * workers/<id>.inbox.ndjson best-effort readable projection of admitted steer requests\n * workers/<label>.ndjson best-effort per-worker control-event log (delivery bookkeeping)\n * cancellations/requests.ndjson worker-scoped cancel requests (durable inbox); each line is a\n * {@link WorkerCancelRequest}\n * cancellations/<opId>.json the acknowledgement for one cancel operation — a\n * {@link WorkerCancellation} written ONLY by the runtime\n * acknowledger in the OWNING manager's turn loop: exact node\n * ids route to the manager that parents them (any depth);\n * label/profile-name references to the root manager alone\n * cancellations/run.request.json the run-scoped cancel request — one {@link RunCancelRequest},\n * the whole RUN rather than one worker\n * cancellations/run.json the acknowledgement for the run-scoped request — a\n * {@link RunCancellation} written ONLY by the runtime (the root\n * manager issues the abort; the `supervise()` settle path records\n * what the run actually did)\n *\n * Reads are tolerant by contract: a partial trailing line (a writer mid-append) or a corrupt line\n * never poisons the rest of the file — later valid lines still matter. Duplicate operation ids\n * collapse to the first admitted request, while a payload conflict fails closed.\n *\n * Promoted from `loops/src/supervisor-control.ts`. Steer admission now requires the exact worker id\n * and a caller-owned operation id. One atomic request file is the durable inbox; the NDJSON file is\n * a readable projection only and never controls idempotency.\n *\n * @experimental\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { canonicalCandidateDigest, type Sha256Digest } from '@tangle-network/agent-interface'\nimport { sha256 } from '../../content-digest'\nimport type { RetainedRunEffect } from '../retained-run-types'\nimport {\n appendDurableFile,\n assertNoSymlinkDescendant,\n publishExclusiveDurableFile,\n writeAtomicDurableFile,\n} from './durable-file'\n\n/** One atomically admitted down-leg request for an exact worker id. @stable */\nexport interface WorkerSteerRequest {\n readonly schemaVersion: 1\n /** Caller-minted stable idempotency key for this operation. */\n readonly operationId: string\n /** Digest of operation id, worker id, message, source, and interrupt mode. */\n readonly requestDigest: Sha256Digest\n /** ISO timestamp of durable admission. */\n readonly at: string\n /** Who asked — 'human', a brain label, a tool name. Provenance, not authorization. */\n readonly source: string\n /** Exact supervised node id, including the run id for its root manager. */\n readonly worker: string\n readonly message: string\n readonly interrupt: boolean\n}\n\n/** Runtime acknowledgement for one exact steer operation. @stable */\nexport interface WorkerSteerAcknowledgement {\n readonly schemaVersion: 1\n readonly operationId: string\n readonly requestDigest: Sha256Digest\n readonly worker: string\n readonly effect: 'unknown' | 'delivered' | 'not_live' | 'unsupported' | 'refused'\n readonly requestedAt: string\n readonly observedAt: string\n readonly detail: string\n}\n\n/** Caller input for one retry-safe steer operation. @stable */\nexport interface WriteWorkerSteerOptions {\n /** Exact Runtime event/control directory, matching the run's `steerDir`.\n * Defaults to `supervisorRunDir(rootDir, supervisorId)` when omitted. */\n readonly eventDir?: string\n readonly operationId: string\n readonly message: string\n readonly source?: string\n readonly interrupt?: boolean\n}\n\n/** One durable worker-scoped cancel request appended to the run's cancellation inbox. */\nexport interface WorkerCancelRequest {\n /** Caller-minted stable operation identifier — the idempotency key of the whole operation. */\n readonly operationId: string\n /** ISO timestamp of the append. */\n readonly at: string\n /** Who asked — 'human', a brain label, a tool name. Provenance, not authorization. */\n readonly source: string\n /** The worker the request targets: a workerId (node id — routed to the owning manager at any\n * depth), or a profile name or spawn label (resolved by the root manager against its direct\n * children only). */\n readonly worker: string\n readonly reason?: string\n}\n\n/**\n * The durable acknowledgement state for one worker-scoped cancel operation, keyed by\n * `operationId`. The runtime acknowledger is the ONLY writer; `cancelWorker` only reads it.\n *\n * `effect` reuses the retained-run vocabulary ({@link RetainedRunEffect}) so the runtime has one\n * spelling of the four cancellation states:\n * - `'unknown'` — not yet resolved by the runtime (also what `cancelWorker` returns for\n * a request no acknowledger has answered), or — terminally, with the\n * run-over detail — an abort was issued but the run ended before the\n * termination could be observed. Never a success.\n * - `'cancel_requested'` — the runtime issued the worker's abort; termination not yet proven.\n * - `'cancelled'` — the worker reached a terminal `down` state on the settle path.\n * - `'not_live'` — the worker was not live to cancel (already settled, it settled\n * `done` despite the abort, or the run ended before the request was\n * ever applied). Never a success of THIS operation.\n *\n * Expiry is run end: the owning manager's final pass closes every still-open request it owns\n * (`not_live` never applied, `unknown` issued-but-unproven), so a pending request cannot outlive\n * its run and abort a future spawn that happens to reuse a label.\n */\nexport interface WorkerCancellation {\n readonly operationId: string\n /** The worker reference exactly as requested. */\n readonly worker: string\n readonly effect: RetainedRunEffect\n /** ISO timestamp of the original request. */\n readonly requestedAt: string\n /** ISO timestamp of the runtime's most recent observation of this operation. */\n readonly observedAt: string\n /** The node id the acknowledger resolved `worker` to, once resolved. */\n readonly workerId?: string\n /** The caller's reason, carried verbatim from the request. */\n readonly reason?: string\n /** The runtime's explanation of how it arrived at `effect`. */\n readonly detail?: string\n /**\n * Every node id this operation PROVED terminated: the requested worker plus each descendant of\n * its subtree observed to reach a terminal `down`/`cancelled` journal record at or after the\n * abort was ISSUED — the acknowledger's own `observedAt` on the `cancel_requested` record\n * (runtime clock), never the client's `requestedAt` (a cancelled lead cascades to its subtree\n * by design — the scope signal chain — so the acknowledgement names the set, not one id).\n * Proven at acknowledgement time; post-abort causation is approximate: a descendant that died\n * of its own cause after the abort is indistinguishable from the cascade and may be included,\n * a late teardown journal joins the set on a later pass while the manager still runs, and one\n * still absent at run end is absent from the set. Grows monotonically; empty until termination\n * is proven.\n */\n readonly terminated: ReadonlyArray<string>\n}\n\n/** The root every supervisor run of one workspace lives under. */\nexport function supervisorRunsRoot(rootDir: string): string {\n return join(resolve(rootDir), '.agent', 'supervisor')\n}\n\n/** The run directory every artifact of one supervisor run lives under. */\nexport function supervisorRunDir(rootDir: string, id: string): string {\n return join(supervisorRunsRoot(rootDir), id)\n}\n\n/**\n * Where a pre-rename writer put the same run (`<root>/.loops/supervisor/<id>`). Readers that must\n * see historical runs check {@link supervisorRunDir} first and fall back to this; nothing writes\n * here anymore.\n */\nexport function legacySupervisorRunDir(rootDir: string, id: string): string {\n return join(legacySupervisorRunsRoot(rootDir), id)\n}\n\n/**\n * The pre-rename runs root (`<root>/.loops/supervisor`). Only readers that ENUMERATE historical\n * runs need this — the per-id form is {@link legacySupervisorRunDir}. Nothing writes here.\n */\nexport function legacySupervisorRunsRoot(rootDir: string): string {\n return join(resolve(rootDir), '.loops', 'supervisor')\n}\n\n/** A worker label reduced to a safe filename stem. Empty labels get a stable fallback. */\nexport function safeWorkerFile(label: string): string {\n const safe = label.replace(/[^A-Za-z0-9._-]/g, '_')\n return safe.length > 0 ? safe : 'worker'\n}\n\n/** The directory holding every per-worker file of one run (inboxes and control-event logs). */\nexport function supervisorWorkersDir(eventDir: string): string {\n return join(eventDir, 'workers')\n}\n\n/** The durable inbox file for one worker of one run. */\nexport function workerInboxFile(rootDir: string, supervisorId: string, worker: string): string {\n return workerInboxFileFromEventDir(supervisorRunDir(rootDir, supervisorId), worker)\n}\n\n/** Same, addressed from an already-known run directory (the reader's usual entry point). */\nexport function workerInboxFileFromEventDir(eventDir: string, worker: string): string {\n return join(supervisorWorkersDir(eventDir), `${safeWorkerFile(worker)}.inbox.ndjson`)\n}\n\n/**\n * The best-effort control-event log for one worker (`workers/<label>.ndjson`) — delivery\n * bookkeeping for steers, plus whatever lifecycle events a writer chooses to append. Distinct from\n * the inbox: the inbox is the durable down-leg queue, this is the record of what happened to it.\n */\nexport function workerControlLogFile(eventDir: string, worker: string): string {\n return join(supervisorWorkersDir(eventDir), `${safeWorkerFile(worker)}.ndjson`)\n}\n\n/** Directory containing atomically admitted steer requests and runtime acknowledgements. */\nexport function workerSteersDir(eventDir: string): string {\n return join(eventDir, 'steers')\n}\n\n/** Directory containing one canonical request file per steer operation. */\nexport function workerSteerRequestsDir(eventDir: string): string {\n return join(workerSteersDir(eventDir), 'requests')\n}\n\n/** Directory containing one runtime acknowledgement per steer operation. */\nexport function workerSteerAcknowledgementsDir(eventDir: string): string {\n return join(workerSteersDir(eventDir), 'acks')\n}\n\n/** Canonical request file for one caller-owned steer operation id. */\nexport function workerSteerRequestFile(eventDir: string, operationId: string): string {\n return join(workerSteerRequestsDir(eventDir), `${operationFileHash(operationId)}.json`)\n}\n\n/** Runtime acknowledgement file for one caller-owned steer operation id. */\nexport function workerSteerAcknowledgementFile(eventDir: string, operationId: string): string {\n return join(workerSteerAcknowledgementsDir(eventDir), `${operationFileHash(operationId)}.json`)\n}\n\n/**\n * Admit one steer exactly once under a caller-owned operation id.\n *\n * Pass `supervisorId` as `worker` to address the root. Router roots consume requests between\n * turns; native roots use their existing accepting inbox during execution, or acknowledge\n * `unsupported` when none is available. Delivery does not prove model consumption.\n * This filesystem API requires trusted write access to the run directory; it adds no MCP grant.\n *\n * The per-operation request file is linked into place atomically after its bytes reach disk. A\n * same-body retry returns the winner's request. A changed-body retry fails loud. The NDJSON inbox\n * and control log are readable projections written only by the admission winner.\n * @stable\n */\nexport function writeWorkerSteer(\n rootDir: string,\n supervisorId: string,\n worker: string,\n options: WriteWorkerSteerOptions,\n): {\n worker: string\n file: string\n request: WorkerSteerRequest\n acknowledgement?: WorkerSteerAcknowledgement\n replayed: boolean\n} {\n const workerId = worker.trim()\n if (!workerId) throw new Error('writeWorkerSteer: worker id is empty')\n const operationId = options.operationId.trim()\n if (!operationId) throw new Error('writeWorkerSteer: operationId is empty')\n const trimmed = options.message.trim()\n if (!trimmed) throw new Error('steer message is empty')\n const source = options.source?.trim() || 'human'\n const interrupt = options.interrupt === true\n if (options.eventDir !== undefined && !options.eventDir.trim()) {\n throw new Error('writeWorkerSteer: eventDir is empty')\n }\n const dir =\n options.eventDir === undefined\n ? supervisorRunDir(rootDir, supervisorId)\n : resolve(options.eventDir)\n const requestDigest = workerSteerRequestDigest({\n operationId,\n worker: workerId,\n message: trimmed,\n source,\n interrupt,\n })\n const request: WorkerSteerRequest = {\n schemaVersion: 1,\n operationId,\n requestDigest,\n at: new Date().toISOString(),\n source,\n worker: workerId,\n message: trimmed,\n interrupt,\n }\n const file = workerSteerRequestFile(dir, operationId)\n assertNoSymlinkDescendant(dir, file, 'steer request')\n mkdirSync(workerSteerRequestsDir(dir), { recursive: true })\n assertNoSymlinkDescendant(dir, file, 'steer request')\n const admitted = admitSteerRequest(file, request)\n if (admitted.replayed) {\n return {\n worker: admitted.request.worker,\n file,\n request: admitted.request,\n ...(readWorkerSteerAcknowledgement(dir, operationId) === undefined\n ? {}\n : { acknowledgement: readWorkerSteerAcknowledgement(dir, operationId) }),\n replayed: true,\n }\n }\n mkdirSync(supervisorWorkersDir(dir), { recursive: true })\n const projection = workerInboxFileFromEventDir(dir, workerId)\n try {\n appendFileSync(projection, `${JSON.stringify(request)}\\n`, 'utf8')\n } catch {\n // The atomic operation file is the queue. This projection does not control admission.\n }\n appendWorkerControlEvent(dir, workerId, {\n kind: 'message',\n direction: 'down',\n source,\n operationId,\n requestDigest,\n message: trimmed,\n interrupt,\n queued: true,\n delivered: false,\n })\n return { worker: workerId, file, request, replayed: false }\n}\n\n/** Read every atomically admitted request for one exact worker id, in admission order. @stable */\nexport function readWorkerSteerRequests(eventDir: string, worker?: string): WorkerSteerRequest[] {\n const workerId = worker?.trim()\n if (worker !== undefined && !workerId) return []\n let names: string[]\n assertNoSymlinkDescendant(eventDir, workerSteerRequestsDir(eventDir), 'steer request')\n try {\n names = readdirSync(workerSteerRequestsDir(eventDir))\n } catch {\n return []\n }\n const out: WorkerSteerRequest[] = []\n for (const name of names) {\n if (!name.endsWith('.json')) continue\n try {\n const file = join(workerSteerRequestsDir(eventDir), name)\n assertNoSymlinkDescendant(eventDir, file, 'steer request')\n const parsed = parseWorkerSteerRequest(JSON.parse(readFileSync(file, 'utf8')))\n if (name !== `${operationFileHash(parsed.operationId)}.json`) continue\n if (workerId === undefined || parsed.worker === workerId) out.push(parsed)\n } catch {\n // One corrupt request cannot hide other independently committed operations.\n }\n }\n return out.sort((left, right) =>\n left.at === right.at\n ? left.operationId.localeCompare(right.operationId)\n : left.at.localeCompare(right.at),\n )\n}\n\n/** Read one runtime steer acknowledgement, or `undefined` while no manager has answered. @stable */\nexport function readWorkerSteerAcknowledgement(\n eventDir: string,\n operationId: string,\n): WorkerSteerAcknowledgement | undefined {\n const id = operationId.trim()\n if (!id) throw new Error('readWorkerSteerAcknowledgement: operationId is empty')\n const file = workerSteerAcknowledgementFile(eventDir, id)\n assertNoSymlinkDescendant(eventDir, file, 'steer acknowledgement')\n if (!existsSync(file)) return undefined\n const record = parseWorkerSteerAcknowledgement(JSON.parse(readFileSync(file, 'utf8')))\n if (record.operationId !== id) {\n throw new Error(`steer acknowledgement '${file}' belongs to another operation`)\n }\n return record\n}\n\n/**\n * Claim one steer for delivery with an atomic no-clobber acknowledgement.\n * Returns `true` only to the process that created the pre-delivery record.\n * @internal\n */\nexport function claimWorkerSteerDelivery(\n eventDir: string,\n record: WorkerSteerAcknowledgement,\n): boolean {\n const exact = parseWorkerSteerAcknowledgement(record)\n if (exact.effect !== 'unknown') {\n throw new Error('steer delivery claim must use effect unknown')\n }\n const request = readWorkerSteerRequest(eventDir, exact.operationId)\n if (request === undefined || request.requestDigest !== exact.requestDigest) {\n throw new Error('steer delivery claim does not match an admitted request')\n }\n const dir = workerSteerAcknowledgementsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'steer acknowledgement')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'steer acknowledgement')\n const file = workerSteerAcknowledgementFile(eventDir, exact.operationId)\n if (publishExclusiveDurableFile(file, `${JSON.stringify(exact, null, 2)}\\n`)) {\n return true\n }\n const winner = readWorkerSteerAcknowledgement(eventDir, exact.operationId)\n if (\n winner === undefined ||\n winner.operationId !== exact.operationId ||\n winner.requestDigest !== exact.requestDigest\n ) {\n throw new Error('steer delivery claim conflicts with another operation')\n }\n return false\n}\n\n/** Atomically replace the runtime acknowledgement for one steer operation. @internal */\nexport function writeWorkerSteerAcknowledgement(\n eventDir: string,\n record: WorkerSteerAcknowledgement,\n): void {\n const exact = parseWorkerSteerAcknowledgement(record)\n const request = readWorkerSteerRequest(eventDir, exact.operationId)\n if (request === undefined || request.requestDigest !== exact.requestDigest) {\n throw new Error('steer acknowledgement does not match an admitted request')\n }\n const dir = workerSteerAcknowledgementsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'steer acknowledgement')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'steer acknowledgement')\n const file = workerSteerAcknowledgementFile(eventDir, exact.operationId)\n const prior = readWorkerSteerAcknowledgement(eventDir, exact.operationId)\n if (\n prior !== undefined &&\n prior.effect !== 'unknown' &&\n canonicalCandidateDigest(prior) !== canonicalCandidateDigest(exact)\n ) {\n throw new Error(`steer operation '${exact.operationId}' already has a terminal acknowledgement`)\n }\n writeAtomicDurableFile(file, `${JSON.stringify(exact, null, 2)}\\n`)\n}\n\n/** The directory holding every cancellation artifact of one run (request inbox + acknowledgements). */\nexport function workerCancellationsDir(eventDir: string): string {\n return join(eventDir, 'cancellations')\n}\n\n/**\n * The durable cancel-request inbox of one run — one NDJSON line per {@link WorkerCancelRequest}.\n * It stays append-only so independent operations retain admission order and readers can skip a\n * partial trailing line. `appendDurableFile` uses O_APPEND, one write, file fsync, and directory\n * fsync; single-record acknowledgements use atomic replacement instead.\n */\nexport function workerCancelRequestsFile(eventDir: string): string {\n return join(workerCancellationsDir(eventDir), 'requests.ndjson')\n}\n\n/**\n * The acknowledgement file for one cancel operation. The filename is a sanitized stem of the\n * `operationId`; the record inside carries the exact id, and readers verify it so two distinct\n * ids that sanitize to one stem fail loud instead of answering for each other.\n */\nexport function workerCancellationFile(eventDir: string, operationId: string): string {\n return join(workerCancellationsDir(eventDir), `${safeOperationFile(operationId)}.json`)\n}\n\nfunction safeOperationFile(operationId: string): string {\n const safe = operationId.replace(/[^A-Za-z0-9._-]/g, '_')\n if (safe.length === 0) throw new Error('cancel operationId is empty')\n return safe\n}\n\n/** Read every valid cancel request in the run's cancellation inbox. Corrupt lines are skipped. */\nexport function readWorkerCancelRequests(eventDir: string): WorkerCancelRequest[] {\n const dir = workerCancellationsDir(eventDir)\n const file = workerCancelRequestsFile(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'cancel request')\n assertNoSymlinkDescendant(eventDir, file, 'cancel request')\n if (!existsSync(file)) return []\n const out: WorkerCancelRequest[] = []\n const byOperationId = new Map<string, WorkerCancelRequest>()\n let raw = ''\n try {\n raw = readFileSync(file, 'utf8')\n } catch {\n return out\n }\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n let parsed: Partial<WorkerCancelRequest>\n try {\n parsed = JSON.parse(trimmed) as Partial<WorkerCancelRequest>\n } catch {\n // Ignore partial or corrupt input lines; later valid lines still matter.\n continue\n }\n if (!isWorkerCancelRequest(parsed)) continue\n const prior = byOperationId.get(parsed.operationId)\n if (prior !== undefined) {\n assertSameWorkerCancelRequest(prior, parsed)\n } else {\n byOperationId.set(parsed.operationId, parsed)\n out.push(parsed)\n }\n }\n return out\n}\n\n/**\n * Read the acknowledgement for one cancel operation. `undefined` when the runtime has not\n * answered. A record whose stored `operationId` differs from the requested one is a filename\n * collision between two sanitized ids — fail loud rather than return another operation's answer.\n */\nexport function readWorkerCancellation(\n eventDir: string,\n operationId: string,\n): WorkerCancellation | undefined {\n const dir = workerCancellationsDir(eventDir)\n const file = workerCancellationFile(eventDir, operationId)\n assertNoSymlinkDescendant(eventDir, dir, 'cancel acknowledgement')\n assertNoSymlinkDescendant(eventDir, file, 'cancel acknowledgement')\n if (!existsSync(file)) return undefined\n const parsed = JSON.parse(readFileSync(file, 'utf8')) as WorkerCancellation\n if (parsed.operationId !== operationId) {\n throw new Error(\n `cancel acknowledgement collision: '${file}' holds operation '${parsed.operationId}', ` +\n `not '${operationId}' — use operation ids that stay distinct after filename sanitization`,\n )\n }\n return parsed\n}\n\n/**\n * Durably write one acknowledgement record. The shared writer fsyncs the file and containing\n * directory, so a concurrent reader sees the prior complete record or the new complete record.\n *\n * @internal The runtime acknowledger is the only intended writer; clients read via\n * {@link readWorkerCancellation} or {@link cancelWorker}.\n */\nexport function writeWorkerCancellation(eventDir: string, record: WorkerCancellation): void {\n const dir = workerCancellationsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'cancel acknowledgement')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'cancel acknowledgement')\n const file = workerCancellationFile(eventDir, record.operationId)\n assertNoSymlinkDescendant(eventDir, file, 'cancel acknowledgement')\n writeAtomicDurableFile(file, `${JSON.stringify(record, null, 2)}\\n`, { mode: 0o600 })\n}\n\n/**\n * Request the cancellation of ONE worker, idempotently, and return the operation's current\n * durable state.\n *\n * The write half of the acknowledged-cancellation contract (`writeWorkerSteer` is the steer\n * analog): append the request to the run's cancellation inbox, where the OWNING manager's\n * acknowledger (its turn loop — the root for label/profile references, the parent manager for an\n * exact node id at any depth) applies it — aborting exactly that worker's subtree and recording\n * what it proved. This function never applies the cancellation itself; writing a\n * request file is not an acknowledgement.\n *\n * Idempotency is a lookup: when an acknowledgement for `operationId` already exists, it is\n * returned AS-IS and nothing is appended — repeating one operation can never apply twice. A\n * retry that changes the worker, source, or reason fails closed. A request the runtime has not\n * answered yet returns `effect: 'unknown'` (never a success); call again with the same\n * `operationId` — or `readWorkerCancellation` — to read the acknowledged result after a\n * reconnect.\n */\nexport function cancelWorker(\n eventDir: string,\n worker: string,\n operationId: string,\n options: { readonly reason?: string; readonly source?: string } = {},\n): WorkerCancellation {\n const ref = worker.trim()\n if (!ref) throw new Error('cancelWorker: worker reference is empty')\n const opId = operationId.trim()\n if (!opId) throw new Error('cancelWorker: operationId is empty')\n const pending = readWorkerCancelRequests(eventDir).find((r) => r.operationId === opId)\n const candidate = {\n operationId: opId,\n worker: ref,\n source: options.source ?? 'human',\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n }\n if (pending !== undefined) assertSameWorkerCancelRequest(pending, candidate)\n const acknowledged = readWorkerCancellation(eventDir, opId)\n if (acknowledged !== undefined) {\n if (pending === undefined && options.source !== undefined) {\n throw new Error(\n `cancelWorker: operation '${opId}' cannot verify source without its admitted request`,\n )\n }\n assertWorkerCancellationMatchesCandidate(acknowledged, candidate)\n return acknowledged\n }\n const source = options.source ?? 'human'\n const request: WorkerCancelRequest = pending ?? {\n operationId: opId,\n at: new Date().toISOString(),\n source,\n worker: ref,\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n }\n if (!pending) {\n const dir = workerCancellationsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'cancel request')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'cancel request')\n const file = workerCancelRequestsFile(eventDir)\n assertNoSymlinkDescendant(eventDir, file, 'cancel request')\n appendDurableFile(file, `${JSON.stringify(request)}\\n`, { mode: 0o600 })\n appendWorkerControlEvent(eventDir, ref, {\n kind: 'cancel-request',\n operationId: opId,\n source,\n queued: true,\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n })\n }\n return {\n operationId: opId,\n worker: request.worker,\n effect: 'unknown',\n requestedAt: request.at,\n observedAt: request.at,\n ...(request.reason === undefined ? {} : { reason: request.reason }),\n detail: 'request queued; no runtime acknowledger has answered yet',\n terminated: [],\n }\n}\n\ntype WorkerCancelRequestCandidate = Omit<WorkerCancelRequest, 'at'>\n\nfunction assertSameWorkerCancelRequest(\n existing: WorkerCancelRequest,\n candidate: WorkerCancelRequestCandidate,\n): void {\n if (existing.operationId !== candidate.operationId) {\n throw new Error(`cancelWorker: operation '${candidate.operationId}' has an id collision`)\n }\n if (existing.worker !== candidate.worker) {\n throw new Error(\n `cancelWorker: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(worker '${existing.worker}' != '${candidate.worker}')`,\n )\n }\n if (existing.source !== candidate.source) {\n throw new Error(\n `cancelWorker: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(source '${existing.source}' != '${candidate.source}')`,\n )\n }\n if (existing.reason !== candidate.reason) {\n throw new Error(\n `cancelWorker: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(reason differs)`,\n )\n }\n}\n\nfunction assertWorkerCancellationMatchesCandidate(\n existing: WorkerCancellation,\n candidate: WorkerCancelRequestCandidate,\n): void {\n if (existing.worker !== candidate.worker) {\n throw new Error(\n `cancelWorker: operation '${candidate.operationId}' conflicts with its acknowledgement ` +\n `(worker '${existing.worker}' != '${candidate.worker}')`,\n )\n }\n if (existing.reason !== candidate.reason) {\n throw new Error(\n `cancelWorker: operation '${candidate.operationId}' conflicts with its acknowledgement ` +\n `(reason differs)`,\n )\n }\n}\n\nfunction isWorkerCancelRequest(value: Partial<WorkerCancelRequest>): value is WorkerCancelRequest {\n return (\n typeof value.operationId === 'string' &&\n value.operationId.length > 0 &&\n typeof value.at === 'string' &&\n typeof value.source === 'string' &&\n typeof value.worker === 'string' &&\n value.worker.length > 0 &&\n (value.reason === undefined || typeof value.reason === 'string')\n )\n}\n\nexport function appendWorkerControlEvent(\n eventDir: string,\n label: string,\n event: Record<string, unknown>,\n): void {\n try {\n mkdirSync(supervisorWorkersDir(eventDir), { recursive: true })\n appendFileSync(\n workerControlLogFile(eventDir, label),\n `${JSON.stringify({ at: new Date().toISOString(), label, ...event })}\\n`,\n 'utf8',\n )\n } catch {\n // Control logging is best-effort; the inbox write above is the durable part.\n }\n}\n\nfunction workerSteerRequestDigest(value: {\n readonly operationId: string\n readonly worker: string\n readonly message: string\n readonly source: string\n readonly interrupt: boolean\n}): Sha256Digest {\n return canonicalCandidateDigest({ kind: 'worker-steer-request.v1', ...value })\n}\n\nfunction operationFileHash(operationId: string): string {\n const id = operationId.trim()\n if (!id) throw new Error('steer operationId is empty')\n return sha256(id)\n}\n\nfunction admitSteerRequest(\n file: string,\n request: WorkerSteerRequest,\n): { readonly request: WorkerSteerRequest; readonly replayed: boolean } {\n const existing = readWorkerSteerRequestFile(file)\n if (existing !== undefined) {\n assertSameSteerRequest(existing, request)\n return { request: existing, replayed: true }\n }\n if (publishExclusiveDurableFile(file, `${JSON.stringify(request, null, 2)}\\n`)) {\n return { request, replayed: false }\n }\n const winner = readWorkerSteerRequestFile(file)\n if (winner === undefined) {\n throw new Error('steer request publication lost its winner')\n }\n assertSameSteerRequest(winner, request)\n return { request: winner, replayed: true }\n}\n\nfunction readWorkerSteerRequest(\n eventDir: string,\n operationId: string,\n): WorkerSteerRequest | undefined {\n const file = workerSteerRequestFile(eventDir, operationId)\n assertNoSymlinkDescendant(eventDir, file, 'steer request')\n const request = readWorkerSteerRequestFile(file)\n if (request !== undefined && request.operationId !== operationId) {\n throw new Error('steer request file belongs to another operation')\n }\n return request\n}\n\nfunction readWorkerSteerRequestFile(file: string): WorkerSteerRequest | undefined {\n if (!existsSync(file)) return undefined\n return parseWorkerSteerRequest(JSON.parse(readFileSync(file, 'utf8')))\n}\n\nfunction parseWorkerSteerRequest(value: unknown): WorkerSteerRequest {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('steer request is malformed')\n }\n const request = value as Partial<WorkerSteerRequest>\n if (\n request.schemaVersion !== 1 ||\n typeof request.operationId !== 'string' ||\n request.operationId.length === 0 ||\n typeof request.requestDigest !== 'string' ||\n typeof request.at !== 'string' ||\n typeof request.source !== 'string' ||\n request.source.length === 0 ||\n typeof request.worker !== 'string' ||\n request.worker.length === 0 ||\n typeof request.message !== 'string' ||\n request.message.trim().length === 0 ||\n typeof request.interrupt !== 'boolean'\n ) {\n throw new Error('steer request is malformed')\n }\n const exact = request as WorkerSteerRequest\n const expected = workerSteerRequestDigest({\n operationId: exact.operationId,\n worker: exact.worker,\n message: exact.message,\n source: exact.source,\n interrupt: exact.interrupt,\n })\n if (exact.requestDigest !== expected) throw new Error('steer request digest does not match')\n return exact\n}\n\nfunction parseWorkerSteerAcknowledgement(value: unknown): WorkerSteerAcknowledgement {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('steer acknowledgement is malformed')\n }\n const record = value as Partial<WorkerSteerAcknowledgement>\n if (\n record.schemaVersion !== 1 ||\n typeof record.operationId !== 'string' ||\n record.operationId.length === 0 ||\n typeof record.requestDigest !== 'string' ||\n typeof record.worker !== 'string' ||\n record.worker.length === 0 ||\n (record.effect !== 'unknown' &&\n record.effect !== 'delivered' &&\n record.effect !== 'not_live' &&\n record.effect !== 'unsupported' &&\n record.effect !== 'refused') ||\n typeof record.requestedAt !== 'string' ||\n typeof record.observedAt !== 'string' ||\n typeof record.detail !== 'string'\n ) {\n throw new Error('steer acknowledgement is malformed')\n }\n return record as WorkerSteerAcknowledgement\n}\n\nfunction assertSameSteerRequest(existing: WorkerSteerRequest, candidate: WorkerSteerRequest): void {\n if (existing.operationId !== candidate.operationId) {\n throw new Error('steer operation file collision')\n }\n if (existing.requestDigest !== candidate.requestDigest) {\n throw new Error(\n `writeWorkerSteer: operation '${candidate.operationId}' conflicts with its admitted request`,\n )\n }\n}\n","import { existsSync, mkdirSync, readFileSync, watch } from 'node:fs'\nimport { join } from 'node:path'\nimport type { RetainedRunEffect } from '../retained-run-types'\nimport { assertNoSymlinkDescendant, writeAtomicDurableFile } from './durable-file'\nimport { appendWorkerControlEvent, workerCancellationsDir } from './run-layout'\n\n/** Apply a durable request through the run's existing abort controller. */\nexport function applyRunCancellation(\n dir: string,\n abortRun: (reason: string, request?: RunCancelRequest) => void,\n now: () => string,\n path: 'observer' | 'turn-boundary' | 'fallback' = 'turn-boundary',\n): RunCancellation | undefined {\n const request = readRunCancelRequest(dir)\n if (request === undefined) return undefined\n const prior = readRunCancellation(dir, request.operationId)\n // A request acknowledged only as `cancel_requested` is still owed by this run: the process\n // that issued the abort died before the run settled. Abort again; the record stands.\n if (prior?.effect === 'cancel_requested') {\n abortRun(request.reason ?? 'run cancel requested', request)\n }\n if (prior !== undefined) return prior\n abortRun(request.reason ?? 'run cancel requested', request)\n const observedAt = now()\n const appliedAfterMs = Math.max(0, Date.parse(observedAt) - Date.parse(request.at))\n const record: RunCancellation = {\n operationId: request.operationId,\n effect: 'cancel_requested',\n path,\n appliedAfterMs,\n ...(request.deadlineMs === undefined\n ? {}\n : { deadlineExceeded: appliedAfterMs > request.deadlineMs }),\n requestedAt: request.at,\n observedAt,\n ...(request.reason === undefined ? {} : { reason: request.reason }),\n ...(request.operator === undefined ? {} : { operator: request.operator }),\n detail: 'root abort issued to the whole run; termination not yet proven',\n }\n writeRunCancellation(dir, record)\n return record\n}\n\n/** External drivers may remain silent indefinitely, so turn boundaries cannot observe control. */\nexport function watchRunCancellation(\n dir: string,\n abortRun: (reason: string, request?: RunCancelRequest) => void,\n createWatch: typeof watch = watch,\n) {\n mkdirSync(workerCancellationsDir(dir), { recursive: true })\n let active = true\n let failure: unknown\n // One observer aborts its run once: a request this process already applied, or one a dead\n // process acknowledged, is not re-issued on every poll.\n let aborted = false\n const abortOnce = (reason: string, request?: RunCancelRequest): void => {\n if (aborted) return\n aborted = true\n abortRun(reason, request)\n }\n const check = (path: 'observer' | 'fallback' = 'observer'): void => {\n if (failure !== undefined) throw failure\n if (active) applyRunCancellation(dir, abortOnce, () => new Date().toISOString(), path)\n }\n const fail = (error: unknown): void => {\n if (!active) return\n failure = error\n abortRun(`durable run cancellation observer failed: ${String(error)}`)\n }\n // The watcher is an optimization over the poll loop below (instant pickup instead of ≤100 ms).\n // Creating it can fail for reasons that say NOTHING about this run: the host's inotify budget is\n // exhausted (EMFILE — a shared box with many agents held ~110 of the 128 default user instances\n // when this was measured), or the kernel caps watches (ENOSPC). Degrading to poll-only keeps\n // every durable behavior; failing the run would make a neighboring process's resource use kill\n // runs that never touched the limit. Any other creation error still fails loudly.\n let watcher: ReturnType<typeof watch> | undefined\n try {\n watcher = createWatch(workerCancellationsDir(dir), (_event, filename) => {\n if (!active || (filename !== null && filename !== 'run.request.json')) return\n try {\n check()\n } catch (error) {\n fail(error)\n }\n })\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code\n if (code !== 'EMFILE' && code !== 'ENOSPC') throw error\n }\n watcher?.on('error', fail)\n // Filesystem notifications are advisory. Scan the same durable inbox when one is dropped —\n // and carry the whole observer alone whenever the watcher above could not be created.\n const fallback = setInterval(() => {\n try {\n check('fallback')\n } catch (error) {\n fail(error)\n }\n }, 100)\n fallback.unref()\n return {\n check,\n close(): void {\n active = false\n watcher?.close()\n clearInterval(fallback)\n },\n }\n}\n\n/** One durable run-scoped cancel request: cancel the WHOLE run, not one worker. */\nexport interface RunCancelRequest {\n /** Caller-minted stable operation identifier — the idempotency key of the whole operation. */\n readonly operationId: string\n /** ISO timestamp of the write. */\n readonly at: string\n /** Who asked — 'human', a brain label, a tool name. Provenance, not authorization. */\n readonly source: string\n /** Requested observation target, measured by the acknowledgement's deadlineExceeded field.\n * The observer always cascades eagerly. This does not guarantee scheduler latency or cleanup. */\n readonly deadlineMs?: number\n /** Who stops the run. `cancelRun` requires it on every new request; it is optional here only\n * so a request written before that rule still reads. The settle record carries it. */\n readonly operator?: string\n readonly reason?: string\n}\n\n/**\n * The durable acknowledgement state for the run-scoped cancel operation, keyed by `operationId`.\n * The runtime is the ONLY writer; {@link cancelRun} only reads it.\n *\n * `effect` is the same {@link RetainedRunEffect} vocabulary the worker-scoped and retained-run\n * paths use, so the runtime has one spelling of the four cancellation states:\n * - `'unknown'` — no runtime has answered yet. Never a success.\n * - `'cancel_requested'` — the root manager issued the run's cascading abort; the run's terminal\n * state is not yet observed.\n * - `'cancelled'` — the run reached its terminal cancelled state with confirmed teardown.\n * - `'not_live'` — the run was not live to cancel: it settled on its own despite the\n * request, or it ended before the request was applied.\n */\nexport interface RunCancellation {\n /** Runtime path that issued the cascade. */\n readonly path?: 'observer' | 'turn-boundary' | 'fallback'\n /** Runtime clock elapsed between request timestamp and cascade application. */\n readonly appliedAfterMs?: number\n /** Whether application exceeded the requested deadlineMs; absent when no target was requested. */\n readonly deadlineExceeded?: boolean\n readonly operationId: string\n readonly effect: RetainedRunEffect\n /** ISO timestamp of the original request. */\n readonly requestedAt: string\n /** ISO timestamp of the runtime's most recent observation of this operation. */\n readonly observedAt: string\n /** The caller's reason, carried verbatim from the request. */\n readonly reason?: string\n /** The caller's operator identity, carried verbatim from the request. */\n readonly operator?: string\n /** The runtime's explanation of how it arrived at `effect`. */\n readonly detail?: string\n}\n\n/** The run-scoped cancel request file of one run — one {@link RunCancelRequest}. */\nexport function runCancelRequestFile(eventDir: string): string {\n return join(workerCancellationsDir(eventDir), 'run.request.json')\n}\n\n/** The run-scoped acknowledgement file of one run — one {@link RunCancellation}. */\nexport function runCancellationFile(eventDir: string): string {\n return join(workerCancellationsDir(eventDir), 'run.json')\n}\n\n/** Read the run-scoped cancel request, or `undefined` when none was written. */\nexport function readRunCancelRequest(eventDir: string): RunCancelRequest | undefined {\n const dir = workerCancellationsDir(eventDir)\n const file = runCancelRequestFile(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel request')\n assertNoSymlinkDescendant(eventDir, file, 'run cancel request')\n if (!existsSync(file)) return undefined\n const parsed = JSON.parse(readFileSync(file, 'utf8')) as Partial<RunCancelRequest>\n if (!isRunCancelRequest(parsed)) {\n throw new Error(`run cancel request '${file}' is not a complete RunCancelRequest`)\n }\n return parsed\n}\n\n/**\n * Read the acknowledgement for the run-scoped cancel operation. `undefined` when the runtime has\n * not answered. A record holding a DIFFERENT `operationId` belongs to another operation on the\n * same run — fail loud rather than answer for it.\n */\nexport function readRunCancellation(\n eventDir: string,\n operationId: string,\n): RunCancellation | undefined {\n const dir = workerCancellationsDir(eventDir)\n const file = runCancellationFile(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel acknowledgement')\n assertNoSymlinkDescendant(eventDir, file, 'run cancel acknowledgement')\n if (!existsSync(file)) return undefined\n const parsed = JSON.parse(readFileSync(file, 'utf8')) as RunCancellation\n if (parsed.operationId !== operationId) {\n throw new Error(\n `run cancel acknowledgement '${file}' holds operation '${parsed.operationId}', not ` +\n `'${operationId}' — one run carries one run-scoped cancel operation`,\n )\n }\n return parsed\n}\n\n/**\n * Durably write the run-scoped acknowledgement. The shared writer fsyncs the file and containing\n * directory, so a concurrent reader sees the prior complete record or the new complete record.\n *\n * @internal The runtime is the only intended writer; clients read via {@link readRunCancellation}\n * or {@link cancelRun}.\n */\nexport function writeRunCancellation(eventDir: string, record: RunCancellation): void {\n const dir = workerCancellationsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel acknowledgement')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel acknowledgement')\n const file = runCancellationFile(eventDir)\n assertNoSymlinkDescendant(eventDir, file, 'run cancel acknowledgement')\n writeAtomicDurableFile(file, `${JSON.stringify(record, null, 2)}\\n`, { mode: 0o600 })\n}\n\n/**\n * Request the cancellation of the WHOLE run, idempotently, and return the operation's current\n * durable state.\n *\n * The run-scoped twin of {@link cancelWorker}: write the request into the run's cancellation\n * directory, where the run's own root manager applies it — aborting the root through the one\n * cascade controller the run already has, so every live worker comes down with it. This function\n * never applies the cancellation itself; writing a request file is not an acknowledgement.\n *\n * Idempotency is a lookup: when an acknowledgement for `operationId` already exists it is returned\n * AS-IS and nothing is written. A retry that changes the source, reason, deadline, or operator\n * fails closed. A request the runtime has not answered yet returns `effect: 'unknown'` (never a\n * success); call again with the same `operationId` — or {@link readRunCancellation} — to read the\n * acknowledged result after a reconnect.\n *\n * A run carries ONE run-scoped operation: a second request under a different `operationId` throws\n * rather than silently replacing the pending one, because both would claim the same single abort.\n * Reopening a settled run (`supervisePursuit`'s `reopen`) moves that operation aside.\n *\n * A NEW request must name its `operator`, so every stop says who made it. A replay of a request\n * or acknowledgement written before that rule is answered as it was.\n */\nexport function cancelRun(\n eventDir: string,\n operationId: string,\n options: {\n readonly reason?: string\n readonly source?: string\n readonly deadlineMs?: number\n readonly operator?: string\n } = {},\n): RunCancellation {\n if (\n options.deadlineMs !== undefined &&\n (!Number.isFinite(options.deadlineMs) || options.deadlineMs < 0)\n ) {\n throw new Error('cancelRun: deadlineMs must be a finite nonnegative number')\n }\n const opId = operationId.trim()\n if (!opId) throw new Error('cancelRun: operationId is empty')\n const pending = readRunCancelRequest(eventDir)\n if (pending !== undefined && pending.operationId !== opId) {\n throw new Error(\n `cancelRun: run cancel '${pending.operationId}' is already pending for this run; ` +\n `read it with readRunCancellation instead of issuing '${opId}'`,\n )\n }\n const candidate = {\n operationId: opId,\n source: options.source ?? 'human',\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n ...(options.deadlineMs === undefined ? {} : { deadlineMs: options.deadlineMs }),\n ...(options.operator === undefined ? {} : { operator: options.operator }),\n }\n if (pending !== undefined) assertSameRunCancelRequest(pending, candidate)\n const acknowledged = readRunCancellation(eventDir, opId)\n if (acknowledged !== undefined) {\n if (pending === undefined && options.source !== undefined) {\n throw new Error(\n `cancelRun: operation '${opId}' cannot verify source without its admitted request`,\n )\n }\n assertRunCancellationMatchesCandidate(acknowledged, candidate)\n return acknowledged\n }\n // A new request names who stops the run. A replay of a request written before this rule keeps\n // its absent operator: it was admitted above against the file it replays.\n if (pending === undefined && (options.operator === undefined || options.operator.trim() === '')) {\n throw new Error('cancelRun: operator is required; name who stops the run')\n }\n const source = options.source ?? 'human'\n const request: RunCancelRequest = pending ?? {\n operationId: opId,\n at: new Date().toISOString(),\n source,\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n ...(options.deadlineMs === undefined ? {} : { deadlineMs: options.deadlineMs }),\n ...(options.operator === undefined ? {} : { operator: options.operator }),\n }\n if (pending === undefined) {\n const dir = workerCancellationsDir(eventDir)\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel request')\n mkdirSync(dir, { recursive: true })\n assertNoSymlinkDescendant(eventDir, dir, 'run cancel request')\n const file = runCancelRequestFile(eventDir)\n assertNoSymlinkDescendant(eventDir, file, 'run cancel request')\n writeAtomicDurableFile(file, `${JSON.stringify(request, null, 2)}\\n`, { mode: 0o600 })\n appendWorkerControlEvent(eventDir, 'run', {\n kind: 'run-cancel-request',\n operationId: opId,\n source,\n queued: true,\n ...(options.reason === undefined ? {} : { reason: options.reason }),\n ...(options.deadlineMs === undefined ? {} : { deadlineMs: options.deadlineMs }),\n ...(options.operator === undefined ? {} : { operator: options.operator }),\n })\n }\n return {\n operationId: opId,\n effect: 'unknown',\n requestedAt: request.at,\n observedAt: request.at,\n ...(request.reason === undefined ? {} : { reason: request.reason }),\n ...(request.operator === undefined ? {} : { operator: request.operator }),\n detail: 'request queued; no runtime acknowledger has answered yet',\n }\n}\n\ntype RunCancelRequestCandidate = Omit<RunCancelRequest, 'at'>\n\nfunction assertSameRunCancelRequest(\n existing: RunCancelRequest,\n candidate: RunCancelRequestCandidate,\n): void {\n if (existing.operationId !== candidate.operationId) {\n throw new Error(`cancelRun: operation '${candidate.operationId}' has an id collision`)\n }\n if (existing.source !== candidate.source) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(source '${existing.source}' != '${candidate.source}')`,\n )\n }\n if (existing.deadlineMs !== candidate.deadlineMs) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its admitted request (deadlineMs differs)`,\n )\n }\n if (existing.reason !== candidate.reason) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(reason differs)`,\n )\n }\n if (existing.operator !== candidate.operator) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its admitted request ` +\n `(operator '${existing.operator}' != '${candidate.operator}')`,\n )\n }\n}\n\nfunction assertRunCancellationMatchesCandidate(\n existing: RunCancellation,\n candidate: RunCancelRequestCandidate,\n): void {\n if (existing.reason !== candidate.reason) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its acknowledgement ` +\n `(reason differs)`,\n )\n }\n // An acknowledgement written before acknowledgements carried the operator (0.251.0) names none\n // even when its admitted request does. The request comparator has already held the candidate\n // to that request, so a legacy record matches any candidate operator; a record that names one\n // must name the same one.\n if (existing.operator !== undefined && existing.operator !== candidate.operator) {\n throw new Error(\n `cancelRun: operation '${candidate.operationId}' conflicts with its acknowledgement ` +\n `(operator '${existing.operator}' != '${candidate.operator}')`,\n )\n }\n}\n\nfunction isRunCancelRequest(value: Partial<RunCancelRequest>): value is RunCancelRequest {\n return (\n typeof value.operationId === 'string' &&\n value.operationId.length > 0 &&\n typeof value.at === 'string' &&\n typeof value.source === 'string' &&\n (value.deadlineMs === undefined ||\n (Number.isFinite(value.deadlineMs) && value.deadlineMs >= 0)) &&\n (value.reason === undefined || typeof value.reason === 'string') &&\n (value.operator === undefined || typeof value.operator === 'string')\n )\n}\n"],"mappings":"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"}
|