pi-ptc-subagents 0.1.2 → 0.1.3
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/CHANGELOG.md +28 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +30 -3128
- package/dist/protocol-CfOgxz3u.js +2 -0
- package/dist/worker.js +3 -758
- package/package.json +3 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/protocol-DUnAP1Ro.js +0 -117
- package/dist/protocol-DUnAP1Ro.js.map +0 -1
- package/dist/worker.js.map +0 -1
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { MessagePort } from "node:worker_threads";
|
|
2
|
-
const HOST_FRAME_KIND = Object.freeze({
|
|
3
|
-
connect: "connect",
|
|
4
|
-
init: "init",
|
|
5
|
-
callResult: "call-result",
|
|
6
|
-
cancel: "cancel"
|
|
7
|
-
});
|
|
8
|
-
const WORKER_FRAME_KIND = Object.freeze({
|
|
9
|
-
ready: "ready",
|
|
10
|
-
call: "call",
|
|
11
|
-
log: "log",
|
|
12
|
-
narration: "narration",
|
|
13
|
-
phase: "phase",
|
|
14
|
-
result: "result",
|
|
15
|
-
error: "error"
|
|
16
|
-
});
|
|
17
|
-
const PTC_LOG_LEVEL = Object.freeze({
|
|
18
|
-
log: "log",
|
|
19
|
-
info: "info",
|
|
20
|
-
warn: "warn",
|
|
21
|
-
error: "error",
|
|
22
|
-
debug: "debug"
|
|
23
|
-
});
|
|
24
|
-
const PTC_ERROR_KIND = Object.freeze({
|
|
25
|
-
/** Program parse error or thrown exception (includes `ReferenceError` from a helper that does not exist on this surface). */
|
|
26
|
-
exception: "exception",
|
|
27
|
-
/** Elapsed deadline expiry. */
|
|
28
|
-
timeout: "timeout",
|
|
29
|
-
/** Caller cancellation. */
|
|
30
|
-
abort: "abort",
|
|
31
|
-
/** Malformed or excessive control traffic. */
|
|
32
|
-
protocol: "protocol",
|
|
33
|
-
/** Early worker exit or a worker-level crash. */
|
|
34
|
-
workerExit: "worker-exit",
|
|
35
|
-
/** Completion value could not be materialized as lossless JSON. */
|
|
36
|
-
invalidOutput: "invalid-output",
|
|
37
|
-
/** Oversized outer result; collected logs are retained. */
|
|
38
|
-
outputLimit: "output-limit"
|
|
39
|
-
});
|
|
40
|
-
function isRecord(value) {
|
|
41
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42
|
-
}
|
|
43
|
-
function isPtcLogLevel(value) {
|
|
44
|
-
return typeof value === "string" && Object.values(PTC_LOG_LEVEL).some((level) => level === value);
|
|
45
|
-
}
|
|
46
|
-
function isPtcErrorKind(value) {
|
|
47
|
-
return typeof value === "string" && Object.values(PTC_ERROR_KIND).some((kind) => kind === value);
|
|
48
|
-
}
|
|
49
|
-
function isPtcCancelReason(value) {
|
|
50
|
-
return value === "timeout" || value === "abort";
|
|
51
|
-
}
|
|
52
|
-
function isPtcConnectFrame(value) {
|
|
53
|
-
return isRecord(value) && value.kind === HOST_FRAME_KIND.connect && value.port instanceof MessagePort;
|
|
54
|
-
}
|
|
55
|
-
function isPtcInitFrame(value) {
|
|
56
|
-
return isRecord(value) && value.kind === HOST_FRAME_KIND.init && typeof value.runId === "string" && (value.surface === "run_code" || value.surface === "workflow") && typeof value.code === "string" && Array.isArray(value.bindings) && value.bindings.every((name) => typeof name === "string") && Array.isArray(value.bindingCandidates) && value.bindingCandidates.every((name) => typeof name === "string") && typeof value.maxItemsPerCall === "number" && Number.isFinite(value.maxItemsPerCall) && typeof value.maxPendingCalls === "number" && Number.isFinite(value.maxPendingCalls);
|
|
57
|
-
}
|
|
58
|
-
function isPtcCallResultFrame(value) {
|
|
59
|
-
if (!isRecord(value) || value.kind !== HOST_FRAME_KIND.callResult) return false;
|
|
60
|
-
if (!Number.isInteger(value.callId) || typeof value.tool !== "string") return false;
|
|
61
|
-
if (value.ok === true) return "value" in value;
|
|
62
|
-
return value.ok === false && typeof value.message === "string";
|
|
63
|
-
}
|
|
64
|
-
function isPtcCancelFrame(value) {
|
|
65
|
-
return isRecord(value) && value.kind === HOST_FRAME_KIND.cancel && isPtcCancelReason(value.reason);
|
|
66
|
-
}
|
|
67
|
-
function isPtcHostFrame(value) {
|
|
68
|
-
return isPtcConnectFrame(value) || isPtcInitFrame(value) || isPtcCallResultFrame(value) || isPtcCancelFrame(value);
|
|
69
|
-
}
|
|
70
|
-
function isPtcReadyFrame(value) {
|
|
71
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.ready;
|
|
72
|
-
}
|
|
73
|
-
function isPtcCallFrame(value) {
|
|
74
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.call && Number.isInteger(value.callId) && typeof value.tool === "string" && value.tool.length > 0 && "args" in value;
|
|
75
|
-
}
|
|
76
|
-
function isPtcLogFrame(value) {
|
|
77
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.log && isPtcLogLevel(value.level) && typeof value.text === "string";
|
|
78
|
-
}
|
|
79
|
-
function isPtcNarrationFrame(value) {
|
|
80
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.narration && typeof value.message === "string";
|
|
81
|
-
}
|
|
82
|
-
function isPtcPhaseFrame(value) {
|
|
83
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.phase && typeof value.title === "string";
|
|
84
|
-
}
|
|
85
|
-
function isPtcResultFrame(value) {
|
|
86
|
-
return isRecord(value) && value.kind === WORKER_FRAME_KIND.result;
|
|
87
|
-
}
|
|
88
|
-
function isPtcErrorFrame(value) {
|
|
89
|
-
if (!isRecord(value) || value.kind !== WORKER_FRAME_KIND.error) return false;
|
|
90
|
-
const error = value.error;
|
|
91
|
-
return isRecord(error) && isPtcErrorKind(error.kind) && typeof error.message === "string" && (error.stack === void 0 || typeof error.stack === "string");
|
|
92
|
-
}
|
|
93
|
-
function isPtcWorkerFrame(value) {
|
|
94
|
-
return isPtcReadyFrame(value) || isPtcCallFrame(value) || isPtcLogFrame(value) || isPtcNarrationFrame(value) || isPtcPhaseFrame(value) || isPtcResultFrame(value) || isPtcErrorFrame(value);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* One-phrase description of an arbitrary value for error messages. Shared by the
|
|
98
|
-
* worker-side helpers (`log(message) expects a string, received …`) and the host-side
|
|
99
|
-
* workflow-args validator, so both ends word their rejection reasons identically.
|
|
100
|
-
*/
|
|
101
|
-
function describeValue(value) {
|
|
102
|
-
if (value === null) return "null";
|
|
103
|
-
if (Array.isArray(value)) return "an array";
|
|
104
|
-
return `a ${typeof value}`;
|
|
105
|
-
}
|
|
106
|
-
function workerProtocolSpec() {
|
|
107
|
-
return {
|
|
108
|
-
hostFrame: HOST_FRAME_KIND,
|
|
109
|
-
workerFrame: WORKER_FRAME_KIND,
|
|
110
|
-
logLevel: PTC_LOG_LEVEL,
|
|
111
|
-
errorKind: PTC_ERROR_KIND
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
//#endregion
|
|
115
|
-
export { describeValue as a, workerProtocolSpec as c, WORKER_FRAME_KIND as i, PTC_ERROR_KIND as n, isPtcHostFrame as o, PTC_LOG_LEVEL as r, isPtcWorkerFrame as s, HOST_FRAME_KIND as t };
|
|
116
|
-
|
|
117
|
-
//# sourceMappingURL=protocol-DUnAP1Ro.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-DUnAP1Ro.js","names":[],"sources":["../src/runtime/protocol.ts"],"sourcesContent":["/**\n * The PTC wire protocol: every frame that crosses the host↔worker boundary, plus a\n * runtime guard for every arm of both closed unions.\n *\n * Shape rules:\n * - Frame kinds, log levels and error kinds live here once; the worker receives the\n * same tables as plain data at spawn (`workerProtocolSpec`), so the two ends cannot\n * drift on names.\n * - Guards validate *shape only*. They never walk payloads: a `log` frame may carry a\n * 64 MiB string and a `call` frame arbitrary tool arguments, so byte accounting is\n * the dispatcher's job (see `serializedBytes` usage there).\n * - Error kinds are R1 §3's taxonomy minus `sandbox-unavailable` (ADR-0007 ships no OS\n * sandbox) and minus any `agent`-related kind (there is no `agent()` helper).\n *\n * This module also carries the small message-formatting helpers both ends share\n * (`describeValue`), since both bundles (host `dist/index.js`, worker `dist/worker.js`)\n * import it statically and the wire strings must stay aligned anyway.\n */\nimport { MessagePort } from \"node:worker_threads\";\nimport type { PtcSurface } from \"./limits.ts\";\n\n/** host → worker */\nconst HOST_FRAME_KIND_VALUES = {\n connect: \"connect\",\n init: \"init\",\n callResult: \"call-result\",\n cancel: \"cancel\",\n} as const;\nexport const HOST_FRAME_KIND: typeof HOST_FRAME_KIND_VALUES = Object.freeze(HOST_FRAME_KIND_VALUES);\n\n/** worker → host */\nconst WORKER_FRAME_KIND_VALUES = {\n ready: \"ready\",\n call: \"call\",\n log: \"log\",\n narration: \"narration\",\n phase: \"phase\",\n result: \"result\",\n error: \"error\",\n} as const;\nexport const WORKER_FRAME_KIND: typeof WORKER_FRAME_KIND_VALUES =\n Object.freeze(WORKER_FRAME_KIND_VALUES);\n\nconst PTC_LOG_LEVEL_VALUES = {\n log: \"log\",\n info: \"info\",\n warn: \"warn\",\n error: \"error\",\n debug: \"debug\",\n} as const;\nexport const PTC_LOG_LEVEL: typeof PTC_LOG_LEVEL_VALUES = Object.freeze(PTC_LOG_LEVEL_VALUES);\nexport type PtcLogLevel = (typeof PTC_LOG_LEVEL)[keyof typeof PTC_LOG_LEVEL];\n\nconst PTC_ERROR_KIND_VALUES = {\n /** Program parse error or thrown exception (includes `ReferenceError` from a helper that does not exist on this surface). */\n exception: \"exception\",\n /** Elapsed deadline expiry. */\n timeout: \"timeout\",\n /** Caller cancellation. */\n abort: \"abort\",\n /** Malformed or excessive control traffic. */\n protocol: \"protocol\",\n /** Early worker exit or a worker-level crash. */\n workerExit: \"worker-exit\",\n /** Completion value could not be materialized as lossless JSON. */\n invalidOutput: \"invalid-output\",\n /** Oversized outer result; collected logs are retained. */\n outputLimit: \"output-limit\",\n} as const;\nexport const PTC_ERROR_KIND: typeof PTC_ERROR_KIND_VALUES = Object.freeze(PTC_ERROR_KIND_VALUES);\nexport type PtcErrorKind = (typeof PTC_ERROR_KIND)[keyof typeof PTC_ERROR_KIND];\n\nexport type PtcCancelReason = \"timeout\" | \"abort\";\n\n/** Lossless-JSON payloads, the only values that may cross the boundary as data. */\nexport interface PtcJsonObject {\n [key: string]: PtcJsonValue;\n}\nexport type PtcJsonValue = string | number | boolean | null | PtcJsonValue[] | PtcJsonObject;\n\nexport interface PtcErrorShape {\n kind: PtcErrorKind;\n message: string;\n stack?: string;\n}\n\n/* -------------------------------------------------------------------------- */\n/* host → worker */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Handshake frame sent over `parentPort` right after spawn.\n *\n * The port must appear *in the payload*, not only in the transfer list: Node silently\n * drops a transfer-list-only entry (the worker receives the message without any port\n * and would wait forever), and it does not populate `msg.ports` for `worker_threads`\n * messages the way the browser `MessageEvent.ports` does. Both were verified against\n * Node v24.18.0 while writing this module.\n */\nexport interface PtcConnectFrame {\n kind: \"connect\";\n port: MessagePort;\n}\n\n/** First frame on the control port: installs the surface and starts the program. */\nexport interface PtcInitFrame {\n kind: \"init\";\n runId: string;\n surface: PtcSurface;\n code: string;\n /** Binding names the worker may expose as `tools.<name>`; the keys of the host table. */\n bindings: readonly string[];\n /**\n * Names the host could have bound (its built-in factory set). Candidates absent from\n * `bindings` get a throwing stub in the worker, so a disabled tool fails with an\n * actionable error instead of `tools.x is not a function` (T7, #21).\n */\n bindingCandidates: readonly string[];\n maxItemsPerCall: number;\n /**\n * In-flight call ceiling the worker must maintain itself (ADR-0004).\n *\n * The worker admits calls before posting them — a wide `Promise.all` / `parallel()`\n * burst then queues inside the worker instead of arriving at the host all at once,\n * which is what makes \"maximum simultaneous host binding calls\" a real invariant\n * rather than an arrival-counted tripwire. The host keeps its own counting as a\n * defense-in-depth backstop for a worker that ignores this field.\n */\n maxPendingCalls: number;\n /** Workflow surface only: value bound to the `args` global. */\n args?: unknown;\n}\n\nexport interface PtcCallResultOkFrame {\n kind: \"call-result\";\n callId: number;\n tool: string;\n ok: true;\n value: unknown;\n}\n\nexport interface PtcCallResultErrorFrame {\n kind: \"call-result\";\n callId: number;\n tool: string;\n ok: false;\n message: string;\n}\n\nexport type PtcCallResultFrame = PtcCallResultOkFrame | PtcCallResultErrorFrame;\n\nexport interface PtcCancelFrame {\n kind: \"cancel\";\n reason: PtcCancelReason;\n}\n\nexport type PtcHostFrame = PtcConnectFrame | PtcInitFrame | PtcCallResultFrame | PtcCancelFrame;\n\n/* -------------------------------------------------------------------------- */\n/* worker → host */\n/* -------------------------------------------------------------------------- */\n\n/** Control port is live and the surface may be installed. */\nexport interface PtcReadyFrame {\n kind: \"ready\";\n}\n\n/** `tools.<tool>(args)`: the worker is waiting for a `call-result` with the same id. */\nexport interface PtcCallFrame {\n kind: \"call\";\n callId: number;\n tool: string;\n args: unknown;\n}\n\nexport interface PtcLogFrame {\n kind: \"log\";\n level: PtcLogLevel;\n text: string;\n}\n\n/** Workflow `log(message)`: narration for the UI, not console output. */\nexport interface PtcNarrationFrame {\n kind: \"narration\";\n message: string;\n}\n\n/** Workflow `phase(title)`. */\nexport interface PtcPhaseFrame {\n kind: \"phase\";\n title: string;\n}\n\n/** Program completed. `value` is absent when the program returned nothing. */\nexport interface PtcResultFrame {\n kind: \"result\";\n value?: PtcJsonValue;\n}\n\nexport interface PtcErrorFrame {\n kind: \"error\";\n error: PtcErrorShape;\n}\n\nexport type PtcWorkerFrame =\n | PtcReadyFrame\n | PtcCallFrame\n | PtcLogFrame\n | PtcNarrationFrame\n | PtcPhaseFrame\n | PtcResultFrame\n | PtcErrorFrame;\n\n/* -------------------------------------------------------------------------- */\n/* guards */\n/* -------------------------------------------------------------------------- */\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nexport function isPtcLogLevel(value: unknown): value is PtcLogLevel {\n return typeof value === \"string\" && Object.values(PTC_LOG_LEVEL).some((level) => level === value);\n}\n\nexport function isPtcErrorKind(value: unknown): value is PtcErrorKind {\n return typeof value === \"string\" && Object.values(PTC_ERROR_KIND).some((kind) => kind === value);\n}\n\nexport function isPtcCancelReason(value: unknown): value is PtcCancelReason {\n return value === \"timeout\" || value === \"abort\";\n}\n\nexport function isPtcConnectFrame(value: unknown): value is PtcConnectFrame {\n return (\n isRecord(value) && value.kind === HOST_FRAME_KIND.connect && value.port instanceof MessagePort\n );\n}\n\nexport function isPtcInitFrame(value: unknown): value is PtcInitFrame {\n return (\n isRecord(value) &&\n value.kind === HOST_FRAME_KIND.init &&\n typeof value.runId === \"string\" &&\n (value.surface === \"run_code\" || value.surface === \"workflow\") &&\n typeof value.code === \"string\" &&\n Array.isArray(value.bindings) &&\n value.bindings.every((name) => typeof name === \"string\") &&\n Array.isArray(value.bindingCandidates) &&\n value.bindingCandidates.every((name) => typeof name === \"string\") &&\n typeof value.maxItemsPerCall === \"number\" &&\n Number.isFinite(value.maxItemsPerCall) &&\n typeof value.maxPendingCalls === \"number\" &&\n Number.isFinite(value.maxPendingCalls)\n );\n}\n\nexport function isPtcCallResultFrame(value: unknown): value is PtcCallResultFrame {\n if (!isRecord(value) || value.kind !== HOST_FRAME_KIND.callResult) return false;\n if (!Number.isInteger(value.callId) || typeof value.tool !== \"string\") return false;\n if (value.ok === true) return \"value\" in value;\n return value.ok === false && typeof value.message === \"string\";\n}\n\nexport function isPtcCancelFrame(value: unknown): value is PtcCancelFrame {\n return (\n isRecord(value) && value.kind === HOST_FRAME_KIND.cancel && isPtcCancelReason(value.reason)\n );\n}\n\nexport function isPtcHostFrame(value: unknown): value is PtcHostFrame {\n return (\n isPtcConnectFrame(value) ||\n isPtcInitFrame(value) ||\n isPtcCallResultFrame(value) ||\n isPtcCancelFrame(value)\n );\n}\n\nexport function isPtcReadyFrame(value: unknown): value is PtcReadyFrame {\n return isRecord(value) && value.kind === WORKER_FRAME_KIND.ready;\n}\n\nexport function isPtcCallFrame(value: unknown): value is PtcCallFrame {\n return (\n isRecord(value) &&\n value.kind === WORKER_FRAME_KIND.call &&\n Number.isInteger(value.callId) &&\n typeof value.tool === \"string\" &&\n value.tool.length > 0 &&\n \"args\" in value\n );\n}\n\nexport function isPtcLogFrame(value: unknown): value is PtcLogFrame {\n return (\n isRecord(value) &&\n value.kind === WORKER_FRAME_KIND.log &&\n isPtcLogLevel(value.level) &&\n typeof value.text === \"string\"\n );\n}\n\nexport function isPtcNarrationFrame(value: unknown): value is PtcNarrationFrame {\n return (\n isRecord(value) &&\n value.kind === WORKER_FRAME_KIND.narration &&\n typeof value.message === \"string\"\n );\n}\n\nexport function isPtcPhaseFrame(value: unknown): value is PtcPhaseFrame {\n return (\n isRecord(value) && value.kind === WORKER_FRAME_KIND.phase && typeof value.title === \"string\"\n );\n}\n\nexport function isPtcResultFrame(value: unknown): value is PtcResultFrame {\n return isRecord(value) && value.kind === WORKER_FRAME_KIND.result;\n}\n\nexport function isPtcErrorFrame(value: unknown): value is PtcErrorFrame {\n if (!isRecord(value) || value.kind !== WORKER_FRAME_KIND.error) return false;\n const error = value.error;\n return (\n isRecord(error) &&\n isPtcErrorKind(error.kind) &&\n typeof error.message === \"string\" &&\n (error.stack === undefined || typeof error.stack === \"string\")\n );\n}\n\nexport function isPtcWorkerFrame(value: unknown): value is PtcWorkerFrame {\n return (\n isPtcReadyFrame(value) ||\n isPtcCallFrame(value) ||\n isPtcLogFrame(value) ||\n isPtcNarrationFrame(value) ||\n isPtcPhaseFrame(value) ||\n isPtcResultFrame(value) ||\n isPtcErrorFrame(value)\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* value description */\n/* -------------------------------------------------------------------------- */\n\n/**\n * One-phrase description of an arbitrary value for error messages. Shared by the\n * worker-side helpers (`log(message) expects a string, received …`) and the host-side\n * workflow-args validator, so both ends word their rejection reasons identically.\n */\nexport function describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"an array\";\n return `a ${typeof value}`;\n}\n\n/* -------------------------------------------------------------------------- */\n/* worker-side spec */\n/* -------------------------------------------------------------------------- */\n\n/**\n * The protocol tables as plain data, injected into the worker at spawn.\n *\n * The worker bootstrap is self-contained (see `worker-main.ts`), so it cannot import\n * these constants — it receives them instead, which is what keeps both ends on the\n * same strings.\n */\nexport interface WorkerProtocolSpec {\n hostFrame: typeof HOST_FRAME_KIND;\n workerFrame: typeof WORKER_FRAME_KIND;\n logLevel: typeof PTC_LOG_LEVEL;\n errorKind: typeof PTC_ERROR_KIND;\n}\n\nexport function workerProtocolSpec(): WorkerProtocolSpec {\n return {\n hostFrame: HOST_FRAME_KIND,\n workerFrame: WORKER_FRAME_KIND,\n logLevel: PTC_LOG_LEVEL,\n errorKind: PTC_ERROR_KIND,\n };\n}\n"],"mappings":"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"}
|
package/dist/worker.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","names":[],"sources":["../src/runtime/worker-main.ts","../src/runtime/worker-entry.ts"],"sourcesContent":["/**\n * Worker-side PTC runtime: installs one surface, runs one program, routes `tools.*`\n * calls back to the host.\n *\n * State machine (ADR-0017 §5):\n *\n * CREATED ── function entry ──────────────────────────► BOOTING\n * │ │\n * │ control port installed\n * │ │\n * │ ┌───────┴───────┐\n * │ │ │\n * │ ▼ ▼\n * │ (host sends init) READY ◄─── ready sent\n * │ │ │\n * │ ▼ │ init\n * │ RUNNING │\n * │ │ │\n * │ (program completes / throws / cancel) │\n * │ │ │\n * │ ▼ │\n * │ reset() + ready sent ───────────────► READY\n * │\n * └── (host closes control port) ─► worker terminates, no further transitions\n *\n * A later `connect` re-enters `READY` from wherever the worker is: a handover, not a wait — which is\n * how a worker the host abandoned is picked up by the next run (see the connect handler, ADR-0017\n * §10(h)).\n *\n * The `ready` frame has two meanings under ADR-0017 §5:\n * - cold start: \"booted, send init\".\n * - warm reuse: \"cleared per-run state, ready for next init\".\n *\n * Run identity: every accepted `init` starts a new run and claims the worker for it\n * (a run ordinal, captured by that run). A run only owns the worker until the next\n * `init` supersedes it — so the reset that ends a run must prove it still owns the\n * worker before it clears anything (see `reset`).\n *\n * Frame ownership: a run's outbound frames (`log`, `narration`, `phase`, `call`, `result`,\n * `error`) are posted through the control port that run captured when its `init` arrived —\n * never through \"whichever port the worker is connected to now\". Warm reuse replaces the\n * connection while a superseded run may still be unwinding, so routing is what keeps one run's\n * terminal frame from settling the next one (see `post` and `startRun`).\n *\n * The worker is loaded by file URL (`dist/worker.js`, see `worker-entry.ts`); V8's\n * code cache and Node's module cache survive across warm-reuse spawns. The\n * SELF-CONTAINMENT RULE that previously gated this module — `Function.prototype.toString()`\n * of `workerMain` into a `data:` URL — is retired.\n */\nimport { describeValue } from \"./protocol.ts\";\nimport type {\n PtcCancelReason,\n PtcErrorKind,\n PtcJsonObject,\n PtcJsonValue,\n PtcLogLevel,\n WorkerProtocolSpec,\n} from \"./protocol.ts\";\n\n/** The subset of `MessagePort`/`parentPort` the worker uses. */\nexport interface WorkerMainPort {\n on(event: \"message\", listener: (value: unknown) => void): unknown;\n on(event: \"close\", listener: () => void): unknown;\n postMessage(value: unknown): void;\n}\n\nexport interface WorkerMainDeps {\n parentPort: WorkerMainPort;\n /**\n * The spawning host's `workerData`: the frozen per-run env snapshot `{ env }` (F3,\n * ADR-0005) and nothing else. Per-run identity is *not* carried here: a warm worker\n * outlives the run that spawned it, so the host sends each run's `runId` in its own\n * `init` frame instead. This worker never reads either one — it routes calls, and the\n * host attributes frames to runs on its side.\n */\n workerData: unknown;\n /** `node:util`'s `inspect`, used to render non-string console arguments. */\n inspect: (value: unknown, options?: Record<string, unknown>) => string;\n /** `node:module`'s `stripTypeScriptTypes`: the program is TypeScript, run type-stripped. */\n stripTypes: (code: string, options: { mode: \"strip\" }) => string;\n protocol: WorkerProtocolSpec;\n}\n\n/**\n * Internal lifecycle of one worker (ADR-0017 §5). The values are exported only so\n * the unit-test seam can read the current state through a shared channel; the\n * worker itself never escapes `state` outside this module.\n */\nexport type WorkerMainState = \"CREATED\" | \"BOOTING\" | \"READY\" | \"RUNNING\";\n\nexport function workerMain(deps: WorkerMainDeps): void {\n const hostFrame = deps.protocol.hostFrame;\n const workerFrame = deps.protocol.workerFrame;\n const logLevel = deps.protocol.logLevel;\n const errorKind = deps.protocol.errorKind;\n /** Wrapper name used to compile a program body (`return …` is legal inside it). */\n const programName = \"__ptcProgram\";\n\n /** Active lifecycle state — see the doc comment at the top of the module. */\n let state: WorkerMainState = \"CREATED\";\n /**\n * Run ordinal: incremented once per accepted `init` frame, never decremented. The value\n * a run was born with is its identity for life — `reset()` checks it against this\n * counter before touching anything.\n */\n let runGeneration = 0;\n\n let control: WorkerMainPort | undefined;\n let cancelled: PtcCancelReason | undefined;\n let nextCallId = 1;\n /** Call frames posted and not yet answered; capped by `maxPendingCalls` (ADR-0004). */\n let inFlightCalls = 0;\n let maxPendingCalls = Number.POSITIVE_INFINITY;\n const admissionWaiters: Array<{ resolve: () => void; reject: (error: unknown) => void }> = [];\n const pending = new Map<\n number,\n { resolve: (value: unknown) => void; reject: (error: unknown) => void }\n >();\n /**\n * Snapshot of `globalThis` taken once, at boot (end of `installWarningCapture`), i.e. the\n * \"warm baseline\" a reset restores to.\n *\n * What it covers: `globalThis`'s own enumerable string keys — the way a PTC program normally\n * touches the realm. A `globalThis.x = 1` left by run N is deleted before run N+1 starts, and any\n * `console` / `tools` / `log` / `phase` / `parallel` / `pipeline` installed by run N is put back\n * to its boot value for run N+1 to replace with its own install.\n *\n * What it does **not** cover — a superseded run's leftovers that survive into the next one, so\n * \"warm reuse is hermetic\" would be the wrong reading of this snapshot:\n * - a property added to `globalThis` that is non-enumerable or symbol-keyed (`Object.keys` is\n * what both the snapshot and the restore walk, so such a property is neither deleted nor put\n * back);\n * - anything reachable through another object: `Array.prototype.x = 1`, a mutated built-in, the\n * module-level state of a module the program imported (Node caches modules per worker, and a\n * program can `import()` one);\n * - `process` state the program wrote — `process.title`, `process.exitCode`, listeners it added;\n * - timers it started, which keep firing (see `startRun`).\n *\n * Those are known, accepted limits of warm reuse rather than oversights of this snapshot.\n *\n * The *boot* snapshot is the only clean starting point there is: a later `connect` must not\n * take a new one, or whatever the run it superseded left behind would be part of the baseline\n * and would be restored into every run after it.\n */\n let warmBaseline: Map<string, unknown> | undefined;\n\n const globals = (): Record<string, unknown> => globalThis as unknown as Record<string, unknown>;\n\n class ToolCallError extends Error {\n toolName: string;\n constructor(toolName: string, message: string) {\n super(message);\n this.name = \"ToolCallError\";\n this.toolName = toolName;\n }\n }\n\n const messageOf = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\n /**\n * Trim a stack down to what a reader can act on.\n *\n * Capped at a small depth so the model-facing stack stays inside the output budget.\n * Now that the worker is loaded by file URL, no `data:text/javascript,…` frames\n * appear at all — the rule kept the previous bootstrap's encoded payload from\n * filling the stack.\n */\n const stackOf = (error: unknown): string | undefined => {\n if (!(error instanceof Error) || typeof error.stack !== \"string\") return undefined;\n const lines = error.stack.split(\"\\n\");\n const kept = [lines[0] ?? \"\"];\n for (const line of lines.slice(1)) {\n kept.push(line);\n if (kept.length >= 6) break;\n }\n return kept.join(\"\\n\");\n };\n /**\n * Post a frame through `port` — the control port the caller's run belongs to — defaulting to\n * the port the worker is currently connected to.\n *\n * Invariant (ADR-0017 §10(b)): *a run's outbound frames travel only through the port that run\n * captured at `init` time*. Warm reuse installs a new port while a superseded run may still be\n * unwinding, and that run's terminal `result` must not land on the *next* run's port — the host\n * reads any `result` there as \"the current run settled\" (`handleFrame` → `finish()`), which\n * would end a run whose program never finished. The port of a run the host has abandoned has\n * been closed on the host's side, so its late frames fail to send and are dropped here; that is\n * the right outcome for a frame nobody owns any more.\n *\n * Only realm-level frames — the `connect` handshake's `ready`, warning `log`s, which belong to\n * the worker rather than to a program — use the default.\n */\n const post = (frame: unknown, port: WorkerMainPort | undefined = control): boolean => {\n if (!port) return false;\n try {\n port.postMessage(frame);\n return true;\n } catch {\n // Port closed (run already settled) — nothing useful to do with the frame.\n return false;\n }\n };\n\n const postLog = (level: PtcLogLevel, text: string, port?: WorkerMainPort): void => {\n post({ kind: workerFrame.log, level, text }, port);\n };\n\n const postError = (\n kind: PtcErrorKind,\n message: string,\n stack?: string,\n port?: WorkerMainPort,\n ): void => {\n post(\n stack === undefined\n ? { kind: workerFrame.error, error: { kind, message } }\n : { kind: workerFrame.error, error: { kind, message, stack } },\n port,\n );\n };\n\n const abortError = (reason: PtcCancelReason): Error => {\n const error = new Error(reason === \"timeout\" ? \"PTC run timed out\" : \"PTC run was cancelled\");\n error.name = \"AbortError\";\n return error;\n };\n\n const closedError = (): Error => {\n const error = new Error(\"the PTC control channel closed before the call completed\");\n error.name = \"AbortError\";\n return error;\n };\n\n /* ------------------------------------------------------------------ */\n /* call admission */\n /* ------------------------------------------------------------------ */\n\n /**\n * Admission control for host binding calls.\n *\n * \"Maximum simultaneous host binding calls\" is the worker's invariant to keep: a call\n * frame is only posted once fewer than `maxPendingCalls` are outstanding, so a wide\n * `Promise.all` / `parallel()` burst queues here rather than arriving at the host in one\n * tick. The host still counts arrivals as a backstop, but it must never see this budget\n * exceeded by a well-behaved program.\n *\n * Waiting for a slot is cancel-aware: `cancel` and a closed control port reject waiters\n * immediately, so an oversized burst unwinds at once instead of waiting out the grace\n * window before the host terminates the worker.\n */\n const acquireCallSlot = async (): Promise<void> => {\n if (inFlightCalls < maxPendingCalls) {\n inFlightCalls += 1;\n return;\n }\n await new Promise<void>((resolve, reject) => {\n admissionWaiters.push({ resolve, reject });\n });\n };\n\n const releaseCallSlot = (): void => {\n const next = admissionWaiters.shift();\n if (next) {\n // Hand the slot over: `inFlightCalls` already accounts for it, so it stays put.\n next.resolve();\n return;\n }\n inFlightCalls -= 1;\n };\n\n const rejectAdmissionWaiters = (error: unknown): void => {\n while (admissionWaiters.length > 0) {\n const waiter = admissionWaiters.shift();\n if (waiter) waiter.reject(error);\n }\n };\n\n /** Settle every outstanding call and every admission wait, so nothing can hang. */\n const flushPendingCalls = (error: Error): void => {\n rejectAdmissionWaiters(error);\n for (const [callId, entry] of pending) {\n pending.delete(callId);\n entry.reject(error);\n }\n };\n\n /**\n * F3 — reinstall the frozen per-run environment carried in `workerData`.\n *\n * The spawn already passes the same snapshot as the worker's `env` option; rebuilding\n * `process.env` from `workerData` here is what makes the snapshot the authority: the\n * program's environment is the frozen record, never whatever `process.env` happened\n * to hold when a binding call crossed the wire.\n */\n const installFrozenEnv = (): void => {\n const data = deps.workerData;\n if (typeof data !== \"object\" || data === null) return;\n const snapshot = (data as { env?: unknown }).env;\n if (typeof snapshot !== \"object\" || snapshot === null || Array.isArray(snapshot)) return;\n const env = snapshot as Record<string, unknown>;\n for (const key of Object.keys(process.env)) {\n if (!(key in env)) delete process.env[key];\n }\n for (const key of Object.keys(env)) {\n const value = env[key];\n if (typeof value === \"string\") process.env[key] = value;\n }\n };\n\n /**\n * Lossless-JSON materialization of the program's return value (R1 §3 `invalid-output`).\n *\n * Plain JSON only: class instances, `Date`/`Map`/`Set`, functions, symbols, bigints,\n * non-finite numbers and cycles are rejected with a path-qualified reason instead of\n * being silently lossy through the transport. `undefined` follows `JSON.stringify`:\n * object properties are dropped, array slots become `null`.\n */\n const toJsonValue = (\n value: unknown,\n ): { ok: true; value: PtcJsonValue | undefined } | { ok: false; reason: string } => {\n const seen = new Set<object>();\n\n const walk = (\n candidate: unknown,\n path: string,\n ): { ok: true; value: PtcJsonValue | undefined } | { ok: false; reason: string } => {\n if (candidate === null) return { ok: true, value: null };\n if (typeof candidate === \"string\" || typeof candidate === \"boolean\")\n return { ok: true, value: candidate };\n if (typeof candidate === \"undefined\") return { ok: true, value: undefined };\n if (typeof candidate === \"number\") {\n if (!Number.isFinite(candidate)) {\n return {\n ok: false,\n reason: `${path} is ${String(candidate)}, which is not representable as JSON`,\n };\n }\n return { ok: true, value: candidate };\n }\n if (typeof candidate !== \"object\") {\n return {\n ok: false,\n reason: `${path} is ${describeValue(candidate)}; results must be lossless JSON`,\n };\n }\n\n if (Array.isArray(candidate)) {\n if (seen.has(candidate)) return { ok: false, reason: `${path} is a circular reference` };\n seen.add(candidate);\n const items: PtcJsonValue[] = [];\n for (let index = 0; index < candidate.length; index += 1) {\n const item = walk(candidate[index], `${path}[${index}]`);\n if (!item.ok) return item;\n items.push(item.value === undefined ? null : item.value);\n }\n seen.delete(candidate);\n return { ok: true, value: items };\n }\n\n const prototype = Object.getPrototypeOf(candidate);\n if (prototype !== Object.prototype && prototype !== null) {\n const ctor = (candidate as { constructor?: { name?: string } }).constructor;\n const name =\n ctor && typeof ctor.name === \"string\" && ctor.name.length > 0 ? ctor.name : \"an object\";\n return { ok: false, reason: `${path} is a ${name}; results must be plain JSON objects` };\n }\n if (seen.has(candidate)) return { ok: false, reason: `${path} is a circular reference` };\n seen.add(candidate);\n const entries: PtcJsonObject = {};\n for (const key of Object.keys(candidate)) {\n const item = walk((candidate as Record<string, unknown>)[key], `${path}.${key}`);\n if (!item.ok) return item;\n if (item.value !== undefined) entries[key] = item.value;\n }\n seen.delete(candidate);\n return { ok: true, value: entries };\n };\n\n return walk(value, \"result\");\n };\n\n const formatArgs = (args: readonly unknown[]): string =>\n args\n .map((arg) =>\n typeof arg === \"string\"\n ? arg\n : deps.inspect(arg, { depth: 4, breakLength: Infinity, colors: false }),\n )\n .join(\" \");\n\n /**\n * Capture `console` instead of letting worker stdio reach the host terminal.\n *\n * Only the printing methods exist on this surface; everything routes to `log` frames\n * so the model (not the terminal) sees the program's output. Log frames belong to the run\n * whose console this is, hence the captured `port`.\n */\n const installConsole = (port: WorkerMainPort | undefined): void => {\n const write = (level: PtcLogLevel) => {\n return (...args: unknown[]): void => {\n postLog(level, formatArgs(args), port);\n };\n };\n globals().console = {\n log: write(logLevel.log),\n info: write(logLevel.info),\n warn: write(logLevel.warn),\n error: write(logLevel.error),\n debug: write(logLevel.debug),\n };\n };\n\n /**\n * Route `process.emitWarning` output through `log` frames.\n *\n * Node's default warning printer writes to stderr, which is piped to the host terminal.\n * `ExperimentalWarning`s are dropped rather than forwarded: the PTC runtime itself uses\n * experimental Node APIs (type stripping, for one) and those warnings are about the\n * harness, not about the program — forwarding them would put Node-internals noise into\n * every run's logs.\n */\n const installWarningCapture = (): void => {\n if (typeof process.removeAllListeners !== \"function\" || typeof process.on !== \"function\")\n return;\n process.removeAllListeners(\"warning\");\n process.on(\"warning\", (warning: unknown) => {\n const record =\n typeof warning === \"object\" && warning !== null\n ? (warning as Record<string, unknown>)\n : undefined;\n const name = record && typeof record.name === \"string\" ? record.name : \"Warning\";\n if (name === \"ExperimentalWarning\") return;\n const detail =\n record && typeof record.message === \"string\" ? record.message : String(warning);\n postLog(logLevel.warn, `${name}: ${detail}`);\n });\n };\n\n /**\n * Compile a program body into a callable.\n *\n * The body is wrapped in an async function so `return` and `await` work at the top\n * level, then run through `stripTypeScriptTypes` so the same body may carry type\n * annotations (DSH's \"type annotations are advisory, the code runs type-stripped\").\n * JavaScript the TypeScript parser rejects falls back to the unstripped source; a\n * genuine syntax error then surfaces from the `Function` constructor instead.\n */\n const compileProgram = (code: string): (() => unknown) => {\n const wrapped = `async function ${programName}() {\\n${code}\\n}`;\n let source = wrapped;\n try {\n source = deps.stripTypes(wrapped, { mode: \"strip\" });\n } catch {\n source = wrapped;\n }\n // oxlint-disable-next-line typescript/no-implied-eval -- compiling the submitted program is this worker's job; it never compiles host code.\n return new Function(`${source}\\nreturn ${programName}();`) as () => unknown;\n };\n\n const runProgram = async (\n code: string,\n generation: number,\n port: WorkerMainPort | undefined,\n ): Promise<void> => {\n try {\n let program: () => unknown;\n try {\n program = compileProgram(code);\n } catch (error) {\n postError(\n errorKind.exception,\n `program failed to compile: ${messageOf(error)}`,\n stackOf(error),\n port,\n );\n return;\n }\n try {\n const value = await program();\n const normalized = toJsonValue(value);\n if (!normalized.ok) {\n postError(errorKind.invalidOutput, normalized.reason, undefined, port);\n return;\n }\n post(\n normalized.value === undefined\n ? { kind: workerFrame.result }\n : { kind: workerFrame.result, value: normalized.value },\n port,\n );\n } catch (error) {\n postError(cancelled ?? errorKind.exception, messageOf(error), stackOf(error), port);\n }\n } finally {\n // RUNNING → READY: every path through `runProgram` (compile fail, completion,\n // exception, cancel) leaves through here. Resetting and re-posting `ready`\n // is what makes warm reuse safe — without it, the worker would have to be\n // terminated and respawned between turns (ADR-0017 §5). The run ordinal is\n // threaded through so a run that has since been superseded resets nothing, and\n // the run's own port is threaded through so its `ready` cannot reach the port\n // that replaced it.\n await reset(generation, port);\n }\n };\n\n /**\n * `tools.<name>(args)` — acquire an admission slot, post a call frame, and await the\n * matching `call-result`.\n *\n * The slot is released on every exit path (settled, admission refused by `post`, cancel),\n * which is what keeps a burst draining instead of deadlocking. Call frames carry the\n * binding's own run port: a superseded run's late call is dropped at its closed port instead\n * of arriving at the host as a call for a run it never made.\n */\n const makeBinding = (name: string, port: WorkerMainPort | undefined) => {\n return async (args: unknown): Promise<unknown> => {\n if (cancelled) throw abortError(cancelled);\n await acquireCallSlot();\n try {\n if (cancelled) throw abortError(cancelled);\n const callId = nextCallId;\n nextCallId += 1;\n const promise = new Promise<unknown>((resolve, reject) => {\n pending.set(callId, { resolve, reject });\n });\n const sent = post({ kind: workerFrame.call, callId, tool: name, args }, port);\n if (!sent) {\n pending.delete(callId);\n throw new ToolCallError(\n name,\n `${name}() could not be called: the arguments are not transferable or the run has ended`,\n );\n }\n return await promise;\n } finally {\n releaseCallSlot();\n }\n };\n };\n\n const settleCall = (frame: Record<string, unknown>): void => {\n const callId = frame.callId;\n if (typeof callId !== \"number\") return;\n const entry = pending.get(callId);\n if (!entry) return;\n pending.delete(callId);\n if (frame.ok === true) {\n entry.resolve(frame.value);\n return;\n }\n entry.reject(\n new ToolCallError(\n typeof frame.tool === \"string\" ? frame.tool : \"unknown\",\n typeof frame.message === \"string\" ? frame.message : \"binding call failed\",\n ),\n );\n };\n\n const cancelPending = (reason: PtcCancelReason): void => {\n cancelled = reason;\n flushPendingCalls(abortError(reason));\n };\n\n /**\n * Confirm a cancel that has nothing to flush, and forget it.\n *\n * A cancel can arrive while the worker is idle — booting, or freshly reset and waiting for the\n * next `init`. There is no program to interrupt and no pending call to reject, so the honest\n * answer is to report the cancel: the host asked to stop, and it should settle now rather than\n * wait out its grace window for a run that will never start (and the `init` it might send next\n * would clear the verdict and run the program anyway).\n */\n const reportIdleCancel = (reason: PtcCancelReason, port: WorkerMainPort): void => {\n cancelled = undefined;\n const error = abortError(reason);\n postError(reason, error.message, undefined, port);\n };\n\n /* ------------------------------------------------------------------ */\n /* workflow helpers (ptc_workflow surface only) */\n /* ------------------------------------------------------------------ */\n\n const assertItemCount = (helper: string, count: number, maxItemsPerCall: number): void => {\n if (count > maxItemsPerCall) {\n throw new RangeError(\n `${helper}() received ${count} items, exceeding maxItemsPerCall (${maxItemsPerCall})`,\n );\n }\n };\n\n const installWorkflowHelpers = (\n args: unknown,\n maxItemsPerCall: number,\n port: WorkerMainPort | undefined,\n ): void => {\n const target = globals();\n target.args = args === undefined ? null : args;\n\n target.log = (message: unknown): void => {\n if (typeof message !== \"string\")\n throw new TypeError(`log(message) expects a string, received ${describeValue(message)}`);\n post({ kind: workerFrame.narration, message }, port);\n };\n\n target.phase = (title: unknown): void => {\n if (typeof title !== \"string\")\n throw new TypeError(`phase(title) expects a string, received ${describeValue(title)}`);\n post({ kind: workerFrame.phase, title }, port);\n };\n\n // parallel(thunks): all thunks start together; a rejected item becomes `null`\n // instead of failing the call (R1 §4).\n target.parallel = async (thunks: unknown): Promise<unknown[]> => {\n if (!Array.isArray(thunks))\n throw new TypeError(\n `parallel(thunks) expects an array of functions, received ${describeValue(thunks)}`,\n );\n assertItemCount(\"parallel\", thunks.length, maxItemsPerCall);\n for (let index = 0; index < thunks.length; index += 1) {\n if (typeof thunks[index] !== \"function\") {\n throw new TypeError(\n `parallel(thunks) expects functions; item ${index} is ${describeValue(thunks[index])}`,\n );\n }\n }\n return await Promise.all(\n (thunks as Array<() => unknown>).map(async (thunk) => {\n try {\n return await thunk();\n } catch {\n return null;\n }\n }),\n );\n };\n\n // pipeline(items, ...stages): stages run per item with no cross-stage barrier; a\n // failing item becomes `null` while its siblings continue (R1 §4).\n target.pipeline = async (items: unknown, ...stages: unknown[]): Promise<unknown[]> => {\n if (!Array.isArray(items))\n throw new TypeError(\n `pipeline(items, ...stages) expects an array of items, received ${describeValue(items)}`,\n );\n assertItemCount(\"pipeline\", items.length, maxItemsPerCall);\n if (stages.length === 0)\n throw new TypeError(\"pipeline(items, ...stages) requires at least one stage function\");\n for (let index = 0; index < stages.length; index += 1) {\n if (typeof stages[index] !== \"function\") {\n throw new TypeError(\n `pipeline(items, ...stages) expects stage functions; stage ${index} is ${describeValue(stages[index])}`,\n );\n }\n }\n const stageFunctions = stages as Array<\n (previous: unknown, item: unknown, index: number) => unknown\n >;\n return await Promise.all(\n (items as unknown[]).map(async (item, index) => {\n try {\n let current: unknown = item;\n for (const stage of stageFunctions) {\n current = await stage(current, item, index);\n }\n return current;\n } catch {\n return null;\n }\n }),\n );\n };\n };\n\n /* ------------------------------------------------------------------ */\n /* reset handshake (ADR-0017 §5) */\n /* ------------------------------------------------------------------ */\n\n /**\n * Restore `globalThis` to the warm baseline taken at the end of the worker's\n * boot-time setup (`installWarningCapture`).\n *\n * This is stronger than deleting the known `RUN_GLOBAL_KEYS`: it also wipes any\n * stray property the previous run's program left behind (`globalThis.x = 1` and\n * similar). Without it, warm reuse would leak state from one run to the next.\n * Enumerating own *enumerable string* keys is also its limit — see `warmBaseline`\n * for the leftovers that walk past it.\n *\n * Properties in the baseline are restored even if the program overwrote them —\n * that is what keeps `console` honest for the next run, since the program's\n * console override does not survive the reset.\n */\n const restoreWarmBaseline = (): void => {\n if (!warmBaseline) return;\n const target = globals();\n for (const key of Object.keys(target)) {\n if (!warmBaseline.has(key)) delete target[key];\n }\n for (const [key, value] of warmBaseline) {\n // Skip properties whose descriptor is non-writable (e.g. `globalThis.crypto`\n // on modern Node — a getter with no setter). Forcing a write would throw and\n // break reset for every other key. The worker didn't install these, so leaving\n // them untouched is the correct behaviour — no run owns them.\n const descriptor = Object.getOwnPropertyDescriptor(target, key);\n if (descriptor !== undefined && descriptor.writable === false) continue;\n try {\n target[key] = value;\n } catch {\n // Same defence for accessor properties whose setter throws or rejects the\n // assignment — non-installed globals stay as Node shipped them.\n }\n }\n };\n\n /**\n * RUNNING → READY: clear the per-run state this worker owns so it is safe to accept\n * another `init` frame on warm reuse (ADR-0017 §5).\n *\n * Order matters: flush first so no settled call leaks into the next run, then\n * restore the warm baseline (the program may have left values behind that would\n * shadow the next install), then rehydrate the frozen env so the next run starts\n * from the same `process.env` snapshot the host captured. State transitions to\n * `READY` last — only when the worker is actually eligible for the next `init`.\n *\n * What it clears is exactly: the outstanding calls and admission waiters, the run\n * bookkeeping (`inFlightCalls`, `cancelled`, `nextCallId`, `pending`), `globalThis`'s own\n * enumerable keys (via the warm baseline — see `warmBaseline` for what that misses) and\n * `process.env`. It does **not** stop timers the program left running; nothing can, see\n * `startRun`. And when the run that produced this reset was superseded, none of it happens at\n * all: the clearing then falls to the *next* run's `startRun` (see the invariant below).\n *\n * Invariant — a reset is scoped to the run that produced it: `generation` is the run\n * ordinal the finishing run was born with. If the worker has since been handed to a\n * newer run (`generation !== runGeneration`), this reset is a no-op: it must not clear\n * the newer run's calls, globals or bookkeeping, and it must not post `ready` (the\n * host reads `ready` as \"the current run settled, send the next init\" — posting a\n * stranger's `ready` is what makes a program execute twice). Ownership is captured at\n * `init` time rather than read from the shared `state`, because `state` belongs to\n * whoever owns the worker now. `port` is the run's own control port for the same reason:\n * a `ready` that survives the ownership check still has no business on another run's port.\n */\n const reset = async (generation: number, port: WorkerMainPort | undefined): Promise<void> => {\n if (state !== \"RUNNING\" || generation !== runGeneration) return;\n flushPendingCalls(closedError());\n inFlightCalls = 0;\n cancelled = undefined;\n nextCallId = 1;\n pending.clear();\n restoreWarmBaseline();\n installFrozenEnv();\n\n state = \"READY\";\n post({ kind: workerFrame.ready }, port);\n };\n\n /* ------------------------------------------------------------------ */\n /* frame handling */\n /* ------------------------------------------------------------------ */\n\n /**\n * Claim the worker for one run and install that run's surface.\n *\n * `port` is the channel the run's `init` arrived on; it *is* the run's control port for life.\n * Every frame the run produces afterwards — `log`, `narration`, `phase`, `call`, `result`,\n * `error`, its closing `ready` — is posted through it, even if the worker has since been handed\n * to another run (see `post`).\n *\n * The run starts from a clean realm. That cannot be left to the previous run's `reset()`: a run\n * the host abandoned is superseded, and its reset is a generation-guarded no-op — so its strays on\n * `globalThis` (`tools`, the workflow helpers, whatever its program assigned) and its bookkeeping\n * would otherwise live on into this run and break the isolation warm reuse promises (ADR-0017\n * §10(d) — and note §5 is explicit that the reset handshake is *not* where isolation comes\n * from). Clearing here is unconditional: one run starting is the end of everything the previous\n * round was doing, whatever the previous round did or did not do.\n *\n * \"Clean\" is what `restoreWarmBaseline` can restore — `globalThis`'s own enumerable keys, then the\n * frozen env and this run's fresh installs — plus this worker's run bookkeeping. It is honestly\n * not every trace a program can leave: a timer it started keeps firing, a prototype it patched\n * stays patched, and `process` state it wrote stays written (see `warmBaseline` for the list).\n * Timers are the leftover this function used to claim to clear, and the claim was false: Node\n * offers no way to enumerate a worker's pending timers — inside a worker thread\n * `process._getActiveHandles()` returns `[]` and `process.getActiveResourcesInfo()` reports names\n * (`\"Timeout\"`), not handles (both checked on Node 24.21.0). A leftover interval is therefore a\n * known, accepted limitation of warm reuse, not something this function clears.\n */\n const startRun = (\n frame: Record<string, unknown>,\n generation: number,\n port: WorkerMainPort,\n ): void => {\n restoreWarmBaseline();\n\n // Bookkeeping resets with the globals: a cancel verdict from the abandoned run must not make\n // this run's first `tools.*` call throw `PTC run timed out`, and calls admitted but never\n // settled cannot be allowed to hold slots in this run's budget (ADR-0004).\n cancelled = undefined;\n inFlightCalls = 0;\n pending.clear();\n\n installFrozenEnv();\n installConsole(port);\n\n // ADR-0004's ceiling, handed over per run. The host's init guard requires the field;\n // the fallback only exists so a hand-built frame cannot silently wedge the surface\n // (the host's arrival-counted backstop still catches a flood in that case).\n maxPendingCalls =\n typeof frame.maxPendingCalls === \"number\" &&\n Number.isFinite(frame.maxPendingCalls) &&\n frame.maxPendingCalls > 0\n ? frame.maxPendingCalls\n : Number.POSITIVE_INFINITY;\n\n const tools: Record<string, (args: unknown) => Promise<unknown>> = {};\n const bindingNames = Array.isArray(frame.bindings)\n ? frame.bindings.filter((name): name is string => typeof name === \"string\")\n : [];\n for (const name of bindingNames) tools[name] = makeBinding(name, port);\n // Known-but-disabled tools (T7, #21): stub each with an actionable error instead of\n // letting the program hit `tools.write is not a function`.\n const available = bindingNames.join(\", \") || \"(none)\";\n const candidates = Array.isArray(frame.bindingCandidates) ? frame.bindingCandidates : [];\n for (const name of candidates) {\n if (typeof name !== \"string\" || tools[name]) continue;\n tools[name] = async () => {\n throw new ToolCallError(\n name,\n `no binding named \"${name}\" in this run; available bindings: ${available}`,\n );\n };\n }\n globals().tools = tools;\n\n if (frame.surface === \"workflow\") {\n const maxItemsPerCall = typeof frame.maxItemsPerCall === \"number\" ? frame.maxItemsPerCall : 0;\n installWorkflowHelpers(frame.args, maxItemsPerCall, port);\n }\n\n void runProgram(typeof frame.code === \"string\" ? frame.code : \"\", generation, port);\n };\n\n /**\n * Handle one host frame, tagging it with the port it arrived on: that port *is* the run's\n * control port if the frame is an `init` (see `startRun`), so the run's frames stay on the\n * channel its own host is listening to.\n */\n const handleHostFrame = (raw: unknown, port: WorkerMainPort): void => {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) return;\n const frame = raw as Record<string, unknown>;\n if (frame.kind === hostFrame.init) {\n // Only accept init in READY — during CREATED/BOOTING we are not installed yet,\n // during RUNNING a previous run is still in flight (or settling via `reset()`).\n if (state !== \"READY\") return;\n // A fresh run: claim the worker by bumping the run ordinal, then hand that ordinal\n // to the run so its eventual `reset()` can prove it still owns the worker.\n runGeneration += 1;\n const generation = runGeneration;\n state = \"RUNNING\";\n startRun(frame, generation, port);\n return;\n }\n if (frame.kind === hostFrame.callResult) {\n settleCall(frame);\n return;\n }\n if (frame.kind === hostFrame.cancel) {\n const reason = frame.reason === \"timeout\" ? \"timeout\" : \"abort\";\n if (state === \"READY\") {\n // No run is in flight, so there is nothing to flush — confirm the cancel instead of\n // leaving the host to wait out its window (see `reportIdleCancel`).\n reportIdleCancel(reason, port);\n return;\n }\n cancelPending(reason);\n }\n };\n\n // `port.on(\"message\", ...)` hands over the raw value — unlike a browser `MessageEvent`\n // there is no `{ data }` wrapper to unwrap here.\n state = \"BOOTING\";\n deps.parentPort.on(\"message\", (value: unknown) => {\n if (typeof value !== \"object\" || value === null) return;\n const frame = value as Record<string, unknown>;\n if (frame.kind !== hostFrame.connect) return;\n const port = frame.port;\n if (\n typeof port !== \"object\" ||\n port === null ||\n typeof (port as WorkerMainPort).on !== \"function\"\n )\n return;\n const connected = port as WorkerMainPort;\n // A `connect` is a (re)handover: the pool gives this worker to the run that just built this\n // channel. A previous run may still be unwinding here — it was superseded, so its `reset()`\n // will be a no-op and the new run's `startRun` is what clears what it left behind. Frames are\n // handled with the port they arrived on, which is how each run captures its own control port.\n control = connected;\n connected.on(\"message\", (raw: unknown) => {\n handleHostFrame(raw, connected);\n });\n // The host is gone (it closed the control port, e.g. after terminating the run): no\n // response can arrive any more, so stop waiting for one. Only the port the worker still\n // owns gets to say that, though: `close` is a queued event, and a run the host abandoned\n // has its port closed while the worker may already belong to the next run, whose calls are\n // in flight in the *shared* `pending` map — flushing on a superseded run's late close would\n // reject the next run's calls. (A close with no handover since keeps `control === connected`,\n // which is the case this flush exists for.)\n connected.on(\"close\", () => {\n if (control === connected) flushPendingCalls(closedError());\n });\n installWarningCapture();\n // Snapshot `globalThis` once, at boot, before any run has touched it: this is the warm\n // baseline every reset restores to. A later `connect` must **not** re-snapshot — whatever the\n // run it superseded left on `globalThis` would be baked into the baseline and become\n // permanent, which is the leak the baseline exists to prevent.\n //\n // That one-shot snapshot is also how this handler tells a first boot from a handover, which is\n // what decides the fate of a leftover cancel verdict below.\n const isFirstBoot = warmBaseline === undefined;\n if (isFirstBoot) warmBaseline = new Map(Object.entries(globals()));\n // The handover's own transition (ADR-0017 §10(h)): a `connect` puts the worker back in `READY`\n // **unconditionally**, from whichever state it was in — `BOOTING` on the first connect, and on\n // every later one from `RUNNING` (a run the pool took back while its program was still\n // unwinding) or from `READY` (an idle worker). §5 records the machine as\n // `CREATED → BOOTING → READY ↔ RUNNING` with `init` and the settle as its transitions; this\n // forced re-entry to `READY` is the one it does not mention, and it is what makes warm reuse\n // work at all — the next run never has to wait for the previous program to stop. It\n // deliberately does *not* clean up on the way: no flush, no `globalThis` restore. The\n // superseded run may still be unwinding, its late `reset()` is a generation-guarded no-op, and\n // clearing is the incoming run's `startRun` (§10(d)).\n state = \"READY\";\n // A cancel that landed while this worker was still booting is the whole story: the host asked\n // to stop before it ever handed over a program. Report it instead of announcing readiness for\n // a run that is already over — otherwise the host restarts its grace window on this `ready`\n // and waits out the full window for a program that will never start, and the `init` it sends\n // next would clear this verdict and run the program anyway.\n //\n // That reasoning holds only for the **first** connect. On a later one the verdict belongs to\n // the run this worker just stopped serving, and the caller on the other end is a stranger with\n // its own lifecycle: replaying \"cancelled\" down its channel would fail it before its `init`\n // ever arrives (ADR-0017 §10(e)). Clearing silently is what keeps one run's cancel from ending\n // the next.\n if (cancelled !== undefined) {\n if (isFirstBoot) {\n reportIdleCancel(cancelled, connected);\n return;\n }\n cancelled = undefined;\n }\n post({ kind: workerFrame.ready }, connected);\n });\n}\n","/**\n * Worker entry — loaded by file URL (ADR-0017 §7).\n *\n * The previous bootstrap composed a `data:text/javascript,…` URL from\n * `Function.prototype.toString()` of `workerMain`, which kept the package as a\n * single self-contained file but paid a fresh V8 spin-up + module-graph parse\n * for every worker spawn (no code-cache reuse). After the rolldown dual-entry\n * build emits `dist/worker.js` as a sibling of `dist/index.js`, this file is\n * the target the host loads; V8 and Node's module cache survive across\n * warm-reuse spawns.\n *\n * The protocol tables travel as static imports in both bundles (host imports\n * from `dist/index.js`, worker imports from `dist/worker.js`) — both files\n * bundle `./protocol.ts`, so each side constructs `workerProtocolSpec()`\n * independently and the wire strings stay aligned. This removes the build-time\n * protocol literal the data: URL used to carry.\n *\n * `workerData` is the spawn-time payload `{ env }` — the frozen per-run env\n * snapshot (F3, ADR-0005) — and nothing else. Run identity is *not* spawn-time:\n * a warm worker outlives the run that spawned it, so the host sends each run's\n * `runId` in its own `init` frame instead. `workerMain` reads neither (see its\n * `WorkerMainDeps.workerData` note); `runId` is host-side bookkeeping for\n * attributing frames to a run.\n */\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { inspect } from \"node:util\";\nimport { stripTypeScriptTypes } from \"node:module\";\nimport { workerMain } from \"./worker-main.ts\";\nimport { workerProtocolSpec } from \"./protocol.ts\";\n\nworkerMain({\n parentPort: parentPort as unknown as Parameters<typeof workerMain>[0][\"parentPort\"],\n workerData,\n inspect,\n stripTypes: stripTypeScriptTypes,\n protocol: workerProtocolSpec(),\n});\n"],"mappings":"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"}
|