@goah/cli 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/dist/LICENSE +201 -0
  2. package/dist/THIRD-PARTY-NOTICES.md +2319 -0
  3. package/dist/anthropic-messages-WBFOHES5.js +7214 -0
  4. package/dist/azure-openai-responses-NZFH3PO6.js +253 -0
  5. package/dist/chunk-25XSBFX6.js +639 -0
  6. package/dist/chunk-2QBQZGXF.js +110 -0
  7. package/dist/chunk-2ZP2NBW3.js +345 -0
  8. package/dist/chunk-4KA63VNZ.js +2 -0
  9. package/dist/chunk-4M6TXTT5.js +86 -0
  10. package/dist/chunk-4US7ZHT3.js +20 -0
  11. package/dist/chunk-6M3OOCKO.js +11809 -0
  12. package/dist/chunk-7AXAFDPG.js +17 -0
  13. package/dist/chunk-7E7V6OIU.js +920 -0
  14. package/dist/chunk-BXA47DTF.js +548 -0
  15. package/dist/chunk-D2DVAH37.js +25 -0
  16. package/dist/chunk-FSBUS2BI.js +26 -0
  17. package/dist/chunk-GKDRAHLI.js +4787 -0
  18. package/dist/chunk-H462EFJP.js +89 -0
  19. package/dist/chunk-IIJQ3DW4.js +35 -0
  20. package/dist/chunk-JQD5EWJY.js +34 -0
  21. package/dist/chunk-K26BVR6O.js +61 -0
  22. package/dist/chunk-KAO7WIXG.js +31 -0
  23. package/dist/chunk-KJ4HJCTK.js +1178 -0
  24. package/dist/chunk-LBKI23CC.js +9810 -0
  25. package/dist/chunk-LKBKZEHT.js +41 -0
  26. package/dist/chunk-MD7TLTXZ.js +18 -0
  27. package/dist/chunk-MPXK7QBL.js +868 -0
  28. package/dist/chunk-NRLGWZJC.js +11 -0
  29. package/dist/chunk-QBD6EJ2Z.js +1746 -0
  30. package/dist/chunk-R6I3VKME.js +132 -0
  31. package/dist/chunk-TJON22J4.js +87 -0
  32. package/dist/chunk-ULY36ME4.js +33097 -0
  33. package/dist/chunk-XALZLRYK.js +9221 -0
  34. package/dist/chunk-XPQKM3L7.js +57 -0
  35. package/dist/chunk-YH6YJ2IB.js +1773 -0
  36. package/dist/cli.d.ts +0 -2
  37. package/dist/cli.js +13716 -580
  38. package/dist/console/assets/{index-Rtc_B7cs.js → index-B1vGMXKr.js} +11 -11
  39. package/dist/console/assets/{index-Rtc_B7cs.js.map → index-B1vGMXKr.js.map} +1 -1
  40. package/dist/console/index.html +1 -1
  41. package/dist/dist-65MDQA4Q.js +1126 -0
  42. package/dist/dist-KNR2XL6J.js +39 -0
  43. package/dist/execution.d.ts +557 -2
  44. package/dist/execution.js +37 -2
  45. package/dist/faux-runner-worker.js +128 -0
  46. package/dist/google-generative-ai-YMHXZSFE.js +422 -0
  47. package/dist/google-vertex-X6DB3ZQ6.js +471 -0
  48. package/dist/index.d.ts +853 -25
  49. package/dist/index.js +84 -385
  50. package/dist/kernel.d.ts +39 -2
  51. package/dist/kernel.js +21 -2
  52. package/dist/mistral-conversations-TY3MMD6G.js +718 -0
  53. package/dist/multipart-parser-F6M4NJZU.js +373 -0
  54. package/dist/openai-codex-responses-BRDUMLN5.js +1374 -0
  55. package/dist/openai-completions-CX634XN3.js +1139 -0
  56. package/dist/openai-responses-HMCXJIHT.js +300 -0
  57. package/dist/openrouter-images-KTWET2H2.js +148 -0
  58. package/dist/pi-messages-XL5OEC4K.js +307 -0
  59. package/dist/pi-worker.js +671 -0
  60. package/dist/runner-pi.d.ts +342 -2
  61. package/dist/runner-pi.js +46 -2
  62. package/dist/runner-registry-GD4BYCQC.js +22 -0
  63. package/dist/sqlite.d.ts +446 -2
  64. package/dist/sqlite.js +15 -2
  65. package/dist/src-F2KBSV4T.js +1398 -0
  66. package/dist/supervisor.d.ts +625 -2
  67. package/dist/supervisor.js +39 -2
  68. package/dist/testkit.d.ts +564 -2
  69. package/dist/testkit.js +127 -2
  70. package/dist/transcript.d.ts +84 -2
  71. package/dist/transcript.js +25 -2
  72. package/dist/verification-worker.js +72 -0
  73. package/package.json +2 -26
  74. package/dist/cli.d.ts.map +0 -1
  75. package/dist/cli.js.map +0 -1
  76. package/dist/control.d.ts +0 -106
  77. package/dist/control.d.ts.map +0 -1
  78. package/dist/control.js +0 -242
  79. package/dist/control.js.map +0 -1
  80. package/dist/execution.d.ts.map +0 -1
  81. package/dist/execution.js.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/index.js.map +0 -1
  84. package/dist/kernel.d.ts.map +0 -1
  85. package/dist/kernel.js.map +0 -1
  86. package/dist/live-config.d.ts +0 -10
  87. package/dist/live-config.d.ts.map +0 -1
  88. package/dist/live-config.js +0 -44
  89. package/dist/live-config.js.map +0 -1
  90. package/dist/prompt-queue.d.ts +0 -13
  91. package/dist/prompt-queue.d.ts.map +0 -1
  92. package/dist/prompt-queue.js +0 -35
  93. package/dist/prompt-queue.js.map +0 -1
  94. package/dist/runner-pi.d.ts.map +0 -1
  95. package/dist/runner-pi.js.map +0 -1
  96. package/dist/runner-registry.d.ts +0 -8
  97. package/dist/runner-registry.d.ts.map +0 -1
  98. package/dist/runner-registry.js +0 -12
  99. package/dist/runner-registry.js.map +0 -1
  100. package/dist/searchable-select.d.ts +0 -24
  101. package/dist/searchable-select.d.ts.map +0 -1
  102. package/dist/searchable-select.js +0 -61
  103. package/dist/searchable-select.js.map +0 -1
  104. package/dist/secret-input.d.ts +0 -8
  105. package/dist/secret-input.d.ts.map +0 -1
  106. package/dist/secret-input.js +0 -14
  107. package/dist/secret-input.js.map +0 -1
  108. package/dist/setup-wizard.d.ts +0 -22
  109. package/dist/setup-wizard.d.ts.map +0 -1
  110. package/dist/setup-wizard.js +0 -154
  111. package/dist/setup-wizard.js.map +0 -1
  112. package/dist/sqlite.d.ts.map +0 -1
  113. package/dist/sqlite.js.map +0 -1
  114. package/dist/supervisor.d.ts.map +0 -1
  115. package/dist/supervisor.js.map +0 -1
  116. package/dist/testkit.d.ts.map +0 -1
  117. package/dist/testkit.js.map +0 -1
  118. package/dist/thread-inspect.d.ts +0 -47
  119. package/dist/thread-inspect.d.ts.map +0 -1
  120. package/dist/thread-inspect.js +0 -78
  121. package/dist/thread-inspect.js.map +0 -1
  122. package/dist/transcript.d.ts.map +0 -1
  123. package/dist/transcript.js.map +0 -1
  124. package/dist/tui-theme.d.ts +0 -17
  125. package/dist/tui-theme.d.ts.map +0 -1
  126. package/dist/tui-theme.js +0 -19
  127. package/dist/tui-theme.js.map +0 -1
  128. package/dist/tui.d.ts +0 -24
  129. package/dist/tui.d.ts.map +0 -1
  130. package/dist/tui.js +0 -784
  131. package/dist/tui.js.map +0 -1
  132. package/dist/update.d.ts +0 -16
  133. package/dist/update.d.ts.map +0 -1
  134. package/dist/update.js +0 -67
  135. package/dist/update.js.map +0 -1
  136. package/dist/web-console.d.ts +0 -33
  137. package/dist/web-console.d.ts.map +0 -1
  138. package/dist/web-console.js +0 -242
  139. package/dist/web-console.js.map +0 -1
  140. package/dist/welcome.d.ts +0 -30
  141. package/dist/welcome.d.ts.map +0 -1
  142. package/dist/welcome.js +0 -69
  143. package/dist/welcome.js.map +0 -1
  144. package/node_modules/goah-ledger-contract/dist/execution.d.ts +0 -544
  145. package/node_modules/goah-ledger-contract/dist/execution.d.ts.map +0 -1
  146. package/node_modules/goah-ledger-contract/dist/execution.js +0 -52
  147. package/node_modules/goah-ledger-contract/dist/execution.js.map +0 -1
  148. package/node_modules/goah-ledger-contract/dist/index.d.ts +0 -4
  149. package/node_modules/goah-ledger-contract/dist/index.d.ts.map +0 -1
  150. package/node_modules/goah-ledger-contract/dist/index.js +0 -4
  151. package/node_modules/goah-ledger-contract/dist/index.js.map +0 -1
  152. package/node_modules/goah-ledger-contract/dist/kernel.d.ts +0 -37
  153. package/node_modules/goah-ledger-contract/dist/kernel.d.ts.map +0 -1
  154. package/node_modules/goah-ledger-contract/dist/kernel.js +0 -8
  155. package/node_modules/goah-ledger-contract/dist/kernel.js.map +0 -1
  156. package/node_modules/goah-ledger-contract/dist/transcript.d.ts +0 -63
  157. package/node_modules/goah-ledger-contract/dist/transcript.d.ts.map +0 -1
  158. package/node_modules/goah-ledger-contract/dist/transcript.js +0 -115
  159. package/node_modules/goah-ledger-contract/dist/transcript.js.map +0 -1
  160. package/node_modules/goah-ledger-contract/package.json +0 -28
  161. package/node_modules/goah-ledger-sqlite/dist/index.d.ts +0 -86
  162. package/node_modules/goah-ledger-sqlite/dist/index.d.ts.map +0 -1
  163. package/node_modules/goah-ledger-sqlite/dist/index.js +0 -1254
  164. package/node_modules/goah-ledger-sqlite/dist/index.js.map +0 -1
  165. package/node_modules/goah-ledger-sqlite/package.json +0 -26
  166. package/node_modules/goah-runner-pi/dist/configurator.d.ts +0 -20
  167. package/node_modules/goah-runner-pi/dist/configurator.d.ts.map +0 -1
  168. package/node_modules/goah-runner-pi/dist/configurator.js +0 -423
  169. package/node_modules/goah-runner-pi/dist/configurator.js.map +0 -1
  170. package/node_modules/goah-runner-pi/dist/credential-store.d.ts +0 -14
  171. package/node_modules/goah-runner-pi/dist/credential-store.d.ts.map +0 -1
  172. package/node_modules/goah-runner-pi/dist/credential-store.js +0 -163
  173. package/node_modules/goah-runner-pi/dist/credential-store.js.map +0 -1
  174. package/node_modules/goah-runner-pi/dist/env-spec.d.ts +0 -17
  175. package/node_modules/goah-runner-pi/dist/env-spec.d.ts.map +0 -1
  176. package/node_modules/goah-runner-pi/dist/env-spec.js +0 -95
  177. package/node_modules/goah-runner-pi/dist/env-spec.js.map +0 -1
  178. package/node_modules/goah-runner-pi/dist/index.d.ts +0 -76
  179. package/node_modules/goah-runner-pi/dist/index.d.ts.map +0 -1
  180. package/node_modules/goah-runner-pi/dist/index.js +0 -326
  181. package/node_modules/goah-runner-pi/dist/index.js.map +0 -1
  182. package/node_modules/goah-runner-pi/dist/model-provider.d.ts +0 -30
  183. package/node_modules/goah-runner-pi/dist/model-provider.d.ts.map +0 -1
  184. package/node_modules/goah-runner-pi/dist/model-provider.js +0 -96
  185. package/node_modules/goah-runner-pi/dist/model-provider.js.map +0 -1
  186. package/node_modules/goah-runner-pi/dist/pi-worker.d.ts +0 -31
  187. package/node_modules/goah-runner-pi/dist/pi-worker.d.ts.map +0 -1
  188. package/node_modules/goah-runner-pi/dist/pi-worker.js +0 -579
  189. package/node_modules/goah-runner-pi/dist/pi-worker.js.map +0 -1
  190. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.d.ts +0 -2
  191. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.d.ts.map +0 -1
  192. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.js +0 -3
  193. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.js.map +0 -1
  194. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.d.ts +0 -2
  195. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.d.ts.map +0 -1
  196. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.js +0 -5
  197. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.js.map +0 -1
  198. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.d.ts +0 -2
  199. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.d.ts.map +0 -1
  200. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.js +0 -5
  201. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.js.map +0 -1
  202. package/node_modules/goah-runner-pi/dist/test-helpers.d.ts +0 -4
  203. package/node_modules/goah-runner-pi/dist/test-helpers.d.ts.map +0 -1
  204. package/node_modules/goah-runner-pi/dist/test-helpers.js +0 -13
  205. package/node_modules/goah-runner-pi/dist/test-helpers.js.map +0 -1
  206. package/node_modules/goah-runner-pi/dist/verification-worker.d.ts +0 -2
  207. package/node_modules/goah-runner-pi/dist/verification-worker.d.ts.map +0 -1
  208. package/node_modules/goah-runner-pi/dist/verification-worker.js +0 -46
  209. package/node_modules/goah-runner-pi/dist/verification-worker.js.map +0 -1
  210. package/node_modules/goah-runner-pi/package.json +0 -28
  211. package/node_modules/goah-supervisor/dist/context-view.d.ts +0 -30
  212. package/node_modules/goah-supervisor/dist/context-view.d.ts.map +0 -1
  213. package/node_modules/goah-supervisor/dist/context-view.js +0 -58
  214. package/node_modules/goah-supervisor/dist/context-view.js.map +0 -1
  215. package/node_modules/goah-supervisor/dist/index.d.ts +0 -96
  216. package/node_modules/goah-supervisor/dist/index.d.ts.map +0 -1
  217. package/node_modules/goah-supervisor/dist/index.js +0 -1075
  218. package/node_modules/goah-supervisor/dist/index.js.map +0 -1
  219. package/node_modules/goah-supervisor/dist/roles.d.ts +0 -4
  220. package/node_modules/goah-supervisor/dist/roles.d.ts.map +0 -1
  221. package/node_modules/goah-supervisor/dist/roles.js +0 -29
  222. package/node_modules/goah-supervisor/dist/roles.js.map +0 -1
  223. package/node_modules/goah-supervisor/dist/verification.d.ts +0 -61
  224. package/node_modules/goah-supervisor/dist/verification.d.ts.map +0 -1
  225. package/node_modules/goah-supervisor/dist/verification.js +0 -135
  226. package/node_modules/goah-supervisor/dist/verification.js.map +0 -1
  227. package/node_modules/goah-supervisor/package.json +0 -26
  228. package/node_modules/goah-testkit/dist/faux-runner-worker.d.ts +0 -2
  229. package/node_modules/goah-testkit/dist/faux-runner-worker.d.ts.map +0 -1
  230. package/node_modules/goah-testkit/dist/faux-runner-worker.js +0 -82
  231. package/node_modules/goah-testkit/dist/faux-runner-worker.js.map +0 -1
  232. package/node_modules/goah-testkit/dist/index.d.ts +0 -49
  233. package/node_modules/goah-testkit/dist/index.d.ts.map +0 -1
  234. package/node_modules/goah-testkit/dist/index.js +0 -96
  235. package/node_modules/goah-testkit/dist/index.js.map +0 -1
  236. package/node_modules/goah-testkit/package.json +0 -29
@@ -0,0 +1,1746 @@
1
+ import { createRequire as __goahCreateRequire } from "node:module";
2
+ const require = __goahCreateRequire(import.meta.url);
3
+ import {
4
+ goalStream,
5
+ memoryStream,
6
+ wakeStream
7
+ } from "./chunk-KAO7WIXG.js";
8
+ import {
9
+ assertAgentHandoff,
10
+ assertHandoff,
11
+ assertTurnOutput,
12
+ goalAutomaticTarget,
13
+ goalCommitment,
14
+ goalRoute,
15
+ humanInboxRoute,
16
+ humanRequestRoute,
17
+ noGoalCommitment,
18
+ normalizeAssistantText,
19
+ specialistAutomaticTarget,
20
+ specialistInboxRoute
21
+ } from "./chunk-TJON22J4.js";
22
+
23
+ // node_modules/goah-supervisor/dist/index.js
24
+ import { randomUUID } from "node:crypto";
25
+
26
+ // node_modules/goah-supervisor/dist/context-view.js
27
+ function selectRecoveryEvents(events) {
28
+ const unknownCalls = new Set(events.filter((event) => event.type === "tool.completed" && field(field(event.data, "result"), "outcome") === "unknown").map((event) => String(field(event.data, "callId"))));
29
+ return events.filter((event) => {
30
+ if (["transcript.interrupted", "context.compacted"].includes(event.type))
31
+ return true;
32
+ if (event.type === "tool.called")
33
+ return unknownCalls.has(String(field(event.data, "callId")));
34
+ if (event.type === "tool.completed")
35
+ return unknownCalls.has(String(field(event.data, "callId")));
36
+ return false;
37
+ });
38
+ }
39
+ function selectWorkingMemory(events, charBudget) {
40
+ const notes = events.filter((event) => event.type === "memory.appended");
41
+ const tail = [];
42
+ let used = 0;
43
+ for (let index = notes.length - 1; index >= 0; index -= 1) {
44
+ const event = notes[index];
45
+ const length = String(field(event.data, "note") ?? "").length;
46
+ if (tail.length > 0 && used + length > charBudget)
47
+ break;
48
+ tail.push(event);
49
+ used += length;
50
+ }
51
+ return tail.reverse();
52
+ }
53
+ function composeActiveContext(input) {
54
+ const handoff = input.lastHandoff?.data;
55
+ const sourceSeqs = /* @__PURE__ */ new Set();
56
+ if (input.lastHandoff)
57
+ sourceSeqs.add(input.lastHandoff.seq);
58
+ for (const event of input.teamHandoffs)
59
+ sourceSeqs.add(event.seq);
60
+ for (const event of input.recoveryEvents)
61
+ sourceSeqs.add(event.seq);
62
+ for (const event of input.workingMemory ?? [])
63
+ sourceSeqs.add(event.seq);
64
+ const sections = [
65
+ ["Objectives", input.goals.map((goal) => `- [${goal.id}] ${goal.objective} (owner: ${goal.owner}, phase: ${goal.phase}, revision: ${goal.revision})`)],
66
+ ["Observation methods", input.goals.map((goal) => `## ${goal.id}
67
+
68
+ ${goal.observationMethod ?? "MISSING \u2014 inspect the project and request authoritative confirmation before claiming progress or completion."}`)],
69
+ ["Verification methods", input.goals.map((goal) => `## ${goal.id}
70
+
71
+ ${goal.verificationMethod ?? "MISSING \u2014 define authoritative completion evidence before claiming completion."}`)],
72
+ ["Wake", [...input.wakeTriggers.filter((trigger) => trigger.status === "pending").map((trigger) => `- [${trigger.source}] ${trigger.triggerRef}`), `- Attempt: ${input.wake.attempt}`]],
73
+ ["Working memory", (input.workingMemory ?? []).map((event) => `- ${String(field(event.data, "note") ?? "")} [event:${event.seq}]`)],
74
+ ["Last outcome", typeof handoff?.outcome === "string" ? [`- ${handoff.outcome}${input.lastHandoff ? ` [event:${input.lastHandoff.seq}]` : ""}`] : []],
75
+ ["Incoming", input.mail.map((mail) => `- [${mail.level}] ${mail.id} from ${mail.from}${mail.goalId ? ` for Goal ${mail.goalId}` : ""}: ${render(mail.body, 2e3)}`)],
76
+ ["Team motion", input.team.map((member) => `- ${member.agent}: motion=${member.motion}; outcome=${member.lastOutcome ?? "none"}; goals=${member.goalIds.join(",") || "none"}; next=${member.nextWakeAt ?? "none"}; handoff=${member.lastHandoffSeq ?? "none"}`)],
77
+ ["Team handoffs", input.teamHandoffs.map((event) => `- ${event.actor}: ${render(event.data)} [event:${event.seq}]`)],
78
+ ["Recovery", input.recoveryEvents.map((event) => `- ${event.type}: ${render(event.data)} [event:${event.seq}]`)]
79
+ ];
80
+ const text = sections.filter(([, values]) => values.length > 0).map(([title, values]) => `# ${title}
81
+
82
+ ${values.join("\n")}`).join("\n\n");
83
+ return { role: input.role, capabilities: input.capabilities, systemPrompt: input.systemPrompt, text, sourceSeqs: [...sourceSeqs].sort((a, b) => a - b) };
84
+ }
85
+ function render(value, maxChars = Number.POSITIVE_INFINITY) {
86
+ const text = typeof value === "string" ? value : JSON.stringify(value);
87
+ return text.length <= maxChars ? text : `${text.slice(0, maxChars)}\u2026`;
88
+ }
89
+ function field(value, key) {
90
+ return value && typeof value === "object" && !Array.isArray(value) ? value[key] : void 0;
91
+ }
92
+
93
+ // node_modules/goah-supervisor/dist/roles.js
94
+ var prompts = {
95
+ child: "Own the assigned Child Goal. Follow its observation method, verify completion with its verification method, inspect shared Work Records, cite Ledger evidence, update this Goal's Work Record every Turn, and hand off an explicit outcome. Handoff is declarative: use mail.send to notify or escalate, setting its typed goalId route to the parent Goal when it should wake the parent's next committed Turn; use schedule.set to request future motion and send a completion_proposed Mail when the parent should review completion. You are not a task-only worker and cannot redefine or complete your own Goal.",
96
+ ceo: `You are the user's sole operating interface and the durable CEO identity for this Goal tree. You organize work; you do not impersonate child execution.
97
+
98
+ On the first wake for a root with no observation method, operationalize the goal before claiming measurable progress: inspect the current directory with read/edit/write/bash; read project documentation, configuration, code, scripts, local CLIs, and existing ledger evidence; clarify the objective, constraints, baseline, and meaning of success; identify the data source or qualitative inspection protocol; define freshness, cadence, time zone, sustain window, and missing-data behavior when relevant; list the exact access required; then propose a textual observation method to the human. Ask only for facts or permissions that cannot be discovered locally. Continue safe reversible exploration while waiting. Never invent a baseline, data source, permission, success criterion, or observation result.
99
+
100
+ On every wake: (1) orient from the root and descendants, each current observation method and revision, Team motion, incoming mail, handoffs, blockers, unknown Tool Calls, and recovery facts; (2) diagnose every active child's motion, ownership, and adherence to its authoritative observation method; (3) decide whether to keep, delegate, revise the objective/method pair, reassign, pause, resume, complete, or escalate; (4) apply organization changes only through the high-level atomic tools; (5) repair every idle_unplanned child and every child missing an observation method before handoff; (6) close with active child motion plus a CEO review, an explicit wait/blocker, a human request, or a completion recommendation carrying evidence produced under the current method.
101
+
102
+ Use goal.delegate rather than separate goal/mail/schedule calls. Execute ambiguous or exploratory work yourself until a stream has a bounded objective, independent observation and verification methods, and a reviewable result; only then create a distinct Goal-owning Agent. Use team.list as the roster source of truth. Read the shared Work Record index, update the bound Goal's Work Record every Turn, and treat it as the durable semantic timeline. Handoff is declarative: use mail.send for explicit organization communication, schedule.set for future motion, and human.request when Human authority is required. Never claim authority to confirm Root methods, complete, or materially change a Root Goal: request the Human instead.`,
103
+ verifier: "Verify one Turn's handoff claims against its trace and runner facts. Do not trust self-report. Persist concise findings with exact evidence sequences.",
104
+ audit: "Independently reconstruct outcomes from durable facts and external observations. Persist independent audit judgment with memory_append; it never substitutes for fresh evidence."
105
+ };
106
+ function defaultRolePrompt(role) {
107
+ return prompts[role];
108
+ }
109
+ function defaultTurnPrompt(role, agent, turn) {
110
+ if (role === "ceo") {
111
+ if (agent !== "ceo")
112
+ throw new Error("only the primary Agent may use the CEO role");
113
+ if (turn.goalCommitment)
114
+ return defaultRolePrompt(role);
115
+ return "You are Goah's primary Agent. Respond naturally to the Human and use tools when useful. The active Root Goal, when present, is context rather than an assignment. Do not create or commit to a Goal for routine single-turn work. When the Human expresses durable intent or asks you to advance the active Goal, use the available Goal creation or Goal work tool; only then maintain its Work Record and finish with a Handoff.";
116
+ }
117
+ if (role === "child") {
118
+ if (!turn.goalCommitment)
119
+ throw new Error("Child Agents require a Goal commitment");
120
+ return defaultRolePrompt(role);
121
+ }
122
+ if (turn.goalCommitment)
123
+ throw new Error("Specialist Agents cannot commit to a Goal");
124
+ return `${defaultRolePrompt(role)} You are Goah specialist ${agent}. Inspect the supplied system context and finish with an ordinary response.`;
125
+ }
126
+
127
+ // node_modules/goah-supervisor/dist/verification.js
128
+ import { createHash } from "node:crypto";
129
+ import { spawn } from "node:child_process";
130
+ var ProcessVerifierModel = class {
131
+ spec;
132
+ constructor(spec) {
133
+ this.spec = spec;
134
+ }
135
+ verifyTurn(input) {
136
+ return this.#call("verify_turn", input);
137
+ }
138
+ blindAudit(facts) {
139
+ return this.#call("blind_audit", { facts });
140
+ }
141
+ async #call(operation, input) {
142
+ const env = {};
143
+ for (const name of ["PATH", "TMPDIR", "TMP", "TEMP", "SYSTEMROOT"])
144
+ if (process.env[name] !== void 0)
145
+ env[name] = process.env[name];
146
+ const child = spawn(this.spec.command, this.spec.args, { detached: process.platform !== "win32", env: { ...env, ...this.spec.env }, stdio: ["pipe", "pipe", "pipe"] });
147
+ let stdout = "";
148
+ let stderr = "";
149
+ let timedOut = false;
150
+ let outputOverflow = false;
151
+ const kill = () => {
152
+ if (child.pid) {
153
+ try {
154
+ process.kill(process.platform === "win32" ? child.pid : -child.pid, "SIGKILL");
155
+ } catch {
156
+ }
157
+ }
158
+ };
159
+ const append = (channel, chunk) => {
160
+ const text = chunk.toString();
161
+ const remaining = Math.max(0, 1e6 - stdout.length - stderr.length);
162
+ if (channel === "stdout")
163
+ stdout += text.slice(0, remaining);
164
+ else
165
+ stderr += text.slice(0, remaining);
166
+ if (text.length > remaining && !outputOverflow) {
167
+ outputOverflow = true;
168
+ kill();
169
+ }
170
+ };
171
+ child.stdout.on("data", (chunk) => append("stdout", chunk));
172
+ child.stderr.on("data", (chunk) => append("stderr", chunk));
173
+ child.stdin.end(`${JSON.stringify({ operation, input })}
174
+ `);
175
+ const timer = setTimeout(() => {
176
+ timedOut = true;
177
+ kill();
178
+ }, this.spec.timeoutMs ?? 6e4);
179
+ let code;
180
+ try {
181
+ code = await new Promise((resolve, reject) => {
182
+ child.once("error", reject);
183
+ child.once("close", resolve);
184
+ });
185
+ } finally {
186
+ clearTimeout(timer);
187
+ }
188
+ if (outputOverflow)
189
+ throw new Error("verifier output exceeded 1 MB");
190
+ if (code !== 0)
191
+ throw new Error(timedOut ? "verifier process timed out" : stderr.trim() || `verifier exited ${code}`);
192
+ return JSON.parse(stdout);
193
+ }
194
+ };
195
+ var VerificationPlane = class {
196
+ ledger;
197
+ supervisor;
198
+ model;
199
+ constructor(ledger, supervisor, model) {
200
+ this.ledger = ledger;
201
+ this.supervisor = supervisor;
202
+ this.model = model;
203
+ }
204
+ async verifyTurn(turnId) {
205
+ const turn = this.ledger.turn(turnId);
206
+ if (!turn)
207
+ throw new Error(`Turn not found: ${turnId}`);
208
+ if (turn.status === "in_progress")
209
+ throw new Error("cannot verify an in-progress Turn");
210
+ const trace = this.ledger.readStream(`turn:${turnId}`);
211
+ const handoff = this.ledger.turnItems(turnId).findLast((item) => item.type === "handoff")?.data ?? null;
212
+ const result = await this.model.verifyTurn({ turnId, handoff, trace });
213
+ this.#validate(result);
214
+ const thread = this.ledger.thread(turn.threadId);
215
+ if (!thread)
216
+ throw new Error("verified Turn has no Thread");
217
+ const level = result.findings.length ? "decision" : "fyi";
218
+ const body = { type: "verification_result", turnId, agent: thread.agent, findings: result.findings, tokensUsed: result.tokensUsed };
219
+ let route;
220
+ if (turn.goalId) {
221
+ const goal = this.ledger.goal(turn.goalId);
222
+ if (!goal || goal.owner !== thread.agent)
223
+ throw new Error("verified committed Turn no longer matches its owner");
224
+ route = goalRoute(turn.goalId);
225
+ } else if (thread.role === "ceo") {
226
+ route = humanInboxRoute();
227
+ } else {
228
+ if (thread.role !== "verifier" && thread.role !== "audit")
229
+ throw new Error("verified uncommitted Turn is not a Specialist");
230
+ route = specialistInboxRoute(thread.role);
231
+ }
232
+ const mail = { id: this.#mailId("verification", turnId, thread.agent, result), to: thread.agent, from: "verifier", level, ...route, body, readAt: null };
233
+ this.ledger.putMail(mail, "verifier");
234
+ return result;
235
+ }
236
+ async auditGlobal(sinceSeq = 0) {
237
+ const facts = this.ledger.eventsSince(sinceSeq).filter((event) => !["handoff.recorded", "runner.note"].includes(event.type));
238
+ const result = await this.model.blindAudit(facts);
239
+ this.#validate(result);
240
+ this.ledger.putMail({ id: this.#mailId("audit", String(sinceSeq), "ceo", result), to: "ceo", from: "audit", level: result.findings.length ? "decision" : "fyi", ...humanInboxRoute(), body: { type: "audit_result", sinceSeq, findings: result.findings, tokensUsed: result.tokensUsed }, readAt: null }, "audit");
241
+ return result;
242
+ }
243
+ #validate(result) {
244
+ const evidence = new Set(this.ledger.events().map((event) => event.seq));
245
+ for (const finding of result.findings)
246
+ if (!finding.id.trim() || finding.evidence.length === 0 || finding.evidence.some((seq) => !evidence.has(seq)))
247
+ throw new Error("verification finding requires an id and existing evidence");
248
+ }
249
+ #mailId(kind, source, recipient, result) {
250
+ const digest = createHash("sha256").update(JSON.stringify(result)).digest("hex").slice(0, 16);
251
+ return `${kind}:${source}:${recipient}:${digest}`;
252
+ }
253
+ };
254
+ function evaluateVerification(labels, predictedIds) {
255
+ const predicted = new Set(predictedIds);
256
+ const positives = labels.filter((label) => label.shouldFlag);
257
+ const truePositives = positives.filter((label) => predicted.has(label.id));
258
+ const falsePositives = labels.filter((label) => !label.shouldFlag && predicted.has(label.id));
259
+ const precision = truePositives.length + falsePositives.length === 0 ? 1 : truePositives.length / (truePositives.length + falsePositives.length);
260
+ const totalRisk = positives.reduce((sum, label) => sum + label.riskWeight, 0);
261
+ const recalledRisk = truePositives.reduce((sum, label) => sum + label.riskWeight, 0);
262
+ return { precision, riskWeightedRecall: totalRisk === 0 ? 1 : recalledRisk / totalRisk };
263
+ }
264
+ function calibrateVerificationThreshold(labels, predictions, minimumPrecision) {
265
+ const candidates = [...new Set(predictions.map((prediction) => prediction.score))].sort((a, b) => a - b);
266
+ let selected = 1;
267
+ let bestRecall = -1;
268
+ for (const threshold of candidates) {
269
+ const metrics = evaluateVerification(labels, predictions.filter((prediction) => prediction.score >= threshold).map((prediction) => prediction.id));
270
+ if (metrics.precision >= minimumPrecision && metrics.riskWeightedRecall > bestRecall) {
271
+ selected = threshold;
272
+ bestRecall = metrics.riskWeightedRecall;
273
+ }
274
+ }
275
+ return selected;
276
+ }
277
+
278
+ // node_modules/goah-supervisor/dist/index.js
279
+ var RunnerRouter = class {
280
+ runners;
281
+ fallback;
282
+ isolation = "process";
283
+ #byPid = /* @__PURE__ */ new Map();
284
+ constructor(runners, fallback = "default") {
285
+ this.runners = runners;
286
+ this.fallback = fallback;
287
+ }
288
+ prepare(request) {
289
+ const context = request.context && typeof request.context === "object" && !Array.isArray(request.context) ? request.context : {};
290
+ const profile = context.runnerProfile && typeof context.runnerProfile === "object" && !Array.isArray(context.runnerProfile) ? context.runnerProfile : {};
291
+ const id = typeof profile.id === "string" ? profile.id : this.fallback;
292
+ const runner = this.runners.get(id);
293
+ if (!runner)
294
+ throw new Error(`runner profile is not configured: ${id}`);
295
+ const handle = runner.prepare(request);
296
+ if (handle.pid !== null && Number.isInteger(handle.pid) && handle.pid > 0)
297
+ this.#byPid.set(handle.pid, runner);
298
+ void handle.result.then(() => {
299
+ if (handle.pid !== null && Number.isInteger(handle.pid) && handle.pid > 0)
300
+ this.#byPid.delete(handle.pid);
301
+ }, () => {
302
+ if (handle.pid !== null && Number.isInteger(handle.pid) && handle.pid > 0)
303
+ this.#byPid.delete(handle.pid);
304
+ });
305
+ return handle;
306
+ }
307
+ async terminateProcess(pid, runnerProfileId) {
308
+ const runner = this.#byPid.get(pid) ?? this.runners.get(runnerProfileId ?? this.fallback);
309
+ if (!runner)
310
+ return;
311
+ await runner.terminateProcess(pid);
312
+ }
313
+ };
314
+ var Supervisor = class {
315
+ ledger;
316
+ clock;
317
+ #leaseMs;
318
+ #memoryTailChars;
319
+ #claimTail = Promise.resolve();
320
+ #humanTail = Promise.resolve();
321
+ #retryPolicy;
322
+ #turnRetryPolicy;
323
+ #profiles;
324
+ #runnerProfiles;
325
+ #handles = /* @__PURE__ */ new Map();
326
+ #executions = /* @__PURE__ */ new Map();
327
+ #agentExecutions = /* @__PURE__ */ new Map();
328
+ #goalExecutionBarriers = /* @__PURE__ */ new Map();
329
+ #handoffValidations = /* @__PURE__ */ new Map();
330
+ #handoffAttemptSeq = /* @__PURE__ */ new Map();
331
+ #runner;
332
+ constructor(ledger, runner, clock, options = {}) {
333
+ this.ledger = ledger;
334
+ this.clock = clock;
335
+ this.#runner = runner;
336
+ this.#leaseMs = options.leaseMs ?? 3e4;
337
+ this.#memoryTailChars = options.memoryTailChars ?? 12e3;
338
+ this.#retryPolicy = options.retryPolicy ?? { maxAttempts: 0, baseDelayMs: 1e3 };
339
+ this.#turnRetryPolicy = options.turnRetryPolicy ?? { maxAttempts: 3, baseDelayMs: 1e3 };
340
+ for (const profile of options.profiles ?? []) {
341
+ if (profile.agent === "ceo" && profile.role !== "ceo" || profile.agent !== "ceo" && profile.role === "ceo")
342
+ throw new Error("exactly the ceo Agent must use the ceo role");
343
+ }
344
+ this.#profiles = new Map([["ceo", { agent: "ceo", role: "ceo" }], ...(options.profiles ?? []).map((profile) => [profile.agent, profile])]);
345
+ for (const thread of this.ledger.threads()) {
346
+ const configured = this.#profiles.get(thread.agent)?.role ?? (thread.agent === "ceo" ? "ceo" : "child");
347
+ if (configured !== thread.role)
348
+ throw new Error(`Agent ${thread.agent} role conflicts with persisted Thread role ${thread.role}`);
349
+ }
350
+ for (const goal of this.ledger.goals().filter((candidate) => candidate.phase !== "complete")) {
351
+ if (!this.#validGoalOwner(goal.owner, goal))
352
+ throw new Error(`Agent ${goal.owner} role conflicts with persisted ${goal.parentId === null ? "Root" : "Child"} Goal ${goal.id}`);
353
+ }
354
+ this.#runnerProfiles = new Map((options.runnerProfiles ?? []).map((profile) => [profile.id, profile]));
355
+ }
356
+ /**
357
+ * Hot-swap the runner after a config reload. Refused while a Turn is active:
358
+ * a live child must never observe its runner vanish mid-flight.
359
+ * The next Turn uses the new runner, and spawn-time env
360
+ * resolution applies the new credentials to the next spawn.
361
+ */
362
+ swapRunner(runner, profiles) {
363
+ const active = this.ledger.turns().filter((turn) => turn.status === "in_progress");
364
+ if (active.length > 0)
365
+ throw new Error("cannot swap runner while a Turn is in progress");
366
+ this.#runner = runner;
367
+ if (profiles) {
368
+ this.#runnerProfiles.clear();
369
+ for (const profile of profiles)
370
+ this.#runnerProfiles.set(profile.id, profile);
371
+ }
372
+ }
373
+ get runner() {
374
+ return this.#runner;
375
+ }
376
+ createGoal(goal, actor = "human") {
377
+ if (!this.#validGoalOwner(goal.owner, goal))
378
+ throw new Error("Goal owner role does not match Root/Child position");
379
+ if (goal.parentId === null && this.ledger.goals().some((candidate) => candidate.id !== goal.id && candidate.parentId === null && candidate.phase !== "complete"))
380
+ throw new Error("CEO already has an unfinished Root Goal");
381
+ this.ledger.putGoal(goal, actor);
382
+ }
383
+ createRootGoal(objective, id = randomUUID(), sourceTurnId) {
384
+ if (!objective.trim())
385
+ throw new Error("root objective is required");
386
+ if (this.ledger.goals().some((goal2) => goal2.parentId === null && goal2.owner === "ceo" && goal2.phase !== "complete"))
387
+ throw new Error("CEO already has an unfinished Root Goal; use work_on_goal");
388
+ const goal = { id, parentId: null, objective, observationMethod: null, verificationMethod: null, owner: "ceo", phase: "active", revision: 0 };
389
+ this.ledger.putGoal(goal, "human", void 0, { operation: "create", reason: "Human established a durable Root Goal", evidence: [], authority: { kind: "human" }, ...sourceTurnId ? { sourceTurnId } : {} });
390
+ return this.#goal(id);
391
+ }
392
+ startGoal(objective, id = randomUUID()) {
393
+ const goal = this.createRootGoal(objective, id);
394
+ const wake = this.#enqueueTrigger("ceo", `root:${id}:created`, { goalId: goal.id });
395
+ if (!wake)
396
+ throw new Error("CEO wake was not admitted for an active root goal");
397
+ return { goal, wake };
398
+ }
399
+ threadFor(agent = "ceo") {
400
+ const parentThreadId = agent === "ceo" ? null : this.threadFor("ceo").id;
401
+ const role = this.#role(agent);
402
+ const existing = this.ledger.threads().find((thread2) => thread2.agent === agent && thread2.parentThreadId === parentThreadId);
403
+ if (existing) {
404
+ if (existing.role !== role)
405
+ throw new Error(`Agent ${agent} role changed from ${existing.role} to ${role}`);
406
+ return existing;
407
+ }
408
+ const now = this.#now();
409
+ const thread = { id: randomUUID(), agent, role, parentThreadId, createdAt: now, updatedAt: now };
410
+ this.ledger.putThread(thread, "supervisor");
411
+ return thread;
412
+ }
413
+ async startHumanTurn(message) {
414
+ const previous = this.#humanTail;
415
+ let release;
416
+ this.#humanTail = new Promise((resolve) => {
417
+ release = resolve;
418
+ });
419
+ await previous;
420
+ try {
421
+ return await this.#startHumanTurn(message);
422
+ } finally {
423
+ release();
424
+ }
425
+ }
426
+ async startHumanGoalTurn(objective, id = randomUUID()) {
427
+ if (!objective.trim())
428
+ throw new Error("root objective is required");
429
+ const previous = this.#humanTail;
430
+ let release;
431
+ this.#humanTail = new Promise((resolve) => {
432
+ release = resolve;
433
+ });
434
+ await previous;
435
+ try {
436
+ const goal = { id, parentId: null, objective, observationMethod: null, verificationMethod: null, owner: "ceo", phase: "active", revision: 0 };
437
+ const accepted = await this.#startHumanTurn(`/goal ${objective}`, goal);
438
+ return { ...accepted, steered: false, goal: this.#goal(id) };
439
+ } finally {
440
+ release();
441
+ }
442
+ }
443
+ async #startHumanTurn(message, newRoot = null) {
444
+ if (!message.trim())
445
+ throw new Error("message is required");
446
+ const existingThread = this.ledger.threads().find((candidate) => candidate.agent === "ceo");
447
+ const now = this.#now();
448
+ const thread = existingThread ? { ...existingThread, updatedAt: now } : { id: randomUUID(), agent: "ceo", role: "ceo", parentThreadId: null, createdAt: now, updatedAt: now };
449
+ const active = existingThread ? this.ledger.activeTurn(existingThread.id) : null;
450
+ if (active) {
451
+ if (active.triggerKind === "user_message" && !newRoot) {
452
+ const handle = this.#handles.get(active.id);
453
+ if (handle?.steer) {
454
+ const item = this.#appendTurnItem(active.id, "user_message", { text: message }, "human", randomUUID(), "in_progress");
455
+ try {
456
+ await handle.steer(message);
457
+ const stored = this.ledger.turnItems(active.id).find((candidate) => candidate.id === item.id);
458
+ if (this.ledger.turn(active.id)?.status === "in_progress" && stored?.status === "in_progress") {
459
+ this.ledger.putTurnItem({ ...stored, status: "completed", completedAt: this.#now() }, "human");
460
+ return { threadId: thread.id, turnId: active.id, steered: true };
461
+ }
462
+ } catch {
463
+ const stored = this.ledger.turnItems(active.id).find((candidate) => candidate.id === item.id);
464
+ if (this.ledger.turn(active.id)?.status === "in_progress" && stored?.status === "in_progress")
465
+ this.ledger.putTurnItem({ ...stored, status: "failed", completedAt: this.#now() }, "human");
466
+ }
467
+ } else if (!handle) {
468
+ this.#appendTurnItem(active.id, "user_message", { text: message }, "human");
469
+ return { threadId: thread.id, turnId: active.id, steered: true };
470
+ }
471
+ }
472
+ }
473
+ const replacement = this.ledger.activeTurn(thread.id);
474
+ const turnStartedAt = this.#now();
475
+ const turn = { id: randomUUID(), threadId: thread.id, triggerKind: "user_message", ...newRoot ? goalCommitment(newRoot.id, newRoot.revision) : noGoalCommitment(), status: "in_progress", attempt: 1, error: null, startedAt: turnStartedAt, endedAt: null, leaseUntil: new Date(this.clock.now().getTime() + this.#leaseMs).toISOString(), leaseToken: randomUUID(), runnerPid: null, runnerProfileId: this.#runnerProfileId("ceo") };
476
+ const messageItem = { id: randomUUID(), turnId: turn.id, ordinal: 1, type: "user_message", status: "completed", data: { text: message }, createdAt: turnStartedAt, completedAt: turnStartedAt };
477
+ const admitted = this.ledger.admitHumanTurn({ thread: { ...thread, updatedAt: turnStartedAt }, turn, messageItem, replaceTurnId: replacement?.id ?? null, ...newRoot ? { rootGoal: newRoot } : {} });
478
+ const interruptedGoalId = replacement?.triggerKind === "wake" ? replacement.goalId : null;
479
+ if (interruptedGoalId) {
480
+ const goal = this.ledger.goal(interruptedGoalId);
481
+ if (goal?.phase === "active")
482
+ this.#enqueueTrigger(goal.owner, `human-interrupted:${replacement.id}`, { goalId: goal.id });
483
+ }
484
+ const context = { trigger: { kind: "user_message" }, activeGoal: newRoot ?? this.currentRoot(), goalCommitment: newRoot ? { goalId: newRoot.id, goalRevision: newRoot.revision } : null };
485
+ const deliveredMail = this.#contextMail("ceo", newRoot?.id ?? null);
486
+ const recordRevisionAtStart = newRoot ? this.ledger.workRecord(newRoot.id)?.recordRevision ?? -1 : -1;
487
+ await this.#activateAdmittedHumanTurn(admitted.turn, admitted.replacedTurn, context, deliveredMail, recordRevisionAtStart);
488
+ return { threadId: thread.id, turnId: turn.id, steered: false };
489
+ }
490
+ async interruptTurn(turnId) {
491
+ return this.#interruptTurn(turnId, "interrupted by Human", "human");
492
+ }
493
+ async #interruptTurn(turnId, reason, actor) {
494
+ const turn = this.ledger.turn(turnId);
495
+ if (!turn || turn.status !== "in_progress")
496
+ throw new Error("active Turn not found");
497
+ this.#clearHandoffState(turn.id);
498
+ this.ledger.finishTurn(turn.id, "interrupted", { message: reason }, this.#now(), actor);
499
+ await this.#cleanupTerminalTurn(turn);
500
+ return this.ledger.turn(turn.id);
501
+ }
502
+ async #executeTurn(initial, agent, turnContext, contextFactory, sourceWake = null, deliveredMailIds = [], recordRevisionAtStart = -1, sourceWakeTriggers = []) {
503
+ while (this.ledger.turn(initial.id)?.status === "in_progress") {
504
+ const execution = this.ledger.turn(initial.id);
505
+ const leaseToken = execution.leaseToken;
506
+ let handle = null;
507
+ let renewal = null;
508
+ let processClean = true;
509
+ try {
510
+ handle = this.runner.prepare({ agent, execution, ...sourceWake ? { sourceWake, sourceWakeTriggers } : {}, turn: turnContext, context: contextFactory(), now: () => this.#now(), emit: (trace) => this.#recordTurnTrace(initial.id, leaseToken, trace.type, trace.data, agent), rpc: (method, params) => this.#agentRpcForTurn(initial.id, agent, turnContext, method, params, sourceWake?.id) });
511
+ this.#handles.set(initial.id, handle);
512
+ if (handle.pid)
513
+ this.ledger.attachTurnProcess(initial.id, leaseToken, handle.pid);
514
+ renewal = setInterval(() => {
515
+ try {
516
+ this.ledger.renewTurnLease(initial.id, leaseToken, new Date(this.clock.now().getTime() + this.#leaseMs).toISOString(), this.#now());
517
+ } catch {
518
+ void this.#terminateHandle(initial.id, handle);
519
+ }
520
+ }, Math.max(25, Math.floor(this.#leaseMs / 3)));
521
+ renewal.unref();
522
+ handle.begin();
523
+ const result = await handle.result;
524
+ if (renewal)
525
+ clearInterval(renewal);
526
+ renewal = null;
527
+ processClean = await this.#terminateHandle(initial.id, handle);
528
+ this.#handles.delete(initial.id);
529
+ if (!processClean)
530
+ throw new Error("Runner process cleanup did not complete");
531
+ const attached = this.ledger.turn(initial.id);
532
+ if (attached?.status === "in_progress" && attached.runnerPid !== null)
533
+ this.ledger.releaseTurnProcess(initial.id, "supervisor");
534
+ const current = this.ledger.turn(initial.id);
535
+ if (!current || current.status !== "in_progress")
536
+ return;
537
+ if (current.attempt > 1)
538
+ this.ledger.appendEvent({ streamId: `turn:${current.id}`, ts: this.#now(), actor: "supervisor", type: "turn.retry_finished", data: { attempt: current.attempt, outcome: result.outcome }, ignorable: true });
539
+ if (result.outcome !== "abnormal")
540
+ this.#closeStreamingItems(current.id);
541
+ if (result.outcome === "abnormal") {
542
+ if (current.attempt < this.#turnRetryPolicy.maxAttempts) {
543
+ this.ledger.repairTurnAttempt(current.id, result.reason, this.#now(), "supervisor");
544
+ this.ledger.appendEvent({ streamId: `turn:${current.id}`, ts: this.#now(), actor: "supervisor", type: "turn.retry_started", data: { attempt: current.attempt + 1, reason: result.reason }, ignorable: true });
545
+ this.ledger.putTurn({ ...current, attempt: current.attempt + 1, leaseUntil: new Date(this.clock.now().getTime() + this.#leaseMs).toISOString(), runnerPid: null }, "supervisor");
546
+ await new Promise((resolve) => setTimeout(resolve, this.#turnRetryPolicy.baseDelayMs * 2 ** (current.attempt - 1)));
547
+ continue;
548
+ }
549
+ this.#failTurn(current.id, result.reason);
550
+ this.#scheduleTurnRecovery(sourceWake, sourceWakeTriggers, current.id, agent);
551
+ return;
552
+ }
553
+ const response = normalizeAssistantText(result.response.content);
554
+ if (!response)
555
+ throw new Error("completed Turn requires a readable assistant response");
556
+ if (turnContext.goalCommitment) {
557
+ if (!result.handoff)
558
+ throw new Error("committed Turn requires Handoff");
559
+ this.#commitTurnGoalWork(current.id, agent, turnContext, response, result.handoff, sourceWake?.id ?? null, deliveredMailIds, recordRevisionAtStart);
560
+ return;
561
+ }
562
+ if (result.handoff)
563
+ throw new Error("uncommitted Turn cannot finish with Handoff");
564
+ const latestMessage = this.ledger.turnItems(current.id).findLast((item) => item.type === "assistant_message" && item.status === "completed");
565
+ if (latestMessage) {
566
+ const traced = normalizeAssistantText(String(latestMessage.data.text ?? ""));
567
+ if (traced !== response)
568
+ throw new Error("completed Turn response does not match its latest assistant trace");
569
+ if (this.#assistantCommitState(current.id, traced) !== "committed")
570
+ throw new Error("uncommitted Turn requires a committed assistant trace");
571
+ } else
572
+ this.#appendTurnItem(current.id, "assistant_message", { text: response }, agent);
573
+ this.ledger.finishTurn(current.id, "completed", null, this.#now(), "supervisor", deliveredMailIds);
574
+ return;
575
+ } catch (error) {
576
+ if (renewal)
577
+ clearInterval(renewal);
578
+ if (handle && processClean)
579
+ processClean = await this.#terminateHandle(initial.id, handle);
580
+ this.#handles.delete(initial.id);
581
+ let current = this.ledger.turn(initial.id);
582
+ if (processClean && current?.status === "in_progress" && current.runnerPid !== null) {
583
+ this.ledger.releaseTurnProcess(initial.id, "supervisor");
584
+ current = this.ledger.turn(initial.id);
585
+ }
586
+ if (current?.status === "in_progress") {
587
+ this.#failTurn(current.id, error instanceof Error ? error.message : String(error));
588
+ this.#scheduleTurnRecovery(sourceWake, sourceWakeTriggers, current.id, agent);
589
+ }
590
+ return;
591
+ }
592
+ }
593
+ }
594
+ #trackExecution(initial, agent, turnContext, contextFactory, sourceWake = null, deliveredMailIds = [], recordRevisionAtStart = -1, sourceWakeTriggers = []) {
595
+ const running = this.#executeTurn(initial, agent, turnContext, contextFactory, sourceWake, deliveredMailIds, recordRevisionAtStart, sourceWakeTriggers);
596
+ this.#executions.set(initial.id, running);
597
+ this.#agentExecutions.set(agent, running);
598
+ void running.finally(() => {
599
+ if (this.#executions.get(initial.id) === running)
600
+ this.#executions.delete(initial.id);
601
+ if (this.#agentExecutions.get(agent) === running)
602
+ this.#agentExecutions.delete(agent);
603
+ });
604
+ return running;
605
+ }
606
+ async #activateAdmittedHumanTurn(turn, replaced, context, mail, recordRevisionAtStart) {
607
+ if (replaced) {
608
+ this.#clearHandoffState(replaced.id);
609
+ if (!await this.#cleanupTerminalTurn(replaced)) {
610
+ this.#failTurn(turn.id, "previous Runner cleanup did not complete");
611
+ this.#scheduleTurnRecovery(null, [], turn.id, "ceo");
612
+ return;
613
+ }
614
+ } else
615
+ await this.#awaitAgentExecution("ceo");
616
+ for (const fence of this.ledger.turns(turn.threadId).filter((candidate) => candidate.status !== "in_progress" && candidate.runnerPid !== null)) {
617
+ if (!await this.#cleanupTerminalTurn(fence)) {
618
+ this.#failTurn(turn.id, "previous Runner cleanup did not complete");
619
+ this.#scheduleTurnRecovery(null, [], turn.id, "ceo");
620
+ return;
621
+ }
622
+ }
623
+ const current = this.ledger.turn(turn.id);
624
+ if (current?.status !== "in_progress")
625
+ return;
626
+ const activated = { ...current, leaseUntil: new Date(this.clock.now().getTime() + this.#leaseMs).toISOString() };
627
+ this.ledger.putTurn(activated, "supervisor");
628
+ this.#trackExecution(activated, "ceo", context, () => this.#humanContext(turn.id, "ceo", mail), null, mail.map((item) => item.id), recordRevisionAtStart);
629
+ }
630
+ async #cleanupTerminalTurn(turn) {
631
+ const handle = this.#handles.get(turn.id);
632
+ let cleaned = true;
633
+ try {
634
+ if (handle)
635
+ cleaned = await this.#terminateHandle(turn.id, handle);
636
+ else if (turn.runnerPid)
637
+ await this.runner.terminateProcess(turn.runnerPid, turn.runnerProfileId);
638
+ } catch (error) {
639
+ this.#recordCleanupFailure(turn.id, error);
640
+ cleaned = false;
641
+ } finally {
642
+ this.#handles.delete(turn.id);
643
+ }
644
+ if (!cleaned)
645
+ return false;
646
+ await this.#executions.get(turn.id);
647
+ const stored = this.ledger.turn(turn.id);
648
+ if (stored && stored.status !== "in_progress" && stored.runnerPid !== null) {
649
+ try {
650
+ this.ledger.releaseTurnProcess(turn.id, "supervisor");
651
+ } catch (error) {
652
+ this.#recordCleanupFailure(turn.id, error);
653
+ return false;
654
+ }
655
+ }
656
+ return true;
657
+ }
658
+ async #awaitAgentExecution(agent) {
659
+ const running = this.#agentExecutions.get(agent);
660
+ if (running)
661
+ await running;
662
+ }
663
+ #humanContext(turnId, agent, mail) {
664
+ const turn = this.ledger.turn(turnId);
665
+ const current = this.#turnHistory(turn.id);
666
+ const turnSourceSeqs = this.ledger.readStream(`turn:${turn.id}`).filter((event) => event.type === "item.user_message.started").map((event) => event.seq);
667
+ if (turn.goalId !== null && turn.goalRevision !== null) {
668
+ const goal = this.#goal(turn.goalId);
669
+ const context2 = { trigger: { kind: "user_message" }, activeGoal: goal, goalCommitment: { goalId: turn.goalId, goalRevision: turn.goalRevision } };
670
+ const base = this.#loadContext({ ...goalAutomaticTarget(agent, turn.goalId), attempt: turn.attempt }, context2, mail, []);
671
+ const sourceSeqs2 = Array.isArray(base.sourceSeqs) ? base.sourceSeqs.filter((value) => typeof value === "number") : [];
672
+ return { ...base, text: `${String(base.text ?? "")}
673
+
674
+ # Current Turn
675
+
676
+ ${current}`, sourceSeqs: [.../* @__PURE__ */ new Set([...sourceSeqs2, ...turnSourceSeqs])].sort((a, b) => a - b) };
677
+ }
678
+ const profile = this.#profiles.get(agent) ?? { agent, role: "ceo" };
679
+ const runnerProfile = this.#runnerProfiles.get(profile.runnerProfile ?? "default");
680
+ const recent = this.ledger.turns(turn.threadId).filter((candidate) => candidate.id !== turn.id && candidate.status === "completed").slice(-8).flatMap((candidate) => this.ledger.turnItems(candidate.id).filter((item) => item.type === "user_message" || item.type === "assistant_message").map((item) => `${item.type === "user_message" ? "Human" : "Assistant"}: ${String(item.data.text ?? "")}`));
681
+ const sourceSeqs = [...turnSourceSeqs, ...this.#mailSourceSeqs(mail)];
682
+ const incoming = mail.map((item) => `- [${item.level}] ${item.id} from ${item.from}: ${boundedJson(item.body)}`);
683
+ const activeGoal = this.currentRoot();
684
+ const context = { trigger: { kind: "user_message" }, activeGoal, goalCommitment: null };
685
+ const goalText = activeGoal ? [`# Active Goal context
686
+
687
+ [${activeGoal.id}] ${activeGoal.objective} (phase: ${activeGoal.phase}, revision: ${activeGoal.revision}). This is visible context, not a commitment to advance it.`] : [];
688
+ return { text: [...recent.length ? [`# Recent conversation
689
+
690
+ ${recent.join("\n")}`] : [], ...goalText, ...incoming.length ? [`# Incoming
691
+
692
+ ${incoming.join("\n")}`] : [], `# Current Turn
693
+
694
+ ${current}`].join("\n\n"), sourceSeqs, activeGoal, capabilities: profile.capabilities ?? defaultCapabilities(profile.role), systemPrompt: profile.systemPrompt ?? defaultTurnPrompt(profile.role, agent, context), ...runnerProfile ? { runnerProfile } : {} };
695
+ }
696
+ #goalContext(wake, turn, turnId, mail, wakeTriggers) {
697
+ const base = this.#loadContext(wake, turn, mail, wakeTriggers);
698
+ if (!base || typeof base !== "object" || Array.isArray(base))
699
+ return base;
700
+ const value = base;
701
+ const history = this.#turnHistory(turnId);
702
+ return { ...value, ...history ? { text: `${String(value.text ?? "")}
703
+
704
+ # Current Turn retry history
705
+
706
+ ${history}` } : {} };
707
+ }
708
+ #threadAgent(threadId) {
709
+ const thread = this.ledger.thread(threadId);
710
+ if (!thread)
711
+ throw new Error("Turn Thread not found");
712
+ return thread.agent;
713
+ }
714
+ #turnHistory(turnId) {
715
+ const items = this.ledger.turnItems(turnId).map((item) => {
716
+ const data = item.data;
717
+ if (item.type === "user_message")
718
+ return `Human: ${String(data.text ?? "")}`;
719
+ if (item.type === "assistant_message")
720
+ return `Assistant: ${String(data.text ?? "")}`;
721
+ if (item.type === "tool_call")
722
+ return `Tool call: ${String(data.tool ?? "")} ${JSON.stringify(item.data)}`;
723
+ if (item.type === "tool_result")
724
+ return `Tool result: ${JSON.stringify(data.result ?? item.data)}`;
725
+ return `${item.type}: ${JSON.stringify(item.data)}`;
726
+ });
727
+ const facts = this.ledger.readStream(`turn:${turnId}`).filter((event) => event.type === "turn.retry_started").map((event) => `${event.type}: ${JSON.stringify(event.data)}`);
728
+ return [...items, ...facts].join("\n");
729
+ }
730
+ #assistantCommitState(turnId, text) {
731
+ const canonical = normalizeAssistantText(text);
732
+ const event = this.ledger.readStream(`turn:${turnId}`).findLast((candidate) => {
733
+ if (candidate.type !== "message.assistant.completed" || !candidate.data || typeof candidate.data !== "object" || Array.isArray(candidate.data))
734
+ return false;
735
+ const message = candidate.data.message;
736
+ return messageTextContent(message?.content) === canonical;
737
+ });
738
+ if (!event || !event.data || typeof event.data !== "object" || Array.isArray(event.data))
739
+ return null;
740
+ const state = event.data.commitState;
741
+ return state === "committed" || state === "provisional" ? state : null;
742
+ }
743
+ #failTurn(turnId, reason) {
744
+ const current = this.ledger.turn(turnId);
745
+ if (!current || current.status !== "in_progress")
746
+ return;
747
+ this.#clearHandoffState(turnId);
748
+ this.ledger.finishTurn(turnId, "failed", { message: reason }, this.#now(), "supervisor");
749
+ }
750
+ #preemptGoalTurn(goalId, reason) {
751
+ const turn = this.ledger.turns().find((candidate) => candidate.status === "in_progress" && candidate.goalId === goalId);
752
+ if (!turn)
753
+ return;
754
+ this.#clearHandoffState(turn.id);
755
+ this.ledger.finishTurn(turn.id, "interrupted", { message: reason }, this.#now(), "supervisor");
756
+ void this.#cleanupTerminalTurn(turn);
757
+ }
758
+ async #terminateHandle(turnId, handle) {
759
+ try {
760
+ await handle.terminate();
761
+ return true;
762
+ } catch (error) {
763
+ this.#recordCleanupFailure(turnId, error);
764
+ const turn = this.ledger.turn(turnId);
765
+ const persistedPid = turn?.runnerPid;
766
+ if (persistedPid === null || persistedPid === void 0)
767
+ return handle.pid === null;
768
+ try {
769
+ await this.runner.terminateProcess(persistedPid, turn?.runnerProfileId);
770
+ return true;
771
+ } catch (fallback) {
772
+ this.#recordCleanupFailure(turnId, fallback);
773
+ return false;
774
+ }
775
+ }
776
+ }
777
+ #recordCleanupFailure(turnId, error) {
778
+ this.ledger.appendEvent({ streamId: `turn:${turnId}`, ts: this.#now(), actor: "supervisor", type: "runner.cleanup_failed", data: { message: error instanceof Error ? error.message : String(error) }, ignorable: true });
779
+ }
780
+ #scheduleTurnRecovery(sourceWake, triggers, turnId, agent) {
781
+ const turn = this.ledger.turn(turnId);
782
+ if (!turn)
783
+ return;
784
+ const role = this.#role(agent);
785
+ const goal = turn.goalId ? this.ledger.goal(turn.goalId) : null;
786
+ if (turn.goalId && (!goal || goal.phase !== "active" || goal.owner !== agent) || !turn.goalId && (turn.triggerKind !== "wake" || role !== "verifier" && role !== "audit"))
787
+ return;
788
+ const prior = Math.max(0, ...triggers.map((trigger) => parseRecoveryTrigger(trigger.triggerRef)?.attempt ?? 0));
789
+ const next = prior + 1;
790
+ if (next < this.#retryPolicy.maxAttempts) {
791
+ const delay = this.#retryPolicy.baseDelayMs * 2 ** prior;
792
+ const target = goal ? goalAutomaticTarget(agent, goal.id) : specialistAutomaticTarget(agent, role);
793
+ this.ledger.putSchedule({ id: recoveryScheduleId(turnId, next), ...target, nextWakeAt: new Date(this.clock.now().getTime() + delay).toISOString(), reason: recoveryRef(turnId), setBy: "supervisor", status: "pending", resolvedAt: null }, "supervisor", sourceWake?.id);
794
+ } else if (role === "child" && goal?.parentId) {
795
+ const parent = this.ledger.goal(goal.parentId);
796
+ if (parent?.phase === "active")
797
+ this.#enqueueTrigger(parent.owner, childRetryExhaustedRef(turnId), { goalId: parent.id });
798
+ }
799
+ }
800
+ #closeStreamingItems(turnId) {
801
+ const open = this.ledger.turnItems(turnId).filter((item) => item.status === "in_progress");
802
+ if (open.some((item) => item.type === "tool_call" || item.type === "user_message"))
803
+ throw new Error("Runner returned while an input or tool call was still open");
804
+ for (const item of open)
805
+ this.ledger.putTurnItem({ ...item, status: "completed", completedAt: this.#now() }, "supervisor");
806
+ }
807
+ #appendTurnItem(turnId, type, data, actor, id = randomUUID(), status = "completed") {
808
+ const now = this.#now();
809
+ const item = { id, turnId, ordinal: this.ledger.turnItems(turnId).length + 1, type, status, data, createdAt: now, completedAt: status === "in_progress" ? null : now };
810
+ this.ledger.putTurnItem(item, actor);
811
+ return item;
812
+ }
813
+ #recordTurnTrace(turnId, leaseToken, type, data, actor = "ceo") {
814
+ if (type === "transcript.completed" || type === "transcript.interrupted")
815
+ return;
816
+ if (type === "transcript.started" && this.ledger.readStream(`turn:${turnId}`).some((event) => event.type === "transcript.started"))
817
+ return;
818
+ if (type === "message.assistant.completed") {
819
+ const value = data && typeof data === "object" && !Array.isArray(data) ? data : {};
820
+ if (!["committed", "provisional"].includes(String(value.commitState)))
821
+ throw new Error("Runner assistant completion is missing normalized commit state");
822
+ if (value.commitState === "provisional" && this.ledger.turn(turnId)?.goalId === null)
823
+ throw new Error("uncommitted Turn cannot emit a provisional assistant response");
824
+ }
825
+ this.ledger.appendTurnEvent({ streamId: `turn:${turnId}`, ts: this.#now(), actor, type, data }, leaseToken);
826
+ if (type === "message.assistant.completed") {
827
+ const value = data;
828
+ const text = messageTextContent(value.message?.content);
829
+ if (text)
830
+ this.#appendTurnItem(turnId, "assistant_message", { text }, actor);
831
+ } else if (type === "plan.updated")
832
+ this.#appendTurnItem(turnId, "plan", data, actor);
833
+ else if (type === "message.assistant.delta") {
834
+ const input = data;
835
+ const delta = input.delta;
836
+ if (delta?.type === "thinking_start" || delta?.type === "thinking_delta" || delta?.type === "thinking_end") {
837
+ const turn = this.ledger.turn(turnId);
838
+ const id = `${turnId}:attempt:${turn.attempt}:reasoning:${String(input.messageId ?? "message")}`;
839
+ const existing = this.ledger.turnItems(turnId).find((item) => item.id === id);
840
+ const text = `${String(existing?.data?.text ?? "")}${delta.type === "thinking_delta" ? String(delta.delta ?? "") : ""}`;
841
+ if (!existing)
842
+ this.#appendTurnItem(turnId, "reasoning", { text }, actor, id, delta.type === "thinking_end" ? "completed" : "in_progress");
843
+ else
844
+ this.ledger.putTurnItem({ ...existing, data: { text }, status: delta.type === "thinking_end" ? "completed" : "in_progress", completedAt: delta.type === "thinking_end" ? this.#now() : null }, actor);
845
+ }
846
+ } else if (type === "tool.called") {
847
+ const input = data;
848
+ const turn = this.ledger.turn(turnId);
849
+ const id = `${turnId}:attempt:${turn.attempt}:tool:${String(input.callId)}`;
850
+ if (this.ledger.turnItems(turnId).some((item) => item.id === id))
851
+ throw new Error("duplicate tool call id in Turn attempt");
852
+ this.#appendTurnItem(turnId, "tool_call", { callId: String(input.callId), tool: String(input.name), arguments: input.arguments ?? null }, actor, id, "in_progress");
853
+ } else if (type === "tool.completed") {
854
+ const input = data;
855
+ const turn = this.ledger.turn(turnId);
856
+ const id = `${turnId}:attempt:${turn.attempt}:tool:${String(input.callId)}`;
857
+ const existing = this.ledger.turnItems(turnId).find((item) => item.id === id);
858
+ if (!existing)
859
+ throw new Error("tool result has no matching call in Turn attempt");
860
+ this.ledger.putTurnItem({ ...existing, status: input.isError ? "failed" : "completed", completedAt: this.#now() }, actor);
861
+ this.#appendTurnItem(turnId, "tool_result", { callId: String(input.callId), result: input.result ?? null }, actor);
862
+ }
863
+ }
864
+ async sendToCeo(body) {
865
+ const value = body && typeof body === "object" && !Array.isArray(body) ? body : {};
866
+ const message = String(value.message ?? "").trim();
867
+ if (!message)
868
+ throw new Error("CEO message is required");
869
+ const accepted = await this.startHumanTurn(message);
870
+ await this.waitForTurn(accepted.turnId);
871
+ return accepted;
872
+ }
873
+ async waitForTurn(turnId) {
874
+ await this.#executions.get(turnId);
875
+ }
876
+ delegate(request, actor = "ceo", wakeId) {
877
+ const candidate = { ...request.childGoal, parentId: request.parentGoalId, phase: "active", revision: 0 };
878
+ if (!this.#validGoalOwner(candidate.owner, candidate))
879
+ throw new Error("Child Goal owner must use a Child Agent profile");
880
+ return this.ledger.commitDelegation(request, actor, wakeId);
881
+ }
882
+ async reassignGoal(request, actor = "ceo", wakeId) {
883
+ const goal = this.#goal(request.goalId);
884
+ if (!this.#validGoalOwner(request.newOwner, { ...goal, owner: request.newOwner }))
885
+ throw new Error("Child Goal owner must use a Child Agent profile");
886
+ const thread = this.ledger.threads().find((candidate) => candidate.agent === goal.owner);
887
+ const active = thread ? this.ledger.activeTurn(thread.id) : null;
888
+ const gate = active ? Promise.withResolvers() : null;
889
+ if (gate)
890
+ this.#goalExecutionBarriers.set(goal.id, gate.promise);
891
+ try {
892
+ const result = this.ledger.commitReassignment(request, actor, wakeId);
893
+ if (active?.goalId === goal.id && this.ledger.turn(active.id)?.status === "in_progress")
894
+ await this.#interruptTurn(active.id, "Goal reassigned to another Agent", "supervisor");
895
+ return result;
896
+ } finally {
897
+ gate?.resolve();
898
+ if (gate && this.#goalExecutionBarriers.get(goal.id) === gate.promise)
899
+ this.#goalExecutionBarriers.delete(goal.id);
900
+ }
901
+ }
902
+ teamList(now = this.#now()) {
903
+ return deriveTeam(this.ledger, now);
904
+ }
905
+ currentRoot() {
906
+ return this.ledger.goals().find((goal) => goal.parentId === null && goal.owner === "ceo" && goal.phase !== "complete") ?? null;
907
+ }
908
+ agentRole(agent) {
909
+ return this.#role(agent);
910
+ }
911
+ updateGoal(id, patch, actor = "human", change) {
912
+ if (patch.objective === void 0 && patch.observationMethod === void 0 && patch.verificationMethod === void 0)
913
+ throw new Error("goal update requires objective, observation method, or verification method");
914
+ const current = this.#goal(id);
915
+ this.#assertGoalMutationAuthority(current, actor);
916
+ if (patch.objective !== void 0 && patch.objective !== current.objective && current.parentId !== null && (patch.observationMethod === void 0 || patch.verificationMethod === void 0))
917
+ throw new Error("child objective revision requires replacement observation and verification methods");
918
+ const next = {
919
+ ...current,
920
+ ...patch,
921
+ ...patch.objective !== void 0 && patch.objective !== current.objective && current.parentId === null && patch.observationMethod === void 0 ? { observationMethod: null } : {},
922
+ ...patch.objective !== void 0 && patch.objective !== current.objective && current.parentId === null && patch.verificationMethod === void 0 ? { verificationMethod: null } : {},
923
+ revision: current.revision + 1
924
+ };
925
+ this.ledger.putGoal(next, actor, change?.sourceWakeId, { operation: "revise", reason: change?.reason ?? "Goal definition revised", evidence: change?.evidence ?? [], ...change?.sourceTurnId ? { sourceTurnId: change.sourceTurnId } : {}, ...change?.sourceWakeId ? { sourceWakeId: change.sourceWakeId } : {} });
926
+ this.#preemptGoalTurn(current.id, "Goal definition changed");
927
+ if (next.parentId === null && next.owner === "ceo" && actor === "human")
928
+ this.#enqueueTrigger("ceo", `root:${id}:revised:${next.revision}`, { goalId: next.id });
929
+ return next;
930
+ }
931
+ confirmObservationMethod(id, observationMethod) {
932
+ const current = this.#goal(id);
933
+ if (current.parentId !== null)
934
+ throw new Error("human confirmation applies only to a root goal");
935
+ return this.updateGoal(id, { observationMethod, verificationMethod: observationMethod }, "human", { reason: "Human confirmed the Root observation and verification method", evidence: [] });
936
+ }
937
+ reviseChildGoal(id, objective, observationMethod, verificationMethod, actor, reason, evidence, wakeId, sourceTurnId) {
938
+ const current = this.#goal(id);
939
+ if (current.parentId === null)
940
+ throw new Error("CEO cannot revise a root goal");
941
+ if (!reason.trim())
942
+ throw new Error("goal revision reason is required");
943
+ for (const seq of evidence)
944
+ if (!this.ledger.eventsSince(seq - 1).some((event) => event.seq === seq))
945
+ throw new Error(`evidence event does not exist: ${seq}`);
946
+ this.ledger.appendEvent({ streamId: wakeId ? wakeStream(wakeId) : goalStream(id), ts: this.#now(), actor, type: "goal.revision_requested", data: { goalId: id, fromRevision: current.revision, objective, observationMethod, verificationMethod, reason, evidence } });
947
+ return this.updateGoal(id, { objective, observationMethod, verificationMethod }, actor, { reason, evidence, ...wakeId ? { sourceWakeId: wakeId } : {}, ...sourceTurnId ? { sourceTurnId } : {} });
948
+ }
949
+ completeGoal(request, actor = "human", wakeId) {
950
+ const goal = this.ledger.completeGoal(request, actor, wakeId);
951
+ this.#preemptGoalTurn(goal.id, "Goal completed");
952
+ return goal;
953
+ }
954
+ transitionGoal(id, phase, actor = "human", scheduleMotion = true, sourceTurnId) {
955
+ const current = this.#goal(id);
956
+ this.#assertGoalMutationAuthority(current, actor);
957
+ if (current.phase === phase)
958
+ return current;
959
+ if (phase === "complete")
960
+ throw new Error("goal completion requires reason and evidence");
961
+ const next = { ...current, phase, revision: current.revision + 1 };
962
+ const operation = phase === "paused" ? "pause" : phase === "blocked" ? "block" : "resume";
963
+ this.ledger.putGoal(next, actor, void 0, { operation, reason: `Goal ${operation} requested by ${actor}`, evidence: [], ...sourceTurnId ? { sourceTurnId } : {} });
964
+ this.#preemptGoalTurn(current.id, `Goal ${operation}`);
965
+ if (phase === "active" && scheduleMotion)
966
+ this.#enqueueTrigger(next.owner, `${next.parentId ? "goal" : "root"}:${id}:resumed:${next.revision}`, { goalId: next.id });
967
+ return next;
968
+ }
969
+ planWake(agent, at, reason, setBy = agent, target) {
970
+ const parsed = Date.parse(at);
971
+ if (!Number.isFinite(parsed))
972
+ throw new Error("schedule time is invalid");
973
+ const nextWakeAt = new Date(parsed).toISOString();
974
+ const binding = target ?? this.#singleActiveGoalTarget(agent);
975
+ const role = this.#role(agent);
976
+ if (!binding && role !== "verifier" && role !== "audit")
977
+ throw new Error("Goal-owning Agent schedules require an active Goal target");
978
+ if (binding) {
979
+ const goal = this.ledger.goal(binding.goalId);
980
+ if (!goal || goal.phase !== "active" || !this.#validGoalOwner(agent, goal))
981
+ throw new Error("schedule target is not an active Goal owned by this Agent");
982
+ }
983
+ const executionTarget = binding ? goalAutomaticTarget(agent, binding.goalId) : specialistAutomaticTarget(agent, role);
984
+ const schedule = { id: `schedule:${agent}${binding ? `:${binding.goalId}` : ""}:${randomUUID()}`, ...executionTarget, nextWakeAt, reason, setBy, status: "pending", resolvedAt: null };
985
+ this.ledger.putSchedule(schedule, setBy);
986
+ return nextWakeAt <= this.#now() ? this.#enqueueSchedule(schedule) : null;
987
+ }
988
+ async stopAgentWake(agent, goalId) {
989
+ const role = this.#role(agent);
990
+ if (goalId) {
991
+ const goal = this.#goal(goalId);
992
+ if (!this.#validGoalOwner(agent, goal))
993
+ throw new Error("Goal stop target is not owned by the Agent");
994
+ }
995
+ const target = role === "verifier" || role === "audit" ? null : goalId ? { goalId } : this.#singleActiveGoalTarget(agent);
996
+ if (role !== "verifier" && role !== "audit" && !target)
997
+ throw new Error("Goal stop requires an explicit Goal target");
998
+ const wake = this.ledger.wakes().find((item) => item.agent === agent && (item.status === "queued" || item.status === "claimed") && (target ? item.targetKind === "goal" && item.goalId === target.goalId : item.targetKind === "specialist"));
999
+ if (wake)
1000
+ this.ledger.cancelWake(wake.id, this.#now());
1001
+ const thread = this.ledger.threads().find((item) => item.agent === agent);
1002
+ const turn = thread ? this.ledger.activeTurn(thread.id) : null;
1003
+ if (turn && (target ? turn.goalId === target.goalId : turn.goalId === null && turn.triggerKind === "wake"))
1004
+ await this.interruptTurn(turn.id);
1005
+ return wake ? this.#wake(wake.id) : null;
1006
+ }
1007
+ async recover() {
1008
+ for (const wake of this.ledger.wakes().filter((candidate) => candidate.status === "claimed"))
1009
+ this.ledger.releaseWake(wake.id, this.#now());
1010
+ for (const turn of this.ledger.turns().filter((candidate) => candidate.status !== "in_progress" && candidate.runnerPid !== null)) {
1011
+ await this.runner.terminateProcess(turn.runnerPid, turn.runnerProfileId);
1012
+ this.ledger.releaseTurnProcess(turn.id, "supervisor");
1013
+ }
1014
+ for (const turn of this.ledger.turns().filter((candidate) => candidate.status === "in_progress" && !this.#handles.has(candidate.id))) {
1015
+ if (turn.runnerPid) {
1016
+ await this.runner.terminateProcess(turn.runnerPid, turn.runnerProfileId);
1017
+ this.ledger.releaseTurnProcess(turn.id, "supervisor");
1018
+ }
1019
+ this.#failTurn(turn.id, "orphaned Runner ownership recovered after Supervisor restart");
1020
+ const thread = this.ledger.thread(turn.threadId);
1021
+ if (!thread)
1022
+ continue;
1023
+ if (turn.goalId) {
1024
+ const goal = this.ledger.goal(turn.goalId);
1025
+ if (goal?.phase === "active" && goal.owner === thread.agent)
1026
+ this.#enqueueTrigger(thread.agent, recoveryRef(turn.id), { goalId: goal.id });
1027
+ } else if (turn.triggerKind === "wake" && (thread.role === "verifier" || thread.role === "audit"))
1028
+ this.#enqueueTrigger(thread.agent, recoveryRef(turn.id));
1029
+ }
1030
+ }
1031
+ async tick() {
1032
+ const wake = await this.#claimNextWake();
1033
+ if (!wake)
1034
+ return null;
1035
+ let createdTurnId = null;
1036
+ try {
1037
+ await this.#awaitAgentExecution(wake.agent);
1038
+ let currentWake = this.#wake(wake.id);
1039
+ if (currentWake.targetKind === "goal")
1040
+ await this.#goalExecutionBarriers.get(currentWake.goalId);
1041
+ currentWake = this.#wake(wake.id);
1042
+ if (currentWake.status !== "claimed")
1043
+ return currentWake;
1044
+ if (currentWake.targetKind === "goal") {
1045
+ const goal = this.ledger.goal(currentWake.goalId);
1046
+ if (!goal || goal.owner !== currentWake.agent || goal.phase !== "active" || !this.#validGoalOwner(currentWake.agent, goal)) {
1047
+ this.ledger.cancelWake(currentWake.id, this.#now());
1048
+ return this.#wake(currentWake.id);
1049
+ }
1050
+ }
1051
+ const wakeTriggers = this.ledger.wakeTriggers(currentWake.id).filter((trigger) => trigger.status === "pending");
1052
+ const turnContext = this.#turnContext(currentWake, wakeTriggers);
1053
+ if (!this.#validExecution(currentWake.agent, turnContext)) {
1054
+ this.ledger.cancelWake(currentWake.id, this.#now());
1055
+ return this.#wake(currentWake.id);
1056
+ }
1057
+ const thread = this.threadFor(currentWake.agent);
1058
+ const now = this.#now();
1059
+ const leaseToken = randomUUID();
1060
+ const commitment = turnContext.goalCommitment ?? noGoalCommitment();
1061
+ const execution = { id: randomUUID(), threadId: thread.id, triggerKind: "wake", ...commitment, status: "in_progress", attempt: 1, error: null, startedAt: now, endedAt: null, leaseUntil: new Date(this.clock.now().getTime() + this.#leaseMs).toISOString(), leaseToken, runnerPid: null, runnerProfileId: this.#runnerProfileId(currentWake.agent) };
1062
+ this.ledger.putThread({ ...thread, updatedAt: this.#now() }, "supervisor");
1063
+ this.ledger.startTurnFromWake(currentWake.id, execution, now);
1064
+ createdTurnId = execution.id;
1065
+ const deliveredMail = this.#contextMail(currentWake.agent, currentWake.targetKind === "goal" ? currentWake.goalId : null);
1066
+ const deliveredMailIds = deliveredMail.map((mail) => mail.id);
1067
+ this.ledger.appendEvent({ streamId: `turn:${execution.id}`, ts: now, actor: "supervisor", type: "run.admitted", data: { ...turnContext, wakeTriggers }, ignorable: true });
1068
+ const revision = turnContext.goalCommitment ? this.ledger.workRecord(turnContext.goalCommitment.goalId)?.recordRevision ?? -1 : -1;
1069
+ await this.#trackExecution(execution, currentWake.agent, turnContext, () => this.#goalContext(currentWake, turnContext, execution.id, deliveredMail, wakeTriggers), currentWake, deliveredMailIds, revision, wakeTriggers);
1070
+ return this.#wake(wake.id);
1071
+ } catch (error) {
1072
+ if (createdTurnId && this.ledger.turn(createdTurnId)?.status === "in_progress")
1073
+ this.#failTurn(createdTurnId, error instanceof Error ? error.message : String(error));
1074
+ const current = this.ledger.wake(wake.id);
1075
+ if (current?.status === "claimed")
1076
+ this.ledger.releaseWake(wake.id, this.#now());
1077
+ return this.#wake(wake.id);
1078
+ }
1079
+ }
1080
+ async #claimNextWake() {
1081
+ const previous = this.#claimTail;
1082
+ let release;
1083
+ this.#claimTail = new Promise((resolve) => {
1084
+ release = resolve;
1085
+ });
1086
+ await previous;
1087
+ try {
1088
+ for (const schedule of this.ledger.dueSchedules(this.#now()))
1089
+ this.#enqueueSchedule(schedule);
1090
+ for (const mail of this.ledger.triggeringMail()) {
1091
+ const thread = this.ledger.threads().find((candidate) => candidate.agent === mail.to);
1092
+ if (thread && this.ledger.activeTurn(thread.id))
1093
+ continue;
1094
+ const goal = mail.routeKind === "goal" ? this.ledger.goal(mail.goalId) : null;
1095
+ const target = goal && goal.owner === mail.to && goal.phase === "active" && this.#validGoalOwner(mail.to, goal) ? { goalId: goal.id } : void 0;
1096
+ const specialistInteraction = mail.routeKind === "specialist_inbox" && this.#role(mail.to) === mail.specialistRole;
1097
+ if (!target && !specialistInteraction)
1098
+ continue;
1099
+ const base = `mail:${mail.id}`;
1100
+ const related = this.ledger.wakeTriggersForAgent(mail.to).map((trigger2) => ({ trigger: trigger2, attempt: mailDeliveryAttempt(trigger2.triggerRef, base) })).filter((entry) => entry.attempt !== null);
1101
+ const pending = related.filter((entry) => entry.trigger.status === "pending").sort((a, b) => b.attempt - a.attempt)[0];
1102
+ const next = related.reduce((highest, entry) => Math.max(highest, entry.attempt), -1) + 1;
1103
+ const trigger = pending?.trigger.triggerRef ?? (next === 0 ? base : `${base}@redelivery:${next}`);
1104
+ this.#enqueueTrigger(mail.to, trigger, target);
1105
+ }
1106
+ return this.ledger.claimNextWake(this.#now());
1107
+ } finally {
1108
+ release();
1109
+ }
1110
+ }
1111
+ async runAvailable(concurrency = 4, maxWakes = 100) {
1112
+ const completed = [];
1113
+ while (true) {
1114
+ const batch = await Promise.all(Array.from({ length: concurrency }, () => this.tick()));
1115
+ const wakes = batch.filter((wake) => wake !== null);
1116
+ completed.push(...wakes);
1117
+ if (wakes.length === 0 || completed.length >= maxWakes)
1118
+ return completed;
1119
+ }
1120
+ }
1121
+ #enqueueSchedule(schedule) {
1122
+ if (schedule.status !== "pending")
1123
+ return null;
1124
+ if (schedule.targetKind === "goal") {
1125
+ const goal = this.ledger.goal(schedule.goalId);
1126
+ if (!goal || goal.owner !== schedule.agent || goal.phase !== "active" || !this.#validGoalOwner(schedule.agent, goal)) {
1127
+ this.ledger.supersedeSchedule(schedule.id, this.#now());
1128
+ return null;
1129
+ }
1130
+ } else if (!["verifier", "audit"].includes(this.#role(schedule.agent))) {
1131
+ this.ledger.cancelSchedule(schedule.id, this.#now());
1132
+ return null;
1133
+ }
1134
+ const wake = { id: `wake:${schedule.id}`, ...schedule.targetKind === "goal" ? goalAutomaticTarget(schedule.agent, schedule.goalId) : specialistAutomaticTarget(schedule.agent, schedule.specialistRole), triggerRef: `${schedule.id}@${schedule.nextWakeAt}`, status: "queued", attempt: 0, enqueuedSeq: 0, claimedAt: null, consumedAt: null, turnId: null };
1135
+ return this.ledger.consumeSchedule(schedule.id, wake, this.#now()).wake;
1136
+ }
1137
+ #enqueueTrigger(agent, triggerRef, target) {
1138
+ let binding;
1139
+ if (target) {
1140
+ const goal = this.ledger.goal(target.goalId);
1141
+ if (!goal || goal.owner !== agent || goal.phase !== "active" || !this.#validGoalOwner(agent, goal))
1142
+ return null;
1143
+ binding = goalAutomaticTarget(agent, target.goalId);
1144
+ } else {
1145
+ const role = this.#role(agent);
1146
+ if (role === "verifier" || role === "audit")
1147
+ binding = specialistAutomaticTarget(agent, role);
1148
+ else
1149
+ return null;
1150
+ }
1151
+ const sameBinding = (wake2) => wake2.targetKind === binding.targetKind && wake2.goalId === binding.goalId && wake2.specialistRole === binding.specialistRole;
1152
+ const exact = this.ledger.wakeByTrigger(agent, triggerRef);
1153
+ if (exact) {
1154
+ if (!sameBinding(exact))
1155
+ throw new Error("Wake trigger was reused with a different automatic target");
1156
+ return exact;
1157
+ }
1158
+ const pending = this.ledger.wakes().find((wake2) => wake2.agent === agent && wake2.status === "claimed" && sameBinding(wake2)) ?? this.ledger.wakes().find((wake2) => wake2.agent === agent && wake2.status === "queued" && sameBinding(wake2));
1159
+ if (pending) {
1160
+ this.ledger.addWakeTrigger(pending.id, triggerRef, "supervisor");
1161
+ return pending;
1162
+ }
1163
+ const wake = { id: randomUUID(), ...binding, triggerRef, status: "queued", attempt: 0, enqueuedSeq: 0, claimedAt: null, consumedAt: null, turnId: null };
1164
+ const result = this.ledger.enqueueWake(wake, "supervisor");
1165
+ if (result.created)
1166
+ return this.#wake(wake.id);
1167
+ const existing = this.ledger.wakeByTrigger(agent, triggerRef);
1168
+ if (!existing)
1169
+ throw new Error("deduplicated wake is missing");
1170
+ return existing;
1171
+ }
1172
+ #singleActiveGoalTarget(agent) {
1173
+ const goals = this.ledger.goalsForOwner(agent).filter((goal) => goal.phase === "active" && this.#validGoalOwner(agent, goal));
1174
+ if (goals.length > 1)
1175
+ throw new Error("Wake requires an explicit Goal target when an Agent owns multiple active Goals");
1176
+ return goals.length === 1 ? { goalId: goals[0].id } : void 0;
1177
+ }
1178
+ #knownAgent(agent) {
1179
+ return this.#profiles.has(agent) || this.ledger.threads().some((thread) => thread.agent === agent) || this.ledger.goals().some((goal) => goal.owner === agent);
1180
+ }
1181
+ #role(agent) {
1182
+ return this.ledger.threads().find((thread) => thread.agent === agent)?.role ?? this.#profiles.get(agent)?.role ?? (agent === "ceo" ? "ceo" : "child");
1183
+ }
1184
+ #validGoalOwner(agent, goal) {
1185
+ const role = this.#role(agent);
1186
+ return goal.owner === agent && (role === "ceo" ? agent === "ceo" && goal.parentId === null : role === "child" && goal.parentId !== null);
1187
+ }
1188
+ #validExecution(agent, turn) {
1189
+ const role = this.#role(agent);
1190
+ if (turn.goalCommitment) {
1191
+ const goal = this.ledger.goal(turn.goalCommitment.goalId);
1192
+ return Boolean(goal && this.#validGoalOwner(agent, goal) && (role === "ceo" || role === "child"));
1193
+ }
1194
+ if (turn.trigger.kind === "user_message")
1195
+ return agent === "ceo" && role === "ceo";
1196
+ return role === "verifier" || role === "audit";
1197
+ }
1198
+ #commitTurnGoalWork(turnId, agent, turn, response, raw, sourceWakeId, mailIds, revisionAtStart) {
1199
+ const binding = turn.goalCommitment;
1200
+ const goal = this.#goal(binding.goalId);
1201
+ if (goal.revision !== binding.goalRevision)
1202
+ throw new Error("Goal revision changed during the Turn");
1203
+ const record = this.ledger.workRecord(goal.id);
1204
+ if (!record || record.recordRevision <= revisionAtStart || record.updatedInTurn !== turnId || record.goalRevision !== goal.revision)
1205
+ throw new Error("committed Turn must update its Work Record before handoff");
1206
+ assertTurnOutput(raw);
1207
+ const validation = this.#handoffValidations.get(raw.validationToken);
1208
+ const execution = this.ledger.turn(turnId);
1209
+ if (!validation || !execution || validation.turnId !== turnId || validation.attemptId !== raw.validationAttemptId || this.#handoffAttemptSeq.get(turnId) !== raw.validationAttemptId || validation.agent !== agent || validation.attempt !== execution.attempt || validation.leaseToken !== execution.leaseToken || validation.goalId !== goal.id || validation.goalRevision !== goal.revision || validation.message !== response || validation.handoff.outcome !== raw.handoff.outcome || !isSameNumbers(validation.handoff.evidence, raw.handoff.evidence))
1210
+ throw new Error("Handoff validation token is stale or does not match this Turn result");
1211
+ const responseItem = [...this.ledger.turnItems(turnId)].reverse().find((item2) => item2.type === "assistant_message" && item2.status === "completed" && item2.data.text === validation.message);
1212
+ if (!responseItem)
1213
+ throw new Error("accepted Handoff response was not recorded in the Turn");
1214
+ const output = this.#committedTurnOutput(raw, binding);
1215
+ assertHandoff(output.handoff);
1216
+ const now = this.#now();
1217
+ const item = { id: randomUUID(), turnId, ordinal: this.ledger.turnItems(turnId).length + 1, type: "handoff", status: "completed", data: output.handoff, createdAt: now, completedAt: now };
1218
+ this.ledger.commitHandoff({ agent, turnId, sourceWakeId, mailIds, ts: now, output, responseItemId: responseItem.id, item });
1219
+ this.#clearHandoffState(turnId);
1220
+ }
1221
+ #committedTurnOutput(output, binding) {
1222
+ const record = this.ledger.workRecord(binding.goalId);
1223
+ if (!record)
1224
+ throw new Error("Goal Work Record is missing");
1225
+ const handoff = {
1226
+ goalId: binding.goalId,
1227
+ goalRevision: binding.goalRevision,
1228
+ recordRevision: record.recordRevision,
1229
+ outcome: output.handoff.outcome,
1230
+ evidence: output.handoff.evidence
1231
+ };
1232
+ return { handoff };
1233
+ }
1234
+ #turnContext(wake, triggers = this.ledger.wakeTriggers(wake.id).filter((trigger) => trigger.status === "pending")) {
1235
+ const trigger = { kind: "wake", reasons: triggers.map((item) => item.triggerRef) };
1236
+ if (wake.targetKind === "specialist")
1237
+ return { trigger, activeGoal: null, goalCommitment: null };
1238
+ const goal = this.#goal(wake.goalId);
1239
+ return { trigger, activeGoal: goal, goalCommitment: { goalId: goal.id, goalRevision: goal.revision } };
1240
+ }
1241
+ #loadContext(wake, turn, mail, wakeTriggers) {
1242
+ const profile = this.#profiles.get(wake.agent) ?? { agent: wake.agent, role: "child" };
1243
+ const role = profile.role;
1244
+ const capabilities = profile.capabilities ?? defaultCapabilities(role);
1245
+ const runnerProfile = this.#runnerProfiles.get(profile.runnerProfile ?? "default");
1246
+ const goals = role === "ceo" ? this.ledger.goals() : this.ledger.goalsForOwner(wake.agent);
1247
+ const handoff = turn.goalCommitment ? this.ledger.lastGoalHandoff(turn.goalCommitment.goalId) : null;
1248
+ const recoveryIds = [...new Set(wakeTriggers.flatMap((trigger) => {
1249
+ const parsed = parseRecoveryTrigger(trigger.triggerRef);
1250
+ const exhausted = childRetryExhaustedTurnId(trigger.triggerRef);
1251
+ return parsed ? [parsed.turnId] : exhausted ? [exhausted] : [];
1252
+ }))];
1253
+ const recoveryEvents = recoveryIds.flatMap((recoveryId) => selectRecoveryEvents(this.ledger.turn(recoveryId) ? this.ledger.readStream(`turn:${recoveryId}`) : this.ledger.eventsForWake(recoveryId)));
1254
+ const teamHandoffs = role === "ceo" ? [...this.ledger.eventsSince(0, ["handoff.recorded"])].reverse().filter((event, index, all) => all.findIndex((candidate) => candidate.actor === event.actor) === index) : [];
1255
+ const workingMemory = selectWorkingMemory(this.ledger.readStream(memoryStream(wake.agent)), this.#memoryTailChars);
1256
+ const active = composeActiveContext({ role, capabilities, systemPrompt: profile.systemPrompt ?? defaultTurnPrompt(role, wake.agent, turn), wake, wakeTriggers, goals, mail, lastHandoff: handoff, teamHandoffs, team: role === "ceo" ? this.teamList() : [], recoveryEvents, workingMemory });
1257
+ const records = this.ledger.workRecords();
1258
+ const currentRecord = turn.goalCommitment ? this.ledger.workRecord(turn.goalCommitment.goalId) : null;
1259
+ const currentGoal = turn.goalCommitment ? this.ledger.goal(turn.goalCommitment.goalId) : null;
1260
+ const parentRecord = currentGoal?.parentId ? this.ledger.workRecord(currentGoal.parentId) : null;
1261
+ const recordIndex = records.map((record) => `- /goals/${record.goalId}.md \xB7 r${record.recordRevision} \xB7 ${this.ledger.goal(record.goalId)?.owner ?? "unknown"} \xB7 ${this.ledger.goal(record.goalId)?.phase ?? "unknown"}`);
1262
+ const workText = [`# Shared Work Record Index
1263
+
1264
+ ${recordIndex.join("\n")}`, ...currentRecord ? [`# Your Work Record
1265
+
1266
+ ${currentRecord.content}`] : [], ...parentRecord ? [`# Parent Work Record
1267
+
1268
+ ${parentRecord.content}`] : []].join("\n\n");
1269
+ return { ...active, text: `${active.text}
1270
+
1271
+ ${workText}`, activeGoal: turn.activeGoal, goalCommitment: turn.goalCommitment, sourceSeqs: [.../* @__PURE__ */ new Set([...active.sourceSeqs, ...this.#mailSourceSeqs(mail), ...records.map((record) => record.lastEventSeq)])].sort((a, b) => a - b), workRecord: currentRecord, sharedWorkRecords: records, ...runnerProfile ? { runnerProfile } : {} };
1272
+ }
1273
+ #wake(id) {
1274
+ const value = this.ledger.wake(id);
1275
+ if (!value)
1276
+ throw new Error(`wake not found: ${id}`);
1277
+ return value;
1278
+ }
1279
+ #goal(id) {
1280
+ const value = this.ledger.goal(id);
1281
+ if (!value)
1282
+ throw new Error(`goal not found: ${id}`);
1283
+ return value;
1284
+ }
1285
+ #assertGoalMutationAuthority(goal, actor) {
1286
+ if (goal.parentId === null) {
1287
+ if (actor !== "human")
1288
+ throw new Error("only human may modify a root goal");
1289
+ return;
1290
+ }
1291
+ const parent = this.ledger.goal(goal.parentId);
1292
+ if (parent?.owner !== actor)
1293
+ throw new Error("only the parent goal owner may modify a child goal");
1294
+ }
1295
+ #now() {
1296
+ return this.clock.now().toISOString();
1297
+ }
1298
+ #futureTime(value, after) {
1299
+ const parsed = Date.parse(value);
1300
+ if (!Number.isFinite(parsed) || parsed <= Date.parse(after))
1301
+ throw new Error("nextWakeAt must be later than the Turn start");
1302
+ return new Date(parsed).toISOString();
1303
+ }
1304
+ #runnerProfileId(agent) {
1305
+ return this.#profiles.get(agent)?.runnerProfile ?? "default";
1306
+ }
1307
+ #contextMail(agent, goalId) {
1308
+ const selected = [];
1309
+ let used = 0;
1310
+ const role = this.#role(agent);
1311
+ const matches = (mail) => goalId ? mail.routeKind === "goal" && mail.goalId === goalId : role === "ceo" ? mail.routeKind === "human_inbox" : mail.routeKind === "specialist_inbox" && mail.specialistRole === role;
1312
+ for (const mail of this.ledger.unreadMail(agent).filter(matches)) {
1313
+ const cost = Math.min(JSON.stringify(mail.body).length, 2e3) + 128;
1314
+ if (selected.length >= 20 || selected.length > 0 && used + cost > this.#memoryTailChars)
1315
+ break;
1316
+ selected.push(mail);
1317
+ used += cost;
1318
+ }
1319
+ return selected;
1320
+ }
1321
+ #mailSourceSeqs(mail) {
1322
+ const ids = new Set(mail.map((item) => item.id));
1323
+ if (!ids.size)
1324
+ return [];
1325
+ return this.ledger.eventsSince(0, ["mail.put"]).filter((event) => {
1326
+ const data = event.data && typeof event.data === "object" && !Array.isArray(event.data) ? event.data : {};
1327
+ return typeof data.snapshot?.id === "string" && ids.has(data.snapshot.id);
1328
+ }).map((event) => event.seq);
1329
+ }
1330
+ async #agentRpcForTurn(turnId, agent, context, method, params, sourceWakeId) {
1331
+ const handoffAttemptId = method === "goal.handoff.validate" ? this.#beginHandoffAttempt(turnId) : null;
1332
+ const execution = this.ledger.turn(turnId);
1333
+ if (!execution || execution.status !== "in_progress" || !execution.leaseToken || !execution.leaseUntil || execution.leaseUntil < this.#now())
1334
+ throw new Error("stale Turn RPC rejected");
1335
+ if (context.goalCommitment) {
1336
+ const goal = this.ledger.goal(context.goalCommitment.goalId);
1337
+ const thread = this.ledger.thread(execution.threadId);
1338
+ if (!goal || goal.phase !== "active" || goal.revision !== context.goalCommitment.goalRevision || goal.owner !== agent || execution.goalId !== goal.id || execution.goalRevision !== goal.revision || thread?.agent !== agent)
1339
+ throw new Error("stale committed Turn RPC rejected");
1340
+ }
1341
+ const input = asRecord(params);
1342
+ if (method === "goal.handoff.validate") {
1343
+ const candidate = String(input.candidateMessage ?? "");
1344
+ this.ledger.appendEvent({ streamId: `turn:${turnId}`, ts: this.#now(), actor: agent, type: "rpc.goal.handoff.validate", data: { attemptId: handoffAttemptId, handoff: input.handoff ?? null, candidateMessagePresent: Boolean(candidate.trim()), candidateMessageChars: candidate.length }, ignorable: true });
1345
+ return this.#validateHandoffDraft(turnId, handoffAttemptId, agent, execution, context, input);
1346
+ }
1347
+ const profile = this.#profiles.get(agent) ?? { agent, role: "child" };
1348
+ const allowed = new Set(profile.capabilities ?? defaultCapabilities(profile.role));
1349
+ if (!allowed.has(method))
1350
+ throw new Error(`${profile.role} agent is not allowed to call ${method}`);
1351
+ if (!context.goalCommitment && goalBoundCapability(method))
1352
+ throw new Error(`${method} requires a Goal commitment`);
1353
+ this.ledger.appendEvent({ streamId: `turn:${turnId}`, ts: this.#now(), actor: agent, type: `rpc.${method}`, data: params, ignorable: true });
1354
+ if (method === "ledger.search")
1355
+ return this.ledger.searchEvents(String(input.query), Number(input.limit ?? 20));
1356
+ if (method === "team.list")
1357
+ return this.teamList();
1358
+ if (method === "goal.get") {
1359
+ const visibleId = context.goalCommitment?.goalId ?? context.activeGoal?.id;
1360
+ return visibleId ? this.ledger.goal(visibleId) : null;
1361
+ }
1362
+ if (method === "goal.create") {
1363
+ if (context.trigger.kind !== "user_message" || context.goalCommitment || agent !== "ceo")
1364
+ throw new Error("Root Goal creation requires an uncommitted direct CEO Turn");
1365
+ const goal = this.createRootGoal(String(input.objective), typeof input.id === "string" ? input.id : void 0, turnId);
1366
+ context.activeGoal = goal;
1367
+ context.goalCommitment = { goalId: goal.id, goalRevision: goal.revision };
1368
+ this.ledger.commitTurnToGoal(turnId, context.goalCommitment, "supervisor");
1369
+ return { goal, goalCommitment: context.goalCommitment };
1370
+ }
1371
+ if (method === "goal.work") {
1372
+ if (context.trigger.kind !== "user_message" || context.goalCommitment)
1373
+ throw new Error("work_on_goal requires an uncommitted direct CEO Turn");
1374
+ const goal = this.#goal(String(input.goalId));
1375
+ if (goal.phase !== "active" || !this.#validGoalOwner(agent, goal))
1376
+ throw new Error("work_on_goal requires the active owned Root Goal");
1377
+ context.activeGoal = goal;
1378
+ context.goalCommitment = { goalId: goal.id, goalRevision: goal.revision };
1379
+ this.ledger.commitTurnToGoal(turnId, context.goalCommitment, "supervisor");
1380
+ return { goal, goalCommitment: context.goalCommitment };
1381
+ }
1382
+ if (method === "work_record.list")
1383
+ return this.ledger.workRecords();
1384
+ if (method === "work_record.read")
1385
+ return this.ledger.workRecord(String(input.goalId ?? context.goalCommitment?.goalId ?? context.activeGoal?.id ?? ""));
1386
+ if (method === "work_record.history")
1387
+ return this.ledger.workRecordHistory(String(input.goalId ?? context.goalCommitment?.goalId ?? context.activeGoal?.id ?? ""));
1388
+ if (method === "work_record.diff")
1389
+ return this.ledger.workRecordDiff(String(input.goalId ?? context.goalCommitment?.goalId ?? context.activeGoal?.id ?? ""), Number(input.fromRevision), Number(input.toRevision));
1390
+ if (method === "work_record.search")
1391
+ return this.ledger.searchWorkRecords(String(input.query), Number(input.limit ?? 20));
1392
+ if (method === "work_record.update") {
1393
+ const binding = context.goalCommitment;
1394
+ return this.ledger.updateWorkRecord({ goalId: binding.goalId, goalRevision: binding.goalRevision, expectedRevision: Number(input.expectedRevision), content: String(input.content), reason: String(input.reason), evidence: numberArray(input.evidence), turnId, ...sourceWakeId ? { sourceWakeId } : {} }, agent);
1395
+ }
1396
+ if (method === "goal.delegate") {
1397
+ const binding = context.goalCommitment;
1398
+ if (String(input.parentGoalId) !== binding.goalId)
1399
+ throw new Error("delegation parent must be the Goal committed to this Turn");
1400
+ return this.delegate({ id: String(input.id), parentGoalId: binding.goalId, expectedParentRevision: Number(input.expectedParentRevision), childGoal: asChildGoal(input.childGoal), brief: input.brief ?? null, reason: String(input.reason), evidence: numberArray(input.evidence), sourceTurnId: turnId }, agent, sourceWakeId);
1401
+ }
1402
+ if (method === "goal.reassign") {
1403
+ const goal = this.#goal(String(input.goalId));
1404
+ if (goal.parentId !== context.goalCommitment.goalId)
1405
+ throw new Error("reassignment target must be a child of the Goal committed to this Turn");
1406
+ return await this.reassignGoal({ id: String(input.id), goalId: goal.id, expectedGoalRevision: Number(input.expectedGoalRevision), newOwner: String(input.newOwner), brief: input.brief ?? null, reason: String(input.reason), evidence: numberArray(input.evidence), sourceTurnId: turnId }, agent, sourceWakeId);
1407
+ }
1408
+ if (method === "goal.revise")
1409
+ return this.reviseChildGoal(String(input.goalId), String(input.objective), String(input.observationMethod), String(input.verificationMethod), agent, String(input.reason), numberArray(input.evidence), sourceWakeId, turnId);
1410
+ if (method === "goal.pause" || method === "goal.resume") {
1411
+ const goal = this.#goal(String(input.goalId));
1412
+ const directRoot = !context.goalCommitment && context.trigger.kind === "user_message" && goal.parentId === null;
1413
+ if (!context.goalCommitment && !directRoot)
1414
+ throw new Error(`${method} requires a Goal commitment`);
1415
+ const next = this.transitionGoal(goal.id, method === "goal.pause" ? "paused" : "active", directRoot ? "human" : agent, !directRoot, turnId);
1416
+ if (method === "goal.resume" && directRoot) {
1417
+ context.activeGoal = next;
1418
+ context.goalCommitment = { goalId: next.id, goalRevision: next.revision };
1419
+ this.ledger.commitTurnToGoal(turnId, context.goalCommitment, "supervisor");
1420
+ return { goal: next, goalCommitment: context.goalCommitment };
1421
+ }
1422
+ return next;
1423
+ }
1424
+ if (method === "goal.complete") {
1425
+ const goal = this.#goal(String(input.goalId));
1426
+ const directRoot = !context.goalCommitment && context.trigger.kind === "user_message" && goal.parentId === null;
1427
+ if (!context.goalCommitment && !directRoot)
1428
+ throw new Error("goal.complete requires a Goal commitment or direct Human Root authority");
1429
+ return this.completeGoal({ goalId: goal.id, revision: Number(input.revision), reason: String(input.reason), evidence: numberArray(input.evidence), sourceTurnId: turnId }, directRoot ? "human" : agent, sourceWakeId);
1430
+ }
1431
+ if (method === "mail.send") {
1432
+ const to = String(input.to);
1433
+ if (to === "human")
1434
+ throw new Error("Human communication requires human.request");
1435
+ if (!this.#knownAgent(to))
1436
+ throw new Error(`unknown Agent recipient: ${to}`);
1437
+ const goalId = String(input.goalId ?? "").trim();
1438
+ if (!goalId)
1439
+ throw new Error("Agent Mail requires a Goal route");
1440
+ const goal = this.#goal(goalId);
1441
+ if (!this.#validGoalOwner(to, goal))
1442
+ throw new Error("Agent Mail Goal route does not match the recipient role and ownership");
1443
+ const mail = { id: randomUUID(), to, from: agent, level: String(input.level), ...goalRoute(goalId), body: input.body ?? null, readAt: null };
1444
+ this.ledger.putMail(mail, agent, sourceWakeId);
1445
+ return mail;
1446
+ }
1447
+ if (method === "human.request") {
1448
+ if (agent !== "ceo")
1449
+ throw new Error("only CEO may request Human input");
1450
+ const evidence = numberArray(input.evidence);
1451
+ if (!evidence.length)
1452
+ throw new Error("evidence is required");
1453
+ for (const seq of evidence)
1454
+ if (!this.ledger.eventsSince(seq - 1).some((event) => event.seq === seq))
1455
+ throw new Error(`evidence event does not exist: ${seq}`);
1456
+ const mail = { id: randomUUID(), to: "human", from: agent, level: "decision", ...humanRequestRoute(), body: { type: String(input.type), message: input.message ?? null, evidence }, readAt: null };
1457
+ this.ledger.putMail(mail, agent, sourceWakeId);
1458
+ return mail;
1459
+ }
1460
+ if (method === "schedule.set")
1461
+ return this.planWake(agent, String(input.at), String(input.reason), agent, context.goalCommitment ?? void 0) ?? { scheduled: true };
1462
+ if (method === "goal.put") {
1463
+ const next = input.goal;
1464
+ if (!this.#validGoalOwner(next.owner, next))
1465
+ throw new Error("Goal owner role does not match Root/Child position");
1466
+ const current = this.ledger.goal(next.id);
1467
+ const operation = !current ? "create" : current.phase !== next.phase ? next.phase === "paused" ? "pause" : next.phase === "active" ? "resume" : next.phase === "blocked" ? "block" : "complete" : current.owner !== next.owner ? "reassign" : "revise";
1468
+ this.ledger.putGoal(next, agent, sourceWakeId, { operation, reason: String(input.reason ?? "Advanced Goal mutation"), evidence: numberArray(input.evidence ?? []), sourceTurnId: turnId, ...sourceWakeId ? { sourceWakeId } : {} });
1469
+ return input.goal;
1470
+ }
1471
+ if (method === "memory.append") {
1472
+ const note = String(input.note ?? "").trim();
1473
+ if (!note)
1474
+ throw new Error("memory note cannot be empty");
1475
+ const event = this.ledger.appendEvent({ streamId: memoryStream(agent), ts: this.#now(), actor: agent, type: "memory.appended", data: { note, turnId } });
1476
+ return { seq: event.seq };
1477
+ }
1478
+ throw new Error(`unsupported Agent capability: ${method}`);
1479
+ }
1480
+ #validateHandoffDraft(turnId, attemptId, agent, execution, context, input) {
1481
+ if (!context.goalCommitment || execution.goalId === null)
1482
+ return { accepted: false, fatal: true, attemptId, issues: [{ code: "turn_not_committed", message: "This Turn no longer has a Goal commitment." }] };
1483
+ const request = { handoff: input.handoff ?? null, candidateMessage: String(input.candidateMessage ?? "") };
1484
+ const issues = [];
1485
+ try {
1486
+ assertAgentHandoff(request.handoff);
1487
+ } catch {
1488
+ issues.push({ code: "handoff_invalid", message: "Handoff requires a valid outcome and at least one evidence event." });
1489
+ }
1490
+ const existingMessage = [...this.ledger.turnItems(turnId)].reverse().find((item) => item.type === "assistant_message" && item.status === "completed" && typeof item.data.text === "string" && Boolean(item.data.text.trim()));
1491
+ const message = normalizeAssistantText(request.candidateMessage) || normalizeAssistantText(String(existingMessage?.data?.text ?? ""));
1492
+ if (!message)
1493
+ issues.push({ code: "message_missing", message: "This committed Turn needs a readable assistant message before it can finish." });
1494
+ const goal = this.ledger.goal(context.goalCommitment.goalId);
1495
+ if (!goal || goal.phase !== "active" || goal.owner !== agent || goal.revision !== context.goalCommitment.goalRevision)
1496
+ return { accepted: false, fatal: true, attemptId, issues: [{ code: "goal_fence_changed", message: "Goal ownership, phase, or revision changed; this Turn can no longer finish against the old commitment." }] };
1497
+ const record = this.ledger.workRecord(goal.id);
1498
+ if (!record || record.updatedInTurn !== turnId || record.goalRevision !== goal.revision)
1499
+ issues.push({ code: "work_record_not_updated", message: "Update this Goal's Work Record in the current Turn before Handoff.", details: { goalId: goal.id, recordRevision: record?.recordRevision ?? null } });
1500
+ const evidence = Array.isArray(request.handoff?.evidence) ? request.handoff.evidence : [];
1501
+ for (const seq of evidence)
1502
+ if (!Number.isInteger(seq) || !this.ledger.eventsSince(seq - 1).some((event) => event.seq === seq))
1503
+ issues.push({ code: "evidence_not_found", message: `Evidence event ${String(seq)} does not exist in the Ledger.`, details: { seq } });
1504
+ if (issues.length)
1505
+ return { accepted: false, fatal: false, attemptId, issues };
1506
+ const token = randomUUID();
1507
+ this.#handoffValidations.set(token, { turnId, attemptId, agent, attempt: execution.attempt, leaseToken: execution.leaseToken, goalId: goal.id, goalRevision: goal.revision, message, handoff: { outcome: request.handoff.outcome, evidence: [...request.handoff.evidence] } });
1508
+ return { accepted: true, fatal: false, attemptId, token, goalId: goal.id, goalRevision: goal.revision };
1509
+ }
1510
+ #beginHandoffAttempt(turnId) {
1511
+ this.#invalidateHandoffTokens(turnId);
1512
+ const attemptId = (this.#handoffAttemptSeq.get(turnId) ?? 0) + 1;
1513
+ this.#handoffAttemptSeq.set(turnId, attemptId);
1514
+ return attemptId;
1515
+ }
1516
+ #invalidateHandoffTokens(turnId) {
1517
+ for (const [token, value] of this.#handoffValidations)
1518
+ if (value.turnId === turnId)
1519
+ this.#handoffValidations.delete(token);
1520
+ }
1521
+ #clearHandoffState(turnId) {
1522
+ this.#invalidateHandoffTokens(turnId);
1523
+ this.#handoffAttemptSeq.delete(turnId);
1524
+ }
1525
+ };
1526
+ async function runSupervisorDaemon(supervisor, options = {}) {
1527
+ const pollMs = options.pollMs ?? 1e3;
1528
+ await supervisor.recover();
1529
+ while (!options.signal?.aborted) {
1530
+ try {
1531
+ await supervisor.runAvailable(options.concurrency ?? 4);
1532
+ } catch (error) {
1533
+ options.onError?.(error);
1534
+ }
1535
+ await new Promise((resolve) => {
1536
+ if (options.signal?.aborted) {
1537
+ resolve();
1538
+ return;
1539
+ }
1540
+ const onAbort = () => {
1541
+ clearTimeout(timer);
1542
+ resolve();
1543
+ };
1544
+ const timer = setTimeout(() => {
1545
+ options.signal?.removeEventListener("abort", onAbort);
1546
+ resolve();
1547
+ }, pollMs);
1548
+ options.signal?.addEventListener("abort", onAbort, { once: true });
1549
+ if (options.signal?.aborted)
1550
+ onAbort();
1551
+ });
1552
+ }
1553
+ }
1554
+ function deriveTeam(ledger, now = (/* @__PURE__ */ new Date()).toISOString()) {
1555
+ const goals = ledger.goals();
1556
+ const wakes = ledger.wakes();
1557
+ const schedules = ledger.schedules();
1558
+ const threads = ledger.threads();
1559
+ const turns = ledger.turns();
1560
+ const handoffs = ledger.eventsSince(0, ["handoff.recorded"]);
1561
+ const owners = [...new Set(goals.map((goal) => goal.owner))].sort();
1562
+ return owners.map((agent) => {
1563
+ const owned = goals.filter((goal) => goal.owner === agent);
1564
+ const live = owned.filter((goal) => goal.phase !== "complete");
1565
+ const agentWakes = wakes.filter((wake) => wake.agent === agent).sort((a, b) => b.enqueuedSeq - a.enqueuedSeq);
1566
+ const activeWake = agentWakes.find((wake) => {
1567
+ if (wake.status !== "claimed" && wake.status !== "queued")
1568
+ return false;
1569
+ if (!wake.goalId)
1570
+ return true;
1571
+ const goal = ledger.goal(wake.goalId);
1572
+ return goal?.phase === "active" && goal.owner === agent;
1573
+ });
1574
+ const threadIds = new Set(threads.filter((thread) => thread.agent === agent).map((thread) => thread.id));
1575
+ const activeTurn = turns.find((turn) => threadIds.has(turn.threadId) && turn.status === "in_progress");
1576
+ const nextWakeAt = schedules.filter((schedule) => {
1577
+ if (schedule.agent !== agent || schedule.status !== "pending" || schedule.nextWakeAt <= now)
1578
+ return false;
1579
+ if (!schedule.goalId)
1580
+ return true;
1581
+ const goal = ledger.goal(schedule.goalId);
1582
+ return goal?.phase === "active" && goal.owner === agent;
1583
+ }).map((schedule) => schedule.nextWakeAt).sort()[0] ?? null;
1584
+ const lastHandoff = [...handoffs].reverse().find((event) => event.actor === agent) ?? null;
1585
+ const value = lastHandoff?.data;
1586
+ const lastOutcome = typeof value?.outcome === "string" ? value.outcome : null;
1587
+ let motion;
1588
+ if (live.length === 0)
1589
+ motion = "retired";
1590
+ else if (activeTurn)
1591
+ motion = "running";
1592
+ else if (activeWake)
1593
+ motion = "queued";
1594
+ else if (nextWakeAt)
1595
+ motion = "scheduled";
1596
+ else
1597
+ motion = "idle";
1598
+ return { agent, goalIds: owned.map((goal) => goal.id), motion, lastOutcome, lastHandoffSeq: lastHandoff?.seq ?? null, lastWakeStatus: agentWakes[0]?.status ?? null, nextWakeAt };
1599
+ });
1600
+ }
1601
+ function deriveRecoveryViews(ledger) {
1602
+ const views = [];
1603
+ const wakes = ledger.wakes();
1604
+ const schedules = ledger.schedules();
1605
+ const triggers = wakes.flatMap((wake) => ledger.wakeTriggers(wake.id));
1606
+ for (const turn of ledger.turns()) {
1607
+ if (turn.status !== "failed")
1608
+ continue;
1609
+ const sourceWake = wakes.find((wake) => wake.turnId === turn.id);
1610
+ const thread = ledger.thread(turn.threadId);
1611
+ const goal = turn.goalId ? ledger.goal(turn.goalId) : null;
1612
+ const goalFailure = Boolean(thread && goal && goal.phase === "active" && goal.owner === thread.agent);
1613
+ const specialistFailure = Boolean(!turn.goalId && thread && (thread.role === "verifier" || thread.role === "audit") && sourceWake?.targetKind === "specialist" && sourceWake.agent === thread.agent && sourceWake.specialistRole === thread.role);
1614
+ if (!thread || !goalFailure && !specialistFailure)
1615
+ continue;
1616
+ const base = { turnId: turn.id, agent: thread.agent };
1617
+ const scheduled = schedules.some((schedule) => {
1618
+ const recovery = parseRecoveryTrigger(schedule.id);
1619
+ const sameTarget = goalFailure ? schedule.targetKind === "goal" && schedule.goalId === goal.id : schedule.targetKind === "specialist" && thread && schedule.specialistRole === thread.role;
1620
+ return schedule.status === "pending" && schedule.setBy === "supervisor" && schedule.agent === thread.agent && sameTarget && schedule.reason === recoveryRef(turn.id) && recovery?.turnId === turn.id && recovery.attempt > 0;
1621
+ });
1622
+ if (scheduled) {
1623
+ views.push({ ...base, state: "scheduled", actionable: false });
1624
+ continue;
1625
+ }
1626
+ const recoveryWake = triggers.flatMap((trigger) => {
1627
+ const recovery = parseRecoveryTrigger(trigger.triggerRef);
1628
+ const wake = recovery?.turnId === turn.id ? wakes.find((candidate) => candidate.id === trigger.wakeId) : null;
1629
+ const sameTarget = goalFailure ? wake?.targetKind === "goal" && wake.goalId === goal.id : wake?.targetKind === "specialist" && thread && wake.specialistRole === thread.role;
1630
+ return wake?.agent === thread.agent && sameTarget ? [wake] : [];
1631
+ }).sort((left, right) => right.enqueuedSeq - left.enqueuedSeq)[0];
1632
+ if (recoveryWake?.status === "queued" || recoveryWake?.status === "claimed") {
1633
+ views.push({ ...base, state: "queued", actionable: false });
1634
+ continue;
1635
+ }
1636
+ if (recoveryWake?.status === "consumed" && recoveryWake.turnId) {
1637
+ const retry = ledger.turn(recoveryWake.turnId);
1638
+ const state = retry?.status === "in_progress" ? "running" : retry?.status === "completed" ? "recovered" : "superseded";
1639
+ views.push({ ...base, state, actionable: false });
1640
+ continue;
1641
+ }
1642
+ const parent = goalFailure && goal.parentId ? ledger.goal(goal.parentId) : null;
1643
+ const escalation = triggers.flatMap((trigger) => {
1644
+ const wake = trigger.triggerRef === childRetryExhaustedRef(turn.id) ? wakes.find((candidate) => candidate.id === trigger.wakeId) : null;
1645
+ return wake?.targetKind === "goal" && parent && wake.agent === parent.owner && wake.goalId === parent.id && parent.phase === "active" ? [wake] : [];
1646
+ }).find((wake) => wake.status === "queued" || wake.status === "claimed" || wake.status === "consumed");
1647
+ if (escalation) {
1648
+ views.push({ ...base, state: "escalated", actionable: false });
1649
+ continue;
1650
+ }
1651
+ views.push({ ...base, state: "needed", actionable: true });
1652
+ }
1653
+ return views;
1654
+ }
1655
+ function renderDashboard(ledger) {
1656
+ const rows = (values) => values.map((value) => `<tr><td><pre>${escapeHtml(JSON.stringify(value, null, 2))}</pre></td></tr>`).join("");
1657
+ return `<!doctype html><html><head><meta charset="utf-8"><title>goah status</title><style>body{font:14px ui-monospace;margin:32px;background:#101418;color:#dce3e4}section{margin:32px 0}pre{white-space:pre-wrap;border:1px solid #334;padding:12px}</style></head><body><h1>goah</h1><p>seq ${ledger.events().at(-1)?.seq ?? 0}</p><section><h2>Team</h2><table>${rows(deriveTeam(ledger))}</table></section><section><h2>Goals</h2><table>${rows(ledger.goals())}</table></section><section><h2>Wakes</h2><table>${rows(ledger.wakes())}</table></section><section><h2>Mailbox</h2><table>${rows(ledger.mailbox())}</table></section></body></html>`;
1658
+ }
1659
+ function escapeHtml(value) {
1660
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
1661
+ }
1662
+ function messageTextContent(content) {
1663
+ if (typeof content === "string")
1664
+ return normalizeAssistantText(content);
1665
+ if (!Array.isArray(content))
1666
+ return "";
1667
+ return content.map((part) => part && typeof part === "object" && !Array.isArray(part) && part.type === "text" ? normalizeAssistantText(String(part.text ?? "")) : "").filter(Boolean).join("\n");
1668
+ }
1669
+ function goalBoundCapability(method) {
1670
+ return ["goal.delegate", "goal.reassign", "goal.revise", "goal.put", "work_record.update", "schedule.set", "human.request"].includes(method);
1671
+ }
1672
+ function asRecord(value) {
1673
+ if (typeof value !== "object" || value === null || Array.isArray(value))
1674
+ throw new Error("RPC params must be an object");
1675
+ return value;
1676
+ }
1677
+ function boundedJson(value, maxChars = 2e3) {
1678
+ const text = typeof value === "string" ? value : JSON.stringify(value);
1679
+ return text.length <= maxChars ? text : `${text.slice(0, maxChars)}\u2026`;
1680
+ }
1681
+ function recoveryRef(turnId) {
1682
+ return `recovery:${turnId}`;
1683
+ }
1684
+ function recoveryScheduleId(turnId, attempt) {
1685
+ return `${recoveryRef(turnId)}:${attempt}`;
1686
+ }
1687
+ function childRetryExhaustedRef(turnId) {
1688
+ return `child-retry-exhausted:${turnId}`;
1689
+ }
1690
+ function childRetryExhaustedTurnId(triggerRef) {
1691
+ return triggerRef.startsWith("child-retry-exhausted:") ? triggerRef.slice("child-retry-exhausted:".length) || null : null;
1692
+ }
1693
+ function parseRecoveryTrigger(triggerRef) {
1694
+ if (!triggerRef.startsWith("recovery:"))
1695
+ return null;
1696
+ const [turnId, rawAttempt] = triggerRef.slice("recovery:".length).split("@")[0].split(":");
1697
+ if (!turnId)
1698
+ return null;
1699
+ const attempt = rawAttempt === void 0 ? 0 : Number(rawAttempt);
1700
+ return Number.isInteger(attempt) && attempt >= 0 ? { turnId, attempt } : null;
1701
+ }
1702
+ function mailDeliveryAttempt(triggerRef, base) {
1703
+ if (triggerRef === base)
1704
+ return 0;
1705
+ const prefix = `${base}@redelivery:`;
1706
+ if (!triggerRef.startsWith(prefix))
1707
+ return null;
1708
+ const attempt = Number(triggerRef.slice(prefix.length));
1709
+ return Number.isInteger(attempt) && attempt > 0 ? attempt : null;
1710
+ }
1711
+ function numberArray(value) {
1712
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "number"))
1713
+ throw new Error("RPC evidence must be a number array");
1714
+ return value;
1715
+ }
1716
+ function isSameNumbers(left, right) {
1717
+ return left.length === right.length && left.every((value, index) => value === right[index]);
1718
+ }
1719
+ function asChildGoal(value) {
1720
+ const input = asRecord(value ?? null);
1721
+ return { id: String(input.id), objective: String(input.objective), observationMethod: String(input.observationMethod), verificationMethod: String(input.verificationMethod), owner: String(input.owner) };
1722
+ }
1723
+ function defaultCapabilities(role) {
1724
+ if (role === "ceo")
1725
+ return ["ledger.search", "mail.send", "schedule.set", "team.list", "goal.get", "goal.create", "goal.work", "goal.delegate", "goal.reassign", "goal.revise", "goal.pause", "goal.resume", "goal.complete", "human.request", "work_record.list", "work_record.read", "work_record.history", "work_record.diff", "work_record.search", "work_record.update"];
1726
+ if (role === "verifier" || role === "audit")
1727
+ return ["ledger.search", "mail.send", "memory.append"];
1728
+ return ["ledger.search", "mail.send", "schedule.set", "goal.get", "work_record.list", "work_record.read", "work_record.history", "work_record.diff", "work_record.search", "work_record.update"];
1729
+ }
1730
+
1731
+ export {
1732
+ selectRecoveryEvents,
1733
+ composeActiveContext,
1734
+ defaultRolePrompt,
1735
+ defaultTurnPrompt,
1736
+ ProcessVerifierModel,
1737
+ VerificationPlane,
1738
+ evaluateVerification,
1739
+ calibrateVerificationThreshold,
1740
+ RunnerRouter,
1741
+ Supervisor,
1742
+ runSupervisorDaemon,
1743
+ deriveTeam,
1744
+ deriveRecoveryViews,
1745
+ renderDashboard
1746
+ };