@mindfoldhq/trellis 0.6.0-beta.9 → 0.6.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/README.md +49 -49
  2. package/dist/cli/index.d.ts.map +1 -1
  3. package/dist/cli/index.js +36 -0
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/channel/adapters/claude.d.ts +29 -0
  6. package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
  7. package/dist/commands/channel/adapters/claude.js +203 -0
  8. package/dist/commands/channel/adapters/claude.js.map +1 -0
  9. package/dist/commands/channel/adapters/codex.d.ts +85 -0
  10. package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
  11. package/dist/commands/channel/adapters/codex.js +505 -0
  12. package/dist/commands/channel/adapters/codex.js.map +1 -0
  13. package/dist/commands/channel/adapters/index.d.ts +84 -0
  14. package/dist/commands/channel/adapters/index.d.ts.map +1 -0
  15. package/dist/commands/channel/adapters/index.js +115 -0
  16. package/dist/commands/channel/adapters/index.js.map +1 -0
  17. package/dist/commands/channel/adapters/types.d.ts +33 -0
  18. package/dist/commands/channel/adapters/types.d.ts.map +1 -0
  19. package/dist/commands/channel/adapters/types.js +2 -0
  20. package/dist/commands/channel/adapters/types.js.map +1 -0
  21. package/dist/commands/channel/agent-loader.d.ts +32 -0
  22. package/dist/commands/channel/agent-loader.d.ts.map +1 -0
  23. package/dist/commands/channel/agent-loader.js +154 -0
  24. package/dist/commands/channel/agent-loader.js.map +1 -0
  25. package/dist/commands/channel/context-loader.d.ts +26 -0
  26. package/dist/commands/channel/context-loader.d.ts.map +1 -0
  27. package/dist/commands/channel/context-loader.js +290 -0
  28. package/dist/commands/channel/context-loader.js.map +1 -0
  29. package/dist/commands/channel/context.d.ts +16 -0
  30. package/dist/commands/channel/context.d.ts.map +1 -0
  31. package/dist/commands/channel/context.js +83 -0
  32. package/dist/commands/channel/context.js.map +1 -0
  33. package/dist/commands/channel/create.d.ts +27 -0
  34. package/dist/commands/channel/create.d.ts.map +1 -0
  35. package/dist/commands/channel/create.js +39 -0
  36. package/dist/commands/channel/create.js.map +1 -0
  37. package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
  38. package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
  39. package/dist/commands/channel/dev-parse-trace.js +70 -0
  40. package/dist/commands/channel/dev-parse-trace.js.map +1 -0
  41. package/dist/commands/channel/guard.d.ts +150 -0
  42. package/dist/commands/channel/guard.d.ts.map +1 -0
  43. package/dist/commands/channel/guard.js +474 -0
  44. package/dist/commands/channel/guard.js.map +1 -0
  45. package/dist/commands/channel/index.d.ts +3 -0
  46. package/dist/commands/channel/index.d.ts.map +1 -0
  47. package/dist/commands/channel/index.js +531 -0
  48. package/dist/commands/channel/index.js.map +1 -0
  49. package/dist/commands/channel/interrupt.d.ts +10 -0
  50. package/dist/commands/channel/interrupt.d.ts.map +1 -0
  51. package/dist/commands/channel/interrupt.js +22 -0
  52. package/dist/commands/channel/interrupt.js.map +1 -0
  53. package/dist/commands/channel/kill.d.ts +7 -0
  54. package/dist/commands/channel/kill.d.ts.map +1 -0
  55. package/dist/commands/channel/kill.js +121 -0
  56. package/dist/commands/channel/kill.js.map +1 -0
  57. package/dist/commands/channel/list.d.ts +17 -0
  58. package/dist/commands/channel/list.d.ts.map +1 -0
  59. package/dist/commands/channel/list.js +233 -0
  60. package/dist/commands/channel/list.js.map +1 -0
  61. package/dist/commands/channel/messages.d.ts +15 -0
  62. package/dist/commands/channel/messages.d.ts.map +1 -0
  63. package/dist/commands/channel/messages.js +245 -0
  64. package/dist/commands/channel/messages.js.map +1 -0
  65. package/dist/commands/channel/rm.d.ts +27 -0
  66. package/dist/commands/channel/rm.d.ts.map +1 -0
  67. package/dist/commands/channel/rm.js +216 -0
  68. package/dist/commands/channel/rm.js.map +1 -0
  69. package/dist/commands/channel/run.d.ts +30 -0
  70. package/dist/commands/channel/run.d.ts.map +1 -0
  71. package/dist/commands/channel/run.js +130 -0
  72. package/dist/commands/channel/run.js.map +1 -0
  73. package/dist/commands/channel/send.d.ts +11 -0
  74. package/dist/commands/channel/send.d.ts.map +1 -0
  75. package/dist/commands/channel/send.js +24 -0
  76. package/dist/commands/channel/send.js.map +1 -0
  77. package/dist/commands/channel/spawn.d.ts +40 -0
  78. package/dist/commands/channel/spawn.d.ts.map +1 -0
  79. package/dist/commands/channel/spawn.js +244 -0
  80. package/dist/commands/channel/spawn.js.map +1 -0
  81. package/dist/commands/channel/store/events.d.ts +39 -0
  82. package/dist/commands/channel/store/events.d.ts.map +1 -0
  83. package/dist/commands/channel/store/events.js +87 -0
  84. package/dist/commands/channel/store/events.js.map +1 -0
  85. package/dist/commands/channel/store/filter.d.ts +3 -0
  86. package/dist/commands/channel/store/filter.d.ts.map +1 -0
  87. package/dist/commands/channel/store/filter.js +2 -0
  88. package/dist/commands/channel/store/filter.js.map +1 -0
  89. package/dist/commands/channel/store/lock.d.ts +23 -0
  90. package/dist/commands/channel/store/lock.d.ts.map +1 -0
  91. package/dist/commands/channel/store/lock.js +99 -0
  92. package/dist/commands/channel/store/lock.js.map +1 -0
  93. package/dist/commands/channel/store/paths.d.ts +63 -0
  94. package/dist/commands/channel/store/paths.d.ts.map +1 -0
  95. package/dist/commands/channel/store/paths.js +246 -0
  96. package/dist/commands/channel/store/paths.js.map +1 -0
  97. package/dist/commands/channel/store/schema.d.ts +27 -0
  98. package/dist/commands/channel/store/schema.d.ts.map +1 -0
  99. package/dist/commands/channel/store/schema.js +34 -0
  100. package/dist/commands/channel/store/schema.js.map +1 -0
  101. package/dist/commands/channel/store/thread-state.d.ts +5 -0
  102. package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
  103. package/dist/commands/channel/store/thread-state.js +16 -0
  104. package/dist/commands/channel/store/thread-state.js.map +1 -0
  105. package/dist/commands/channel/store/watch.d.ts +19 -0
  106. package/dist/commands/channel/store/watch.d.ts.map +1 -0
  107. package/dist/commands/channel/store/watch.js +146 -0
  108. package/dist/commands/channel/store/watch.js.map +1 -0
  109. package/dist/commands/channel/supervisor/idle.d.ts +46 -0
  110. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
  111. package/dist/commands/channel/supervisor/idle.js +72 -0
  112. package/dist/commands/channel/supervisor/idle.js.map +1 -0
  113. package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
  114. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
  115. package/dist/commands/channel/supervisor/inbox.js +160 -0
  116. package/dist/commands/channel/supervisor/inbox.js.map +1 -0
  117. package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
  118. package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
  119. package/dist/commands/channel/supervisor/shutdown.js +146 -0
  120. package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
  121. package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
  122. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
  123. package/dist/commands/channel/supervisor/stdout.js +121 -0
  124. package/dist/commands/channel/supervisor/stdout.js.map +1 -0
  125. package/dist/commands/channel/supervisor/turns.d.ts +31 -0
  126. package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
  127. package/dist/commands/channel/supervisor/turns.js +45 -0
  128. package/dist/commands/channel/supervisor/turns.js.map +1 -0
  129. package/dist/commands/channel/supervisor/warning.d.ts +48 -0
  130. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
  131. package/dist/commands/channel/supervisor/warning.js +77 -0
  132. package/dist/commands/channel/supervisor/warning.js.map +1 -0
  133. package/dist/commands/channel/supervisor.d.ts +59 -0
  134. package/dist/commands/channel/supervisor.d.ts.map +1 -0
  135. package/dist/commands/channel/supervisor.js +344 -0
  136. package/dist/commands/channel/supervisor.js.map +1 -0
  137. package/dist/commands/channel/text-body.d.ts +13 -0
  138. package/dist/commands/channel/text-body.d.ts.map +1 -0
  139. package/dist/commands/channel/text-body.js +47 -0
  140. package/dist/commands/channel/text-body.js.map +1 -0
  141. package/dist/commands/channel/threads.d.ts +39 -0
  142. package/dist/commands/channel/threads.d.ts.map +1 -0
  143. package/dist/commands/channel/threads.js +106 -0
  144. package/dist/commands/channel/threads.js.map +1 -0
  145. package/dist/commands/channel/title.d.ts +12 -0
  146. package/dist/commands/channel/title.d.ts.map +1 -0
  147. package/dist/commands/channel/title.js +24 -0
  148. package/dist/commands/channel/title.js.map +1 -0
  149. package/dist/commands/channel/wait.d.ts +17 -0
  150. package/dist/commands/channel/wait.d.ts.map +1 -0
  151. package/dist/commands/channel/wait.js +75 -0
  152. package/dist/commands/channel/wait.js.map +1 -0
  153. package/dist/commands/init.d.ts +3 -0
  154. package/dist/commands/init.d.ts.map +1 -1
  155. package/dist/commands/init.js +162 -43
  156. package/dist/commands/init.js.map +1 -1
  157. package/dist/commands/mem.d.ts +13 -217
  158. package/dist/commands/mem.d.ts.map +1 -1
  159. package/dist/commands/mem.js +142 -1587
  160. package/dist/commands/mem.js.map +1 -1
  161. package/dist/commands/uninstall.d.ts.map +1 -1
  162. package/dist/commands/uninstall.js +28 -2
  163. package/dist/commands/uninstall.js.map +1 -1
  164. package/dist/commands/update.d.ts.map +1 -1
  165. package/dist/commands/update.js +102 -5
  166. package/dist/commands/update.js.map +1 -1
  167. package/dist/commands/workflow.d.ts +35 -0
  168. package/dist/commands/workflow.d.ts.map +1 -0
  169. package/dist/commands/workflow.js +232 -0
  170. package/dist/commands/workflow.js.map +1 -0
  171. package/dist/configurators/claude.d.ts.map +1 -1
  172. package/dist/configurators/claude.js +1 -0
  173. package/dist/configurators/claude.js.map +1 -1
  174. package/dist/configurators/index.d.ts.map +1 -1
  175. package/dist/configurators/index.js +5 -0
  176. package/dist/configurators/index.js.map +1 -1
  177. package/dist/configurators/reasonix.d.ts +23 -0
  178. package/dist/configurators/reasonix.d.ts.map +1 -0
  179. package/dist/configurators/reasonix.js +60 -0
  180. package/dist/configurators/reasonix.js.map +1 -0
  181. package/dist/configurators/shared.d.ts.map +1 -1
  182. package/dist/configurators/shared.js +8 -0
  183. package/dist/configurators/shared.js.map +1 -1
  184. package/dist/configurators/workflow.d.ts +8 -0
  185. package/dist/configurators/workflow.d.ts.map +1 -1
  186. package/dist/configurators/workflow.js +14 -3
  187. package/dist/configurators/workflow.js.map +1 -1
  188. package/dist/constants/paths.d.ts +4 -0
  189. package/dist/constants/paths.d.ts.map +1 -1
  190. package/dist/constants/paths.js +4 -0
  191. package/dist/constants/paths.js.map +1 -1
  192. package/dist/migrations/manifests/0.5.14.json +9 -0
  193. package/dist/migrations/manifests/0.5.15.json +9 -0
  194. package/dist/migrations/manifests/0.5.16.json +9 -0
  195. package/dist/migrations/manifests/0.5.17.json +9 -0
  196. package/dist/migrations/manifests/0.5.18.json +9 -0
  197. package/dist/migrations/manifests/0.5.19.json +9 -0
  198. package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
  199. package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
  200. package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
  201. package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
  202. package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
  203. package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
  204. package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
  205. package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
  206. package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
  207. package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
  208. package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
  209. package/dist/migrations/manifests/0.6.0-beta.21.json +9 -0
  210. package/dist/migrations/manifests/0.6.0-beta.22.json +9 -0
  211. package/dist/migrations/manifests/0.6.0-beta.23.json +88 -0
  212. package/dist/migrations/manifests/0.6.0-rc.0.json +9 -0
  213. package/dist/templates/claude/agents/trellis-check.md +12 -6
  214. package/dist/templates/claude/agents/trellis-implement.md +1 -1
  215. package/dist/templates/claude/agents/trellis-research.md +1 -1
  216. package/dist/templates/codebuddy/agents/trellis-check.md +12 -6
  217. package/dist/templates/codebuddy/agents/trellis-implement.md +1 -1
  218. package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
  219. package/dist/templates/codex/agents/trellis-check.toml +0 -25
  220. package/dist/templates/codex/agents/trellis-implement.toml +0 -25
  221. package/dist/templates/codex/config.toml +9 -16
  222. package/dist/templates/codex/hooks/session-start.py +22 -0
  223. package/dist/templates/codex/hooks.json +1 -1
  224. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +27 -0
  225. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +81 -0
  226. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +66 -0
  227. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +93 -0
  228. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/SKILL.md +41 -0
  229. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +90 -0
  230. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/repository-analysis.md +59 -0
  231. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +61 -0
  232. package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-writing.md +70 -0
  233. package/dist/templates/copilot/hooks/session-start.py +24 -0
  234. package/dist/templates/cursor/agents/trellis-check.md +12 -6
  235. package/dist/templates/cursor/agents/trellis-implement.md +1 -1
  236. package/dist/templates/cursor/agents/trellis-research.md +1 -1
  237. package/dist/templates/cursor/hooks.json +0 -6
  238. package/dist/templates/droid/droids/trellis-check.md +12 -6
  239. package/dist/templates/droid/droids/trellis-implement.md +1 -1
  240. package/dist/templates/droid/droids/trellis-research.md +1 -1
  241. package/dist/templates/gemini/agents/trellis-check.md +11 -5
  242. package/dist/templates/kiro/agents/trellis-check.json +1 -1
  243. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
  244. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +130 -0
  245. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +38 -0
  246. package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
  247. package/dist/templates/opencode/agents/trellis-check.md +11 -5
  248. package/dist/templates/pi/agents/trellis-check.md +5 -4
  249. package/dist/templates/pi/agents/trellis-implement.md +5 -4
  250. package/dist/templates/pi/extensions/trellis/index.ts.txt +1339 -913
  251. package/dist/templates/pi/settings.json +0 -9
  252. package/dist/templates/qoder/agents/trellis-check.md +12 -6
  253. package/dist/templates/qoder/agents/trellis-implement.md +1 -1
  254. package/dist/templates/qoder/agents/trellis-research.md +1 -1
  255. package/dist/templates/reasonix/agents/trellis-check.md +36 -0
  256. package/dist/templates/reasonix/agents/trellis-implement.md +41 -0
  257. package/dist/templates/reasonix/index.d.ts +13 -0
  258. package/dist/templates/reasonix/index.d.ts.map +1 -0
  259. package/dist/templates/reasonix/index.js +16 -0
  260. package/dist/templates/reasonix/index.js.map +1 -0
  261. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  262. package/dist/templates/shared-hooks/index.js +0 -1
  263. package/dist/templates/shared-hooks/index.js.map +1 -1
  264. package/dist/templates/shared-hooks/inject-workflow-state.py +22 -0
  265. package/dist/templates/shared-hooks/session-start.py +25 -8
  266. package/dist/templates/trellis/agents/check.md +70 -0
  267. package/dist/templates/trellis/agents/implement.md +71 -0
  268. package/dist/templates/trellis/config.yaml +20 -0
  269. package/dist/templates/trellis/index.d.ts +13 -0
  270. package/dist/templates/trellis/index.d.ts.map +1 -1
  271. package/dist/templates/trellis/index.js +22 -0
  272. package/dist/templates/trellis/index.js.map +1 -1
  273. package/dist/templates/trellis/scripts/common/safe_commit.py +49 -19
  274. package/dist/templates/trellis/scripts/common/task_store.py +94 -16
  275. package/dist/templates/trellis/workflow.md +21 -0
  276. package/dist/types/ai-tools.d.ts +4 -4
  277. package/dist/types/ai-tools.d.ts.map +1 -1
  278. package/dist/types/ai-tools.js +16 -0
  279. package/dist/types/ai-tools.js.map +1 -1
  280. package/dist/utils/agent-refs.d.ts +31 -0
  281. package/dist/utils/agent-refs.d.ts.map +1 -0
  282. package/dist/utils/agent-refs.js +63 -0
  283. package/dist/utils/agent-refs.js.map +1 -0
  284. package/dist/utils/cwd-guard.d.ts +38 -0
  285. package/dist/utils/cwd-guard.d.ts.map +1 -0
  286. package/dist/utils/cwd-guard.js +62 -0
  287. package/dist/utils/cwd-guard.js.map +1 -0
  288. package/dist/utils/file-writer.d.ts +13 -0
  289. package/dist/utils/file-writer.d.ts.map +1 -1
  290. package/dist/utils/file-writer.js +59 -1
  291. package/dist/utils/file-writer.js.map +1 -1
  292. package/dist/utils/manifest-prune.d.ts +61 -0
  293. package/dist/utils/manifest-prune.d.ts.map +1 -0
  294. package/dist/utils/manifest-prune.js +136 -0
  295. package/dist/utils/manifest-prune.js.map +1 -0
  296. package/dist/utils/registry-config.d.ts +7 -0
  297. package/dist/utils/registry-config.d.ts.map +1 -0
  298. package/dist/utils/registry-config.js +171 -0
  299. package/dist/utils/registry-config.js.map +1 -0
  300. package/dist/utils/task-json.d.ts +9 -42
  301. package/dist/utils/task-json.d.ts.map +1 -1
  302. package/dist/utils/task-json.js +8 -45
  303. package/dist/utils/task-json.js.map +1 -1
  304. package/dist/utils/template-fetcher.d.ts +11 -0
  305. package/dist/utils/template-fetcher.d.ts.map +1 -1
  306. package/dist/utils/template-fetcher.js +51 -2
  307. package/dist/utils/template-fetcher.js.map +1 -1
  308. package/dist/utils/template-hash.d.ts +32 -6
  309. package/dist/utils/template-hash.d.ts.map +1 -1
  310. package/dist/utils/template-hash.js +53 -31
  311. package/dist/utils/template-hash.js.map +1 -1
  312. package/dist/utils/workflow-resolver.d.ts +86 -0
  313. package/dist/utils/workflow-resolver.d.ts.map +1 -0
  314. package/dist/utils/workflow-resolver.js +265 -0
  315. package/dist/utils/workflow-resolver.js.map +1 -0
  316. package/package.json +9 -8
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Supervisor-side idle-timeout timer.
3
+ *
4
+ * Complements the spawn-time guard: each running worker self-terminates
5
+ * after its own idle TTL so a long-lived supervisor can't keep an
6
+ * otherwise-idle worker alive indefinitely.
7
+ *
8
+ * Behavior:
9
+ * - Start an idle timer right after `spawned`.
10
+ * - Reset / restart on `turn_finished` and `interrupted` (worker
11
+ * transitioned back to idle).
12
+ * - Pause on `turn_started` (worker is mid-turn; never kill mid-turn).
13
+ * - On idle timeout, call `shutdown.request("SIGTERM", "idle-timeout")`.
14
+ *
15
+ * Lives outside `createShutdown` so the shutdown funnel only owns the
16
+ * kill ladder + `killed` append. Cancellation is via the returned
17
+ * handle (used on supervisor teardown).
18
+ */
19
+ /**
20
+ * Schedule a self-resetting idle timer. `idleTimeoutMs <= 0` short-
21
+ * circuits to a no-op handle (idle cleanup disabled).
22
+ */
23
+ export function scheduleSupervisorIdleTimer(args) {
24
+ const { idleTimeoutMs, shutdown, isChildExited, log } = args;
25
+ if (idleTimeoutMs <= 0) {
26
+ return {
27
+ reset: () => undefined,
28
+ pause: () => undefined,
29
+ cancel: () => undefined,
30
+ };
31
+ }
32
+ let timer;
33
+ let cancelled = false;
34
+ const clear = () => {
35
+ if (timer) {
36
+ clearTimeout(timer);
37
+ timer = undefined;
38
+ }
39
+ };
40
+ const fire = () => {
41
+ timer = undefined;
42
+ if (cancelled)
43
+ return;
44
+ if (shutdown.isShuttingDown() ||
45
+ shutdown.hasTerminalEvent() ||
46
+ isChildExited()) {
47
+ return;
48
+ }
49
+ log.write(`[supervisor] idle timeout ${idleTimeoutMs}ms reached, requesting shutdown\n`);
50
+ void shutdown.request("SIGTERM", "idle-timeout");
51
+ };
52
+ const start = () => {
53
+ if (cancelled)
54
+ return;
55
+ clear();
56
+ timer = setTimeout(fire, idleTimeoutMs);
57
+ // Don't keep the supervisor alive solely for the idle timer; if
58
+ // every other handle has gone away the worker has nothing to do.
59
+ timer.unref?.();
60
+ };
61
+ // Initial schedule: worker just spawned, currently idle.
62
+ start();
63
+ return {
64
+ reset: start,
65
+ pause: clear,
66
+ cancel: () => {
67
+ cancelled = true;
68
+ clear();
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=idle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idle.js","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/idle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA0BH;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,IAA2B;IAE3B,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7D,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;YACtB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;YACtB,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS;SACxB,CAAC;IACJ,CAAC;IAED,IAAI,KAAgD,CAAC;IACrD,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,KAAK,GAAG,SAAS,CAAC;QAClB,IAAI,SAAS;YAAE,OAAO;QACtB,IACE,QAAQ,CAAC,cAAc,EAAE;YACzB,QAAQ,CAAC,gBAAgB,EAAE;YAC3B,aAAa,EAAE,EACf,CAAC;YACD,OAAO;QACT,CAAC;QACD,GAAG,CAAC,KAAK,CACP,6BAA6B,aAAa,mCAAmC,CAC9E,CAAC;QACF,KAAK,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IACnD,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,SAAS;YAAE,OAAO;QACtB,KAAK,EAAE,CAAC;QACR,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QACxC,gEAAgE;QAChE,iEAAiE;QACjE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAClB,CAAC,CAAC;IAEF,yDAAyD;IACzD,KAAK,EAAE,CAAC;IAER,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,GAAG,EAAE;YACX,SAAS,GAAG,IAAI,CAAC;YACjB,KAAK,EAAE,CAAC;QACV,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Inbox watcher: tails events.jsonl for worker-addressed messages and
3
+ * interrupt requests, then forwards accepted input into the worker's stdin.
4
+ * A persisted cursor file keeps respawns from replaying events the previous
5
+ * supervisor already delivered.
6
+ *
7
+ * Step 3 of the supervisor refactor: pulled out of supervisor.ts so the
8
+ * orchestrator only needs to call `runInboxWatcher(...)`. Cursor
9
+ * read/write helpers stay private to this module.
10
+ */
11
+ import type { ChildProcessByStdio } from "node:child_process";
12
+ import type { Readable, Writable } from "node:stream";
13
+ import { type InboxPolicy } from "@mindfoldhq/trellis-core/channel";
14
+ import type { WorkerAdapter } from "../adapters/index.js";
15
+ import type { TurnTracker } from "./turns.js";
16
+ type Child = ChildProcessByStdio<Writable, Readable, Readable>;
17
+ export interface InboxWatcherArgs {
18
+ channelName: string;
19
+ workerName: string;
20
+ adapter: WorkerAdapter;
21
+ ctx: unknown;
22
+ child: Child;
23
+ signal: AbortSignal;
24
+ /** Inbox delivery policy. Defaults to `explicitOnly` (legacy behavior). */
25
+ inboxPolicy?: InboxPolicy;
26
+ turnTracker?: TurnTracker;
27
+ }
28
+ export declare function runInboxWatcher(args: InboxWatcherArgs): Promise<void>;
29
+ export {};
30
+ //# sourceMappingURL=inbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/inbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,KAAK,KAAK,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;IACvB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoH3E"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Inbox watcher: tails events.jsonl for worker-addressed messages and
3
+ * interrupt requests, then forwards accepted input into the worker's stdin.
4
+ * A persisted cursor file keeps respawns from replaying events the previous
5
+ * supervisor already delivered.
6
+ *
7
+ * Step 3 of the supervisor refactor: pulled out of supervisor.ts so the
8
+ * orchestrator only needs to call `runInboxWatcher(...)`. Cursor
9
+ * read/write helpers stay private to this module.
10
+ */
11
+ import fs from "node:fs";
12
+ import { DEFAULT_INBOX_POLICY, matchesInboxPolicy, } from "@mindfoldhq/trellis-core/channel";
13
+ import { appendEvent } from "../store/events.js";
14
+ import { workerFile } from "../store/paths.js";
15
+ import { watchEvents } from "../store/watch.js";
16
+ export async function runInboxWatcher(args) {
17
+ const { channelName, workerName, adapter, ctx, child, signal } = args;
18
+ const inboxPolicy = args.inboxPolicy ?? DEFAULT_INBOX_POLICY;
19
+ // Resume from persisted cursor: first-time spawn → 0 (read full backlog);
20
+ // respawn after kill → last forwarded seq (no replay).
21
+ let cursor = readInboxCursor(channelName, workerName);
22
+ for await (const ev of watchEvents(channelName, {
23
+ self: workerName, // ignore our own events
24
+ kind: ["message", "interrupt_requested"],
25
+ },
26
+ // First run with cursor=0 reads backlog from start; subsequent runs
27
+ // use sinceSeq to skip already-processed events. Both cases tail
28
+ // future events normally.
29
+ { signal, sinceSeq: cursor, fromStart: cursor === 0 ? true : undefined })) {
30
+ if (signal.aborted)
31
+ return;
32
+ if (ev.kind === "message") {
33
+ // Core decides delivery from the worker's inbox policy: explicitOnly
34
+ // (default) consumes only targeted messages; broadcastAndExplicit
35
+ // also consumes broadcasts.
36
+ if (!matchesInboxPolicy(ev, workerName, inboxPolicy))
37
+ continue;
38
+ }
39
+ else if (ev.worker !== workerName) {
40
+ continue;
41
+ }
42
+ const text = (ev.text ?? "").trim();
43
+ const interruptText = (ev.message ?? "").trim();
44
+ const isInterrupt = ev.kind === "interrupt_requested";
45
+ if (!text && (!isInterrupt || !interruptText))
46
+ continue;
47
+ // Block until the adapter says it can accept input (e.g. codex
48
+ // thread/start has produced a threadId). Drop the message if we
49
+ // never get ready before being aborted.
50
+ if (!adapter.isReady(ctx)) {
51
+ const deadline = Date.now() + 60_000;
52
+ while (!adapter.isReady(ctx) &&
53
+ Date.now() < deadline &&
54
+ !signal.aborted) {
55
+ await sleep(25);
56
+ }
57
+ if (!adapter.isReady(ctx)) {
58
+ // never became ready; advance the cursor anyway so we don't
59
+ // re-attempt this exact event on next start.
60
+ cursor = ev.seq;
61
+ writeInboxCursor(channelName, workerName, cursor);
62
+ continue;
63
+ }
64
+ }
65
+ if (!isInterrupt) {
66
+ await waitForActiveTurnToFinish(args.turnTracker, signal);
67
+ if (signal.aborted)
68
+ return;
69
+ }
70
+ if (isInterrupt) {
71
+ const aborted = args.turnTracker?.abortCurrent();
72
+ if (aborted) {
73
+ await appendEvent(channelName, {
74
+ kind: "turn_finished",
75
+ by: workerName,
76
+ worker: workerName,
77
+ inputSeq: aborted.inputSeq,
78
+ turnId: aborted.turnId,
79
+ outcome: "aborted",
80
+ });
81
+ }
82
+ await appendEvent(channelName, {
83
+ kind: "interrupted",
84
+ by: workerName,
85
+ worker: workerName,
86
+ ...(aborted?.turnId ? { turnId: aborted.turnId } : {}),
87
+ reason: "user",
88
+ method: "stdin",
89
+ outcome: aborted ? "interrupted" : "no-active-turn",
90
+ });
91
+ }
92
+ let turn = args.turnTracker?.begin(ev.seq);
93
+ try {
94
+ if (turn) {
95
+ await appendEvent(channelName, {
96
+ kind: "turn_started",
97
+ by: workerName,
98
+ worker: workerName,
99
+ inputSeq: ev.seq,
100
+ turnId: turn.turnId,
101
+ });
102
+ }
103
+ child.stdin.write(isInterrupt
104
+ ? adapter.encodeInterruptMessage(interruptText, ctx)
105
+ : adapter.encodeUserMessage(text, ctx));
106
+ cursor = ev.seq;
107
+ writeInboxCursor(channelName, workerName, cursor);
108
+ }
109
+ catch {
110
+ if (turn) {
111
+ args.turnTracker?.finish();
112
+ await appendEvent(channelName, {
113
+ kind: "turn_finished",
114
+ by: workerName,
115
+ worker: workerName,
116
+ inputSeq: turn.inputSeq,
117
+ turnId: turn.turnId,
118
+ outcome: "aborted",
119
+ }).catch(() => undefined);
120
+ turn = undefined;
121
+ }
122
+ // stdin closed, worker exiting — bail out
123
+ return;
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * Per-worker inbox consumption cursor. Persisted to
129
+ * `<worker>.inbox-cursor` so a respawn (same worker name) doesn't replay
130
+ * messages that the previous supervisor already forwarded into the worker
131
+ * process. The cursor is the highest seq we've already turned into a
132
+ * worker stdin write.
133
+ */
134
+ function readInboxCursor(channelName, workerName) {
135
+ try {
136
+ const raw = fs.readFileSync(workerFile(channelName, workerName, "inbox-cursor"), "utf-8");
137
+ const n = Number(raw.trim());
138
+ return Number.isFinite(n) && n > 0 ? n : 0;
139
+ }
140
+ catch {
141
+ return 0;
142
+ }
143
+ }
144
+ function writeInboxCursor(channelName, workerName, seq) {
145
+ try {
146
+ fs.writeFileSync(workerFile(channelName, workerName, "inbox-cursor"), String(seq), "utf-8");
147
+ }
148
+ catch {
149
+ // ignore — cursor is best-effort; worst case we replay a message
150
+ }
151
+ }
152
+ function sleep(ms) {
153
+ return new Promise((r) => setTimeout(r, ms));
154
+ }
155
+ async function waitForActiveTurnToFinish(turnTracker, signal) {
156
+ while (turnTracker?.current() && !signal.aborted) {
157
+ await sleep(25);
158
+ }
159
+ }
160
+ //# sourceMappingURL=inbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox.js","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/inbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * ShutdownController — the single funnel for every "this worker is going
3
+ * away" trigger (explicit kill, timeout, post-spawn crash, signal, child
4
+ * exit). It owns:
5
+ *
6
+ * - the `shutdownReason` flag (idempotent — first call wins)
7
+ * - the SIGTERM → grace → SIGKILL ladder
8
+ * - the trailing `killed` event append
9
+ * - a `terminalEmitted` flag tracking adapter-emitted done/error
10
+ * - `finalizeOnExit` — synthesises a fallback `done`/`error` when the
11
+ * worker exited without the adapter sending one (otherwise
12
+ * `wait --kind done` would hang forever)
13
+ * - `awaitFinalize` — lets `child.on("exit")` block process.exit until
14
+ * any in-progress killed-append from a concurrent shutdown completes
15
+ *
16
+ * Step 2 of the supervisor refactor: this absorbs the 5 reviewer issues
17
+ * (codex #1 crashed-without-done, #2 fire-and-forget shutdown, #3 spawn
18
+ * after shutdown requested, #4 handshake error detail; claude M2 post-
19
+ * spawn error ordering, L1 pre-spawn double-fire guard) into a single
20
+ * state machine. The supervisor.ts orchestrator stays mostly mechanical.
21
+ */
22
+ import type { ChildProcessByStdio } from "node:child_process";
23
+ import type { Readable, Writable } from "node:stream";
24
+ type Child = ChildProcessByStdio<Writable, Readable, Readable>;
25
+ export type ShutdownReason = "explicit-kill" | "timeout" | "crash" | "idle-timeout";
26
+ export interface ShutdownController {
27
+ /** Idempotent: only the first call wins. Returns the killed-append
28
+ * promise so callers can await ordering if they need to. */
29
+ request(signal: NodeJS.Signals, reason: ShutdownReason): Promise<void>;
30
+ /** Synchronously mark shutdown intent without starting the kill
31
+ * ladder or appending `killed`. Use when other code must see
32
+ * `isShuttingDown=true` BEFORE the caller proceeds to any await
33
+ * (e.g. post-spawn error handler that needs to `await appendEvent`
34
+ * first, but doesn't want the main flow to keep writing `spawned`).
35
+ * Returns true if this call claimed the flag, false if already set. */
36
+ claim(reason: ShutdownReason): boolean;
37
+ isShuttingDown(): boolean;
38
+ reason(): ShutdownReason | null;
39
+ /** Mark that the adapter has produced a `done` or `error` event, so
40
+ * `finalizeOnExit` won't synthesise a fallback. */
41
+ markTerminalEmitted(): void;
42
+ hasTerminalEvent(): boolean;
43
+ /** Call from `child.on("exit")` — synthesises a fallback terminal
44
+ * event if the adapter never produced one, then awaits any pending
45
+ * `request()` so `killed` lands before the supervisor exits. */
46
+ finalizeOnExit(code: number | null, signal: NodeJS.Signals | null): Promise<void>;
47
+ /** Promise that resolves when the current (or last) `request()` has
48
+ * finished writing its `killed` event. No-op when never requested. */
49
+ awaitFinalize(): Promise<void>;
50
+ }
51
+ export interface CreateShutdownArgs {
52
+ channelName: string;
53
+ workerName: string;
54
+ log: {
55
+ write: (data: string) => void;
56
+ };
57
+ /** Lazy child getter — the controller is created before `spawn()`
58
+ * returns, so we read the child handle at shutdown time. */
59
+ getChild: () => Child;
60
+ graceMs: number;
61
+ /** Recorded on the `killed` event for the timeout reason. */
62
+ timeoutMs?: number;
63
+ /** Recorded on the `killed` event when reason is `"idle-timeout"`. */
64
+ idleTimeoutMs?: number;
65
+ }
66
+ export declare function createShutdown(args: CreateShutdownArgs): ShutdownController;
67
+ export {};
68
+ //# sourceMappingURL=shutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/shutdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAItD,KAAK,KAAK,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/D,MAAM,MAAM,cAAc,GACtB,eAAe,GACf,SAAS,GACT,OAAO,GACP,cAAc,CAAC;AAEnB,MAAM,WAAW,kBAAkB;IACjC;iEAC6D;IAC7D,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE;;;;;4EAKwE;IACxE,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC;IACvC,cAAc,IAAI,OAAO,CAAC;IAC1B,MAAM,IAAI,cAAc,GAAG,IAAI,CAAC;IAEhC;wDACoD;IACpD,mBAAmB,IAAI,IAAI,CAAC;IAC5B,gBAAgB,IAAI,OAAO,CAAC;IAE5B;;qEAEiE;IACjE,cAAc,CACZ,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;2EACuE;IACvE,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE;QAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACvC;iEAC6D;IAC7D,QAAQ,EAAE,MAAM,KAAK,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAkJ3E"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * ShutdownController — the single funnel for every "this worker is going
3
+ * away" trigger (explicit kill, timeout, post-spawn crash, signal, child
4
+ * exit). It owns:
5
+ *
6
+ * - the `shutdownReason` flag (idempotent — first call wins)
7
+ * - the SIGTERM → grace → SIGKILL ladder
8
+ * - the trailing `killed` event append
9
+ * - a `terminalEmitted` flag tracking adapter-emitted done/error
10
+ * - `finalizeOnExit` — synthesises a fallback `done`/`error` when the
11
+ * worker exited without the adapter sending one (otherwise
12
+ * `wait --kind done` would hang forever)
13
+ * - `awaitFinalize` — lets `child.on("exit")` block process.exit until
14
+ * any in-progress killed-append from a concurrent shutdown completes
15
+ *
16
+ * Step 2 of the supervisor refactor: this absorbs the 5 reviewer issues
17
+ * (codex #1 crashed-without-done, #2 fire-and-forget shutdown, #3 spawn
18
+ * after shutdown requested, #4 handshake error detail; claude M2 post-
19
+ * spawn error ordering, L1 pre-spawn double-fire guard) into a single
20
+ * state machine. The supervisor.ts orchestrator stays mostly mechanical.
21
+ */
22
+ import { appendEvent } from "../store/events.js";
23
+ export function createShutdown(args) {
24
+ const { channelName, workerName, log, getChild, graceMs, timeoutMs, idleTimeoutMs, } = args;
25
+ let shutdownReason = null;
26
+ let requestSignal = null;
27
+ let terminalEmitted = false;
28
+ let killedPromise = null;
29
+ const childStillRunning = (child) => child.exitCode === null && child.signalCode === null;
30
+ const startKillLadder = (child) => {
31
+ try {
32
+ child.stdin.end();
33
+ }
34
+ catch {
35
+ // already closed
36
+ }
37
+ setTimeout(() => {
38
+ if (childStillRunning(child)) {
39
+ log.write(`[supervisor] grace expired, SIGTERM worker\n`);
40
+ try {
41
+ child.kill("SIGTERM");
42
+ }
43
+ catch {
44
+ // already dead
45
+ }
46
+ setTimeout(() => {
47
+ if (childStillRunning(child)) {
48
+ log.write(`[supervisor] still alive, SIGKILL worker\n`);
49
+ try {
50
+ child.kill("SIGKILL");
51
+ }
52
+ catch {
53
+ // already dead
54
+ }
55
+ }
56
+ }, graceMs);
57
+ }
58
+ }, graceMs);
59
+ };
60
+ const writeKilled = async (reason, signal) => {
61
+ await appendEvent(channelName, {
62
+ kind: "killed",
63
+ by: `supervisor:${workerName}`,
64
+ reason,
65
+ signal,
66
+ ...(reason === "timeout" && timeoutMs ? { timeout_ms: timeoutMs } : {}),
67
+ ...(reason === "idle-timeout" && idleTimeoutMs
68
+ ? { idle_timeout_ms: idleTimeoutMs }
69
+ : {}),
70
+ });
71
+ };
72
+ const claim = (reason) => {
73
+ if (shutdownReason)
74
+ return false;
75
+ shutdownReason = reason;
76
+ return true;
77
+ };
78
+ const request = async (signal, reason) => {
79
+ // The kill ladder + killed-append are one-shot; whether we got here
80
+ // via `claim()` + `request()` (post-spawn error) or a single
81
+ // `request()` (signal / timeout), only run them once.
82
+ if (killedPromise) {
83
+ await killedPromise.catch(() => undefined);
84
+ return;
85
+ }
86
+ shutdownReason ??= reason;
87
+ requestSignal ??= signal;
88
+ log.write(`[supervisor] shutting down worker (reason=${shutdownReason}, signal=${requestSignal})\n`);
89
+ startKillLadder(getChild());
90
+ killedPromise = writeKilled(shutdownReason, requestSignal);
91
+ await killedPromise;
92
+ };
93
+ const finalizeOnExit = async (code, signal) => {
94
+ log.write(`[supervisor] worker exit code=${code ?? "null"} signal=${signal ?? "null"}\n`);
95
+ // #1 fix: synthesise a terminal event so consumers blocked on
96
+ // `wait --kind done` don't hang when the adapter never produced
97
+ // one. Only applies to COLD exits (no explicit shutdown requested);
98
+ // when shutdown was requested the `killed` event already serves as
99
+ // the terminal signal and a synthesised error would just duplicate.
100
+ //
101
+ // The flag is claimed SYNCHRONOUSLY before the await so two
102
+ // concurrent `finalizeOnExit` calls (or `applyParseResult` racing
103
+ // with `child.on("exit")`) can't both pass the guard and emit
104
+ // duplicate synthetic events. `by` is the worker name (not
105
+ // `supervisor:<name>`) so `wait --from <worker> --kind done` wakes
106
+ // for the synthesised event same as for an adapter-emitted one.
107
+ if (!terminalEmitted && shutdownReason === null) {
108
+ terminalEmitted = true;
109
+ if (code === 0) {
110
+ await appendEvent(channelName, {
111
+ kind: "done",
112
+ by: workerName,
113
+ synthesized: true,
114
+ exit_code: code,
115
+ });
116
+ }
117
+ else {
118
+ await appendEvent(channelName, {
119
+ kind: "error",
120
+ by: workerName,
121
+ message: `worker exited without terminal event (code=${code ?? "null"}, signal=${signal ?? "null"})`,
122
+ synthesized: true,
123
+ exit_code: code,
124
+ exit_signal: signal,
125
+ });
126
+ }
127
+ }
128
+ // #2 fix: wait for any in-progress `killed` append from a concurrent
129
+ // shutdown request so it lands before the supervisor exits.
130
+ if (killedPromise)
131
+ await killedPromise.catch(() => undefined);
132
+ };
133
+ return {
134
+ request,
135
+ claim,
136
+ isShuttingDown: () => shutdownReason !== null,
137
+ reason: () => shutdownReason,
138
+ markTerminalEmitted: () => {
139
+ terminalEmitted = true;
140
+ },
141
+ hasTerminalEvent: () => terminalEmitted,
142
+ finalizeOnExit,
143
+ awaitFinalize: () => killedPromise ?? Promise.resolve(),
144
+ };
145
+ }
146
+ //# sourceMappingURL=shutdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/shutdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * stdout pipeline: line-buffered reader → adapter.parseLine → append
3
+ * events into events.jsonl + persist session/thread IDs + write any
4
+ * adapter `reply` back to the worker's stdin.
5
+ *
6
+ * Step 3 of the supervisor refactor: pulled out of supervisor.ts so the
7
+ * orchestrator stays thin. The pump itself is pure (no fs / process), so
8
+ * unit testing the line-splitting logic is straightforward once we want
9
+ * to. `applyParseResult` still touches fs for session-id persistence —
10
+ * that's intentional, it's the only place that needs to.
11
+ */
12
+ import type { ChildProcessByStdio } from "node:child_process";
13
+ import type { Readable, Writable } from "node:stream";
14
+ import type { WorkerAdapter } from "../adapters/index.js";
15
+ import type { ParseResult } from "../adapters/types.js";
16
+ import type { ShutdownController } from "./shutdown.js";
17
+ import type { TurnTracker } from "./turns.js";
18
+ type Child = ChildProcessByStdio<Writable, Readable, Readable>;
19
+ /**
20
+ * Line-buffered stdout pump. Yields each non-empty line to `onLine` as
21
+ * soon as a newline arrives, wraps the handler in a `.catch` so a thrown
22
+ * await doesn't escape as `unhandledRejection`, and reports the failure
23
+ * through `onError` for observability.
24
+ */
25
+ export declare function pumpStdout(stream: Readable, onLine: (line: string) => Promise<void> | void, onError?: (err: Error) => void): void;
26
+ /**
27
+ * Translate an adapter `ParseResult` into channel events + adapter-level
28
+ * side-effects (session-id persistence, stdin writes). Also tells the
29
+ * shutdown controller when the adapter emits a `done`/`error` so the
30
+ * fallback synthesiser in `finalizeOnExit` doesn't duplicate.
31
+ */
32
+ export declare function applyParseResult(channelName: string, workerName: string, result: ParseResult, child: Child, shutdown: ShutdownController, turnTracker?: TurnTracker): Promise<void>;
33
+ /**
34
+ * Convenience wrapper: wire `pumpStdout` to `applyParseResult` with
35
+ * standard error-event-on-failure handling. The orchestrator just calls
36
+ * this and forgets about line buffering / parse plumbing.
37
+ */
38
+ export declare function startStdoutPump(args: {
39
+ channelName: string;
40
+ workerName: string;
41
+ child: Child;
42
+ adapter: WorkerAdapter;
43
+ adapterCtx: unknown;
44
+ log: {
45
+ write: (data: string) => void;
46
+ };
47
+ shutdown: ShutdownController;
48
+ turnTracker?: TurnTracker;
49
+ }): void;
50
+ export {};
51
+ //# sourceMappingURL=stdout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout.d.ts","sourceRoot":"","sources":["../../../../src/commands/channel/supervisor/stdout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D,KAAK,KAAK,GAAG,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/D;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAC9C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAC7B,IAAI,CAuBN;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,kBAAkB,EAC5B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,IAAI,CAAC,CAqDf;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE;QAAE,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACvC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,GAAG,IAAI,CAkCP"}