agent-tempo 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/CLAUDE.md +213 -0
  2. package/LICENSE +21 -0
  3. package/README.md +289 -0
  4. package/assets/icon-32.png +0 -0
  5. package/assets/icon-512.png +0 -0
  6. package/assets/icon-64.png +0 -0
  7. package/assets/icon-dark-32.png +0 -0
  8. package/assets/icon-dark-64.png +0 -0
  9. package/assets/icon-dark.svg +9 -0
  10. package/assets/icon.svg +9 -0
  11. package/assets/logo-dark.svg +11 -0
  12. package/assets/logo-light.svg +11 -0
  13. package/dashboard/README.md +91 -0
  14. package/dashboard/dist/assets/index-CB78ToNE.css +2 -0
  15. package/dashboard/dist/assets/index-_5jV0Znu.js +62 -0
  16. package/dashboard/dist/assets/index-_5jV0Znu.js.map +1 -0
  17. package/dashboard/dist/index.html +21 -0
  18. package/dashboard/package.json +47 -0
  19. package/dist/activities/hard-terminate.d.ts +32 -0
  20. package/dist/activities/hard-terminate.js +460 -0
  21. package/dist/activities/maestro.d.ts +72 -0
  22. package/dist/activities/maestro.js +254 -0
  23. package/dist/activities/outbox.d.ts +188 -0
  24. package/dist/activities/outbox.js +849 -0
  25. package/dist/activities/resolve.d.ts +64 -0
  26. package/dist/activities/resolve.js +129 -0
  27. package/dist/activities/schedule-fire.d.ts +36 -0
  28. package/dist/activities/schedule-fire.js +147 -0
  29. package/dist/adapters/base.d.ts +426 -0
  30. package/dist/adapters/base.js +1270 -0
  31. package/dist/adapters/claude-api/adapter.d.ts +168 -0
  32. package/dist/adapters/claude-api/adapter.js +797 -0
  33. package/dist/adapters/claude-api/api-error.d.ts +96 -0
  34. package/dist/adapters/claude-api/api-error.js +191 -0
  35. package/dist/adapters/claude-api/index.d.ts +16 -0
  36. package/dist/adapters/claude-api/index.js +21 -0
  37. package/dist/adapters/claude-api/mcp-bridge.d.ts +50 -0
  38. package/dist/adapters/claude-api/mcp-bridge.js +157 -0
  39. package/dist/adapters/claude-code/adapter.d.ts +133 -0
  40. package/dist/adapters/claude-code/adapter.js +274 -0
  41. package/dist/adapters/claude-code/index.d.ts +15 -0
  42. package/dist/adapters/claude-code/index.js +20 -0
  43. package/dist/adapters/claude-code-headless/adapter.d.ts +131 -0
  44. package/dist/adapters/claude-code-headless/adapter.js +710 -0
  45. package/dist/adapters/claude-code-headless/error-mapper.d.ts +107 -0
  46. package/dist/adapters/claude-code-headless/error-mapper.js +281 -0
  47. package/dist/adapters/claude-code-headless/index.d.ts +17 -0
  48. package/dist/adapters/claude-code-headless/index.js +26 -0
  49. package/dist/adapters/claude-code-headless/pre-flight.d.ts +51 -0
  50. package/dist/adapters/claude-code-headless/pre-flight.js +207 -0
  51. package/dist/adapters/claude-code-headless/prompt.d.ts +93 -0
  52. package/dist/adapters/claude-code-headless/prompt.js +79 -0
  53. package/dist/adapters/claude-code-headless/stream-json.d.ts +242 -0
  54. package/dist/adapters/claude-code-headless/stream-json.js +208 -0
  55. package/dist/adapters/claude-code-headless/types.d.ts +28 -0
  56. package/dist/adapters/claude-code-headless/types.js +36 -0
  57. package/dist/adapters/copilot/adapter.d.ts +100 -0
  58. package/dist/adapters/copilot/adapter.js +730 -0
  59. package/dist/adapters/copilot/index.d.ts +15 -0
  60. package/dist/adapters/copilot/index.js +20 -0
  61. package/dist/adapters/index.d.ts +42 -0
  62. package/dist/adapters/index.js +115 -0
  63. package/dist/adapters/opencode/adapter.d.ts +82 -0
  64. package/dist/adapters/opencode/adapter.js +710 -0
  65. package/dist/adapters/opencode/config.d.ts +90 -0
  66. package/dist/adapters/opencode/config.js +137 -0
  67. package/dist/adapters/opencode/helpers.d.ts +40 -0
  68. package/dist/adapters/opencode/helpers.js +144 -0
  69. package/dist/adapters/opencode/index.d.ts +12 -0
  70. package/dist/adapters/opencode/index.js +17 -0
  71. package/dist/adapters/opencode/server-bridge.d.ts +124 -0
  72. package/dist/adapters/opencode/server-bridge.js +216 -0
  73. package/dist/adapters/sdk/base.d.ts +95 -0
  74. package/dist/adapters/sdk/base.js +134 -0
  75. package/dist/adapters/sdk/system-prompt.d.ts +64 -0
  76. package/dist/adapters/sdk/system-prompt.js +78 -0
  77. package/dist/adapters/terminal-error.d.ts +27 -0
  78. package/dist/adapters/terminal-error.js +39 -0
  79. package/dist/channel.d.ts +3 -0
  80. package/dist/channel.js +48 -0
  81. package/dist/cli/commands.d.ts +245 -0
  82. package/dist/cli/commands.js +2438 -0
  83. package/dist/cli/config-command.d.ts +8 -0
  84. package/dist/cli/config-command.js +254 -0
  85. package/dist/cli/daemon-command.d.ts +57 -0
  86. package/dist/cli/daemon-command.js +493 -0
  87. package/dist/cli/daemon.d.ts +217 -0
  88. package/dist/cli/daemon.js +632 -0
  89. package/dist/cli/dashboard-command.d.ts +20 -0
  90. package/dist/cli/dashboard-command.js +241 -0
  91. package/dist/cli/dev-banner.d.ts +107 -0
  92. package/dist/cli/dev-banner.js +190 -0
  93. package/dist/cli/dev-mode-bootstrap.d.ts +29 -0
  94. package/dist/cli/dev-mode-bootstrap.js +36 -0
  95. package/dist/cli/dev-verbs.d.ts +43 -0
  96. package/dist/cli/dev-verbs.js +254 -0
  97. package/dist/cli/help-text.d.ts +1 -0
  98. package/dist/cli/help-text.js +158 -0
  99. package/dist/cli/legacy-migration.d.ts +35 -0
  100. package/dist/cli/legacy-migration.js +335 -0
  101. package/dist/cli/mcp.d.ts +8 -0
  102. package/dist/cli/mcp.js +63 -0
  103. package/dist/cli/output.d.ts +12 -0
  104. package/dist/cli/output.js +37 -0
  105. package/dist/cli/preflight.d.ts +9 -0
  106. package/dist/cli/preflight.js +96 -0
  107. package/dist/cli/removed-verbs.d.ts +9 -0
  108. package/dist/cli/removed-verbs.js +78 -0
  109. package/dist/cli/sa-preflight.d.ts +99 -0
  110. package/dist/cli/sa-preflight.js +183 -0
  111. package/dist/cli/scenarios-command.d.ts +6 -0
  112. package/dist/cli/scenarios-command.js +167 -0
  113. package/dist/cli/startup.d.ts +112 -0
  114. package/dist/cli/startup.js +641 -0
  115. package/dist/cli/upgrade-command.d.ts +5 -0
  116. package/dist/cli/upgrade-command.js +240 -0
  117. package/dist/cli.d.ts +2 -0
  118. package/dist/cli.js +680 -0
  119. package/dist/client/core.d.ts +33 -0
  120. package/dist/client/core.js +1260 -0
  121. package/dist/client/ensure-conductor-spawned.d.ts +35 -0
  122. package/dist/client/ensure-conductor-spawned.js +48 -0
  123. package/dist/client/index.d.ts +32 -0
  124. package/dist/client/index.js +22 -0
  125. package/dist/client/interface.d.ts +461 -0
  126. package/dist/client/interface.js +2 -0
  127. package/dist/client/subscribe.d.ts +108 -0
  128. package/dist/client/subscribe.js +598 -0
  129. package/dist/client/with-spawn.d.ts +27 -0
  130. package/dist/client/with-spawn.js +87 -0
  131. package/dist/config.d.ts +323 -0
  132. package/dist/config.js +593 -0
  133. package/dist/connection.d.ts +7 -0
  134. package/dist/connection.js +46 -0
  135. package/dist/constants.d.ts +50 -0
  136. package/dist/constants.js +74 -0
  137. package/dist/copilot-bridge.d.ts +22 -0
  138. package/dist/copilot-bridge.js +565 -0
  139. package/dist/daemon-adapter-versions.d.ts +52 -0
  140. package/dist/daemon-adapter-versions.js +170 -0
  141. package/dist/daemon.d.ts +275 -0
  142. package/dist/daemon.js +989 -0
  143. package/dist/ensemble/agent-types.d.ts +23 -0
  144. package/dist/ensemble/agent-types.js +132 -0
  145. package/dist/ensemble/loader.d.ts +14 -0
  146. package/dist/ensemble/loader.js +140 -0
  147. package/dist/ensemble/saver.d.ts +49 -0
  148. package/dist/ensemble/saver.js +201 -0
  149. package/dist/ensemble/schema.d.ts +71 -0
  150. package/dist/ensemble/schema.js +3 -0
  151. package/dist/git-info.d.ts +4 -0
  152. package/dist/git-info.js +29 -0
  153. package/dist/http/aggregate.d.ts +319 -0
  154. package/dist/http/aggregate.js +684 -0
  155. package/dist/http/auth.d.ts +67 -0
  156. package/dist/http/auth.js +177 -0
  157. package/dist/http/body.d.ts +71 -0
  158. package/dist/http/body.js +121 -0
  159. package/dist/http/catalog.d.ts +67 -0
  160. package/dist/http/catalog.js +209 -0
  161. package/dist/http/cors.d.ts +42 -0
  162. package/dist/http/cors.js +111 -0
  163. package/dist/http/dashboard-pair.d.ts +94 -0
  164. package/dist/http/dashboard-pair.js +148 -0
  165. package/dist/http/dashboard.d.ts +20 -0
  166. package/dist/http/dashboard.js +160 -0
  167. package/dist/http/event-bus.d.ts +217 -0
  168. package/dist/http/event-bus.js +365 -0
  169. package/dist/http/event-id.d.ts +77 -0
  170. package/dist/http/event-id.js +117 -0
  171. package/dist/http/event-types.d.ts +348 -0
  172. package/dist/http/event-types.js +36 -0
  173. package/dist/http/fixtures/chat-stress.d.ts +8 -0
  174. package/dist/http/fixtures/chat-stress.js +63 -0
  175. package/dist/http/fixtures/conductor-leaving.d.ts +8 -0
  176. package/dist/http/fixtures/conductor-leaving.js +80 -0
  177. package/dist/http/fixtures/constants.d.ts +10 -0
  178. package/dist/http/fixtures/constants.js +13 -0
  179. package/dist/http/fixtures/eight-player-broadcast.d.ts +10 -0
  180. package/dist/http/fixtures/eight-player-broadcast.js +81 -0
  181. package/dist/http/fixtures/empty-ensemble.d.ts +6 -0
  182. package/dist/http/fixtures/empty-ensemble.js +26 -0
  183. package/dist/http/fixtures/index.d.ts +55 -0
  184. package/dist/http/fixtures/index.js +110 -0
  185. package/dist/http/fixtures/single-conductor.d.ts +7 -0
  186. package/dist/http/fixtures/single-conductor.js +46 -0
  187. package/dist/http/fixtures/sse-reconnect.d.ts +8 -0
  188. package/dist/http/fixtures/sse-reconnect.js +77 -0
  189. package/dist/http/index.d.ts +21 -0
  190. package/dist/http/index.js +61 -0
  191. package/dist/http/port-file.d.ts +22 -0
  192. package/dist/http/port-file.js +132 -0
  193. package/dist/http/responses.d.ts +27 -0
  194. package/dist/http/responses.js +40 -0
  195. package/dist/http/ring-buffer.d.ts +41 -0
  196. package/dist/http/ring-buffer.js +80 -0
  197. package/dist/http/server.d.ts +122 -0
  198. package/dist/http/server.js +459 -0
  199. package/dist/http/snapshot.d.ts +85 -0
  200. package/dist/http/snapshot.js +180 -0
  201. package/dist/http/sse-handler.d.ts +87 -0
  202. package/dist/http/sse-handler.js +294 -0
  203. package/dist/http/writes.d.ts +55 -0
  204. package/dist/http/writes.js +240 -0
  205. package/dist/palette/index.d.ts +138 -0
  206. package/dist/palette/index.js +221 -0
  207. package/dist/reconcile/orphans.d.ts +255 -0
  208. package/dist/reconcile/orphans.js +340 -0
  209. package/dist/scripts/258-spotcheck.js +303 -0
  210. package/dist/scripts/check-components-css-sync.js +199 -0
  211. package/dist/scripts/run-shard.js +121 -0
  212. package/dist/scripts/verify-daemon-isolation-guard.js +128 -0
  213. package/dist/server-tools.d.ts +87 -0
  214. package/dist/server-tools.js +146 -0
  215. package/dist/server.d.ts +2 -0
  216. package/dist/server.js +366 -0
  217. package/dist/spawn.d.ts +296 -0
  218. package/dist/spawn.js +747 -0
  219. package/dist/tools/agent-types.d.ts +2 -0
  220. package/dist/tools/agent-types.js +21 -0
  221. package/dist/tools/attachment-info.d.ts +4 -0
  222. package/dist/tools/attachment-info.js +48 -0
  223. package/dist/tools/broadcast.d.ts +4 -0
  224. package/dist/tools/broadcast.js +76 -0
  225. package/dist/tools/cancel-stage.d.ts +3 -0
  226. package/dist/tools/cancel-stage.js +20 -0
  227. package/dist/tools/clear-state.d.ts +3 -0
  228. package/dist/tools/clear-state.js +37 -0
  229. package/dist/tools/coat-check-evict.d.ts +4 -0
  230. package/dist/tools/coat-check-evict.js +43 -0
  231. package/dist/tools/coat-check-get.d.ts +4 -0
  232. package/dist/tools/coat-check-get.js +56 -0
  233. package/dist/tools/coat-check-list.d.ts +4 -0
  234. package/dist/tools/coat-check-list.js +60 -0
  235. package/dist/tools/coat-check-put.d.ts +4 -0
  236. package/dist/tools/coat-check-put.js +53 -0
  237. package/dist/tools/cue.d.ts +44 -0
  238. package/dist/tools/cue.js +201 -0
  239. package/dist/tools/destroy.d.ts +4 -0
  240. package/dist/tools/destroy.js +188 -0
  241. package/dist/tools/detach.d.ts +4 -0
  242. package/dist/tools/detach.js +45 -0
  243. package/dist/tools/encore.d.ts +4 -0
  244. package/dist/tools/encore.js +31 -0
  245. package/dist/tools/ensemble.d.ts +32 -0
  246. package/dist/tools/ensemble.js +198 -0
  247. package/dist/tools/evaluate-gate.d.ts +3 -0
  248. package/dist/tools/evaluate-gate.js +32 -0
  249. package/dist/tools/fetch-state.d.ts +13 -0
  250. package/dist/tools/fetch-state.js +78 -0
  251. package/dist/tools/gates.d.ts +3 -0
  252. package/dist/tools/gates.js +41 -0
  253. package/dist/tools/helpers.d.ts +21 -0
  254. package/dist/tools/helpers.js +25 -0
  255. package/dist/tools/hosts.d.ts +4 -0
  256. package/dist/tools/hosts.js +40 -0
  257. package/dist/tools/listen.d.ts +3 -0
  258. package/dist/tools/listen.js +22 -0
  259. package/dist/tools/load-lineup.d.ts +5 -0
  260. package/dist/tools/load-lineup.js +381 -0
  261. package/dist/tools/migrate.d.ts +4 -0
  262. package/dist/tools/migrate.js +60 -0
  263. package/dist/tools/pause-ensemble.d.ts +4 -0
  264. package/dist/tools/pause-ensemble.js +58 -0
  265. package/dist/tools/pause.d.ts +4 -0
  266. package/dist/tools/pause.js +36 -0
  267. package/dist/tools/play.d.ts +4 -0
  268. package/dist/tools/play.js +57 -0
  269. package/dist/tools/quality-gate.d.ts +3 -0
  270. package/dist/tools/quality-gate.js +26 -0
  271. package/dist/tools/recall.d.ts +3 -0
  272. package/dist/tools/recall.js +32 -0
  273. package/dist/tools/recruit.d.ts +38 -0
  274. package/dist/tools/recruit.js +447 -0
  275. package/dist/tools/release.d.ts +4 -0
  276. package/dist/tools/release.js +98 -0
  277. package/dist/tools/report.d.ts +3 -0
  278. package/dist/tools/report.js +29 -0
  279. package/dist/tools/resolve.d.ts +1 -0
  280. package/dist/tools/resolve.js +7 -0
  281. package/dist/tools/restart.d.ts +35 -0
  282. package/dist/tools/restart.js +131 -0
  283. package/dist/tools/restore.d.ts +4 -0
  284. package/dist/tools/restore.js +107 -0
  285. package/dist/tools/resume-ensemble.d.ts +4 -0
  286. package/dist/tools/resume-ensemble.js +79 -0
  287. package/dist/tools/save-lineup.d.ts +4 -0
  288. package/dist/tools/save-lineup.js +36 -0
  289. package/dist/tools/save-state.d.ts +3 -0
  290. package/dist/tools/save-state.js +57 -0
  291. package/dist/tools/schedule.d.ts +4 -0
  292. package/dist/tools/schedule.js +152 -0
  293. package/dist/tools/schedules.d.ts +4 -0
  294. package/dist/tools/schedules.js +54 -0
  295. package/dist/tools/set-ensemble-description.d.ts +4 -0
  296. package/dist/tools/set-ensemble-description.js +37 -0
  297. package/dist/tools/set-name.d.ts +4 -0
  298. package/dist/tools/set-name.js +45 -0
  299. package/dist/tools/set-part.d.ts +3 -0
  300. package/dist/tools/set-part.js +20 -0
  301. package/dist/tools/shutdown.d.ts +4 -0
  302. package/dist/tools/shutdown.js +54 -0
  303. package/dist/tools/stage.d.ts +3 -0
  304. package/dist/tools/stage.js +28 -0
  305. package/dist/tools/stages.d.ts +3 -0
  306. package/dist/tools/stages.js +35 -0
  307. package/dist/tools/stop.d.ts +4 -0
  308. package/dist/tools/stop.js +29 -0
  309. package/dist/tools/unschedule.d.ts +4 -0
  310. package/dist/tools/unschedule.js +35 -0
  311. package/dist/tools/who-am-i.d.ts +3 -0
  312. package/dist/tools/who-am-i.js +34 -0
  313. package/dist/tools/worktree.d.ts +4 -0
  314. package/dist/tools/worktree.js +181 -0
  315. package/dist/tui/App.d.ts +85 -0
  316. package/dist/tui/App.js +1791 -0
  317. package/dist/tui/bootstrap-types.d.ts +46 -0
  318. package/dist/tui/bootstrap-types.js +7 -0
  319. package/dist/tui/client.d.ts +6 -0
  320. package/dist/tui/client.js +9 -0
  321. package/dist/tui/commands.d.ts +71 -0
  322. package/dist/tui/commands.js +1375 -0
  323. package/dist/tui/components/ActivityLog.d.ts +16 -0
  324. package/dist/tui/components/ActivityLog.js +36 -0
  325. package/dist/tui/components/ChatView.d.ts +35 -0
  326. package/dist/tui/components/ChatView.js +54 -0
  327. package/dist/tui/components/CommandOverlay.d.ts +15 -0
  328. package/dist/tui/components/CommandOverlay.js +34 -0
  329. package/dist/tui/components/CommandPalette.d.ts +21 -0
  330. package/dist/tui/components/CommandPalette.js +67 -0
  331. package/dist/tui/components/ConductorChat.d.ts +16 -0
  332. package/dist/tui/components/ConductorChat.js +32 -0
  333. package/dist/tui/components/ConversationStream.d.ts +114 -0
  334. package/dist/tui/components/ConversationStream.js +307 -0
  335. package/dist/tui/components/CreateEnsembleWizard.d.ts +19 -0
  336. package/dist/tui/components/CreateEnsembleWizard.js +223 -0
  337. package/dist/tui/components/DestroyConfirmModal.d.ts +17 -0
  338. package/dist/tui/components/DestroyConfirmModal.js +62 -0
  339. package/dist/tui/components/EnsembleListView.d.ts +14 -0
  340. package/dist/tui/components/EnsembleListView.js +32 -0
  341. package/dist/tui/components/EnsemblePanel.d.ts +12 -0
  342. package/dist/tui/components/EnsemblePanel.js +40 -0
  343. package/dist/tui/components/ErrorView.d.ts +31 -0
  344. package/dist/tui/components/ErrorView.js +129 -0
  345. package/dist/tui/components/HomeView.d.ts +54 -0
  346. package/dist/tui/components/HomeView.js +306 -0
  347. package/dist/tui/components/InputBar.d.ts +13 -0
  348. package/dist/tui/components/InputBar.js +58 -0
  349. package/dist/tui/components/LoadLineupModal.d.ts +18 -0
  350. package/dist/tui/components/LoadLineupModal.js +79 -0
  351. package/dist/tui/components/MainView.d.ts +21 -0
  352. package/dist/tui/components/MainView.js +107 -0
  353. package/dist/tui/components/NewEnsembleModal.d.ts +9 -0
  354. package/dist/tui/components/NewEnsembleModal.js +73 -0
  355. package/dist/tui/components/Picker.d.ts +23 -0
  356. package/dist/tui/components/Picker.js +70 -0
  357. package/dist/tui/components/PlayerDetailView.d.ts +26 -0
  358. package/dist/tui/components/PlayerDetailView.js +118 -0
  359. package/dist/tui/components/PromptArea.d.ts +50 -0
  360. package/dist/tui/components/PromptArea.js +303 -0
  361. package/dist/tui/components/RecruitWizard.d.ts +17 -0
  362. package/dist/tui/components/RecruitWizard.js +221 -0
  363. package/dist/tui/components/RestoreConfirmModal.d.ts +18 -0
  364. package/dist/tui/components/RestoreConfirmModal.js +71 -0
  365. package/dist/tui/components/ScheduleOverlay.d.ts +13 -0
  366. package/dist/tui/components/ScheduleOverlay.js +113 -0
  367. package/dist/tui/components/ScheduleWizard.d.ts +19 -0
  368. package/dist/tui/components/ScheduleWizard.js +259 -0
  369. package/dist/tui/components/Splash.d.ts +23 -0
  370. package/dist/tui/components/Splash.js +221 -0
  371. package/dist/tui/components/StatusBar.d.ts +48 -0
  372. package/dist/tui/components/StatusBar.js +128 -0
  373. package/dist/tui/components/StatusOverlay.d.ts +15 -0
  374. package/dist/tui/components/StatusOverlay.js +76 -0
  375. package/dist/tui/components/TitleBar.d.ts +10 -0
  376. package/dist/tui/components/TitleBar.js +21 -0
  377. package/dist/tui/components/TopBar.d.ts +12 -0
  378. package/dist/tui/components/TopBar.js +15 -0
  379. package/dist/tui/core-api.d.ts +26 -0
  380. package/dist/tui/core-api.js +67 -0
  381. package/dist/tui/hooks/useEnsembleDiscovery.d.ts +3 -0
  382. package/dist/tui/hooks/useEnsembleDiscovery.js +30 -0
  383. package/dist/tui/hooks/useMaestroPoller.d.ts +3 -0
  384. package/dist/tui/hooks/useMaestroPoller.js +36 -0
  385. package/dist/tui/hooks/useSendCommand.d.ts +7 -0
  386. package/dist/tui/hooks/useSendCommand.js +29 -0
  387. package/dist/tui/index.d.ts +15 -0
  388. package/dist/tui/index.js +156 -0
  389. package/dist/tui/ink-context.d.ts +18 -0
  390. package/dist/tui/ink-context.js +59 -0
  391. package/dist/tui/ink-loader.d.ts +26 -0
  392. package/dist/tui/ink-loader.js +42 -0
  393. package/dist/tui/removed-commands.d.ts +9 -0
  394. package/dist/tui/removed-commands.js +22 -0
  395. package/dist/tui/sse-handler.d.ts +52 -0
  396. package/dist/tui/sse-handler.js +157 -0
  397. package/dist/tui/store.d.ts +598 -0
  398. package/dist/tui/store.js +753 -0
  399. package/dist/tui/utils/format.d.ts +56 -0
  400. package/dist/tui/utils/format.js +155 -0
  401. package/dist/tui/utils/fullscreen.d.ts +23 -0
  402. package/dist/tui/utils/fullscreen.js +71 -0
  403. package/dist/tui/utils/history.d.ts +10 -0
  404. package/dist/tui/utils/history.js +85 -0
  405. package/dist/tui/utils/platform.d.ts +45 -0
  406. package/dist/tui/utils/platform.js +258 -0
  407. package/dist/tui/utils/theme.d.ts +21 -0
  408. package/dist/tui/utils/theme.js +24 -0
  409. package/dist/types.d.ts +1020 -0
  410. package/dist/types.js +39 -0
  411. package/dist/utils/attachment-format.d.ts +22 -0
  412. package/dist/utils/attachment-format.js +32 -0
  413. package/dist/utils/default-part.d.ts +43 -0
  414. package/dist/utils/default-part.js +104 -0
  415. package/dist/utils/duration.d.ts +30 -0
  416. package/dist/utils/duration.js +69 -0
  417. package/dist/utils/ensemble-ops.d.ts +61 -0
  418. package/dist/utils/ensemble-ops.js +77 -0
  419. package/dist/utils/format-hosts.d.ts +21 -0
  420. package/dist/utils/format-hosts.js +73 -0
  421. package/dist/utils/hosts.d.ts +113 -0
  422. package/dist/utils/hosts.js +265 -0
  423. package/dist/utils/parent-death-watchdog.d.ts +1 -0
  424. package/dist/utils/parent-death-watchdog.js +47 -0
  425. package/dist/utils/query-timeout.d.ts +103 -0
  426. package/dist/utils/query-timeout.js +113 -0
  427. package/dist/utils/recall-format.d.ts +78 -0
  428. package/dist/utils/recall-format.js +105 -0
  429. package/dist/utils/restore-format.d.ts +49 -0
  430. package/dist/utils/restore-format.js +91 -0
  431. package/dist/utils/safe-path.d.ts +10 -0
  432. package/dist/utils/safe-path.js +43 -0
  433. package/dist/utils/sdk-probe.d.ts +9 -0
  434. package/dist/utils/sdk-probe.js +45 -0
  435. package/dist/utils/search-attributes.d.ts +76 -0
  436. package/dist/utils/search-attributes.js +86 -0
  437. package/dist/utils/validation.d.ts +113 -0
  438. package/dist/utils/validation.js +163 -0
  439. package/dist/utils/visibility-deadline.d.ts +186 -0
  440. package/dist/utils/visibility-deadline.js +158 -0
  441. package/dist/utils/worktree.d.ts +103 -0
  442. package/dist/utils/worktree.js +327 -0
  443. package/dist/worker.d.ts +14 -0
  444. package/dist/worker.js +146 -0
  445. package/dist/workflows/attachment-math.d.ts +56 -0
  446. package/dist/workflows/attachment-math.js +47 -0
  447. package/dist/workflows/index.d.ts +3 -0
  448. package/dist/workflows/index.js +11 -0
  449. package/dist/workflows/maestro-signals.d.ts +217 -0
  450. package/dist/workflows/maestro-signals.js +155 -0
  451. package/dist/workflows/maestro.d.ts +3 -0
  452. package/dist/workflows/maestro.js +812 -0
  453. package/dist/workflows/scheduler-signals.d.ts +10 -0
  454. package/dist/workflows/scheduler-signals.js +14 -0
  455. package/dist/workflows/scheduler.d.ts +17 -0
  456. package/dist/workflows/scheduler.js +143 -0
  457. package/dist/workflows/session.d.ts +2 -0
  458. package/dist/workflows/session.js +1638 -0
  459. package/dist/workflows/signals.d.ts +297 -0
  460. package/dist/workflows/signals.js +239 -0
  461. package/examples/agents/tempo-composer.md +56 -0
  462. package/examples/agents/tempo-conductor.md +117 -0
  463. package/examples/agents/tempo-critic.md +73 -0
  464. package/examples/agents/tempo-improv.md +74 -0
  465. package/examples/agents/tempo-liner.md +75 -0
  466. package/examples/agents/tempo-roadie.md +61 -0
  467. package/examples/agents/tempo-soloist.md +71 -0
  468. package/examples/agents/tempo-tuner.md +94 -0
  469. package/examples/ensembles/tempo-big-band.yaml +146 -0
  470. package/examples/ensembles/tempo-dev-team.yaml +58 -0
  471. package/examples/ensembles/tempo-headless-jam.yaml +77 -0
  472. package/examples/ensembles/tempo-jam-session.yaml +41 -0
  473. package/examples/ensembles/tempo-mock-jam.yaml +79 -0
  474. package/examples/ensembles/tempo-review-squad.yaml +32 -0
  475. package/package.json +172 -0
  476. package/packaging/launchd/com.agent.tempo.plist +46 -0
  477. package/packaging/systemd/agent-tempo.service +32 -0
  478. package/packaging/windows/install-task.ps1 +71 -0
  479. package/scenarios/conductor-recruit-mock.yaml +33 -0
  480. package/scenarios/echo-roundtrip.yaml +15 -0
  481. package/scenarios/multi-player-handoff.yaml +38 -0
  482. package/scenarios/recruit-cascade.yaml +38 -0
  483. package/scenarios/two-player-conversation.yaml +33 -0
  484. package/workflow-bundle.js +14146 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Compute the base directory for all worktrees in an ensemble.
3
+ * Convention: `{gitRoot}/../.ct-worktrees/{ensemble}/`
4
+ */
5
+ export declare function worktreeBasePath(gitRoot: string, ensemble: string): string;
6
+ export interface CreateWorktreeOpts {
7
+ gitRoot: string;
8
+ ensemble: string;
9
+ playerName: string;
10
+ branch?: string;
11
+ }
12
+ /**
13
+ * Tag returned by {@link switchWorktreeToBranch} and surfaced on
14
+ * {@link CreateWorktreeResult.switched} so the MCP tool's response text can
15
+ * report the actual state transition instead of silently reusing the request
16
+ * as ground truth (#261). Values:
17
+ *
18
+ * - `same` — the worktree was already on the requested branch. No-op.
19
+ * - `switched` — the requested branch existed locally; plain `git checkout`.
20
+ * - `created-from-main` — the requested branch did not exist locally;
21
+ * created it off `origin/main` via `git checkout -b`.
22
+ */
23
+ export type WorktreeSwitchResult = 'same' | 'switched' | 'created-from-main';
24
+ export interface CreateWorktreeResult {
25
+ /** Absolute path to the worktree directory. */
26
+ path: string;
27
+ /** Branch name used for the worktree. */
28
+ branch: string;
29
+ /** Whether the worktree was newly created (false if it already existed). */
30
+ created: boolean;
31
+ /**
32
+ * When `created === false` (reuse path), which git operation the helper ran
33
+ * to bring the worktree onto the requested branch. `undefined` on fresh
34
+ * creation — the #261 information is only meaningful for reuse.
35
+ */
36
+ switched?: WorktreeSwitchResult;
37
+ }
38
+ /**
39
+ * Ensure the worktree at `wtPath` is checked out on `targetBranch`.
40
+ *
41
+ * Fix for #261: the prior reuse path returned the *requested* branch name in
42
+ * its result without ever consulting the worktree's actual HEAD, silently
43
+ * papering over mismatches when a worktree from a prior task was recycled for
44
+ * a new branch. This helper does the repointing that was missing — and
45
+ * refuses (rather than silently discarding) if the target worktree has
46
+ * uncommitted work on a different branch.
47
+ *
48
+ * Decision tree (mirrors the conductor's guidance on #261):
49
+ * 1. current branch === targetBranch → no-op, return `'same'`. The
50
+ * hot path. Deliberately does NOT run `status --porcelain`: if we're
51
+ * not flipping the branch, dirty work is fine.
52
+ * 2. `git status --porcelain` non-empty → throw `"uncommitted changes"`
53
+ * with path + current branch. Must precede any checkout so we never
54
+ * silently discard work on a branch flip.
55
+ * 3. target branch exists locally → `git checkout <target>`.
56
+ * Preserves the branch's recorded state; no `-B`, no force-reset.
57
+ * 4. target branch does not exist locally → `git checkout -b <target> origin/main`.
58
+ * Matches the semantics of the fresh-worktree `git worktree add -B`
59
+ * path — new branch rooted at the current main tip.
60
+ *
61
+ * Caller is expected to have already verified `wtPath` is an existing git
62
+ * worktree (this helper runs the git commands with `-C <wtPath>` and does no
63
+ * path-existence checks of its own).
64
+ */
65
+ export declare function switchWorktreeToBranch(wtPath: string, targetBranch: string): WorktreeSwitchResult;
66
+ /**
67
+ * Create a git worktree for a player. If the worktree already exists
68
+ * at the expected path, returns it after repointing to the requested branch
69
+ * via {@link switchWorktreeToBranch} — the fix for #261, which previously
70
+ * reused the directory without ever consulting its actual HEAD.
71
+ *
72
+ * Branch defaults to `{ensemble}/{playerName}` if not specified.
73
+ */
74
+ export declare function createWorktree(opts: CreateWorktreeOpts): CreateWorktreeResult;
75
+ /**
76
+ * Install dependencies in a worktree directory.
77
+ *
78
+ * Detects the package manager (npm, yarn, pnpm) by lockfile presence.
79
+ * Failure or timeout is logged but does not throw — the recruit proceeds
80
+ * with whatever state the worktree is in.
81
+ */
82
+ export declare function installDependencies(worktreePath: string, timeoutMs?: number): void;
83
+ /**
84
+ * Remove a git worktree.
85
+ *
86
+ * Throws if the worktree directory survives the removal (#594). On Windows,
87
+ * `git worktree remove --force` deletes `.git/worktrees/<name>` metadata
88
+ * *first*, then `rmdir`s the directory — so when a native `.node` module
89
+ * inside the worktree is memory-mapped by a live process, the directory
90
+ * deletion fails while the metadata is already gone. The pre-#594 code
91
+ * swallowed that failure (log-only, no throw), so the caller reported
92
+ * success and Temporal state diverged from disk. Now the post-removal
93
+ * `existsSync` check turns a half-removal into a hard error the caller can
94
+ * surface.
95
+ *
96
+ * `gitRoot` scopes the `git worktree remove` invocation to the owning
97
+ * repository. Pre-#594 the command ran with no `cwd`, so it only worked when
98
+ * `process.cwd()` happened to be the right repo — fragile, and wrong outright
99
+ * when the conductor's cwd is a different checkout than the worktree's repo.
100
+ * Callers should pass `entry.gitRoot` from the `WorktreeEntry`; it defaults to
101
+ * `process.cwd()` for backward compatibility.
102
+ */
103
+ export declare function removeWorktree(worktreePath: string, gitRoot?: string): void;
@@ -0,0 +1,327 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.worktreeBasePath = worktreeBasePath;
37
+ exports.switchWorktreeToBranch = switchWorktreeToBranch;
38
+ exports.createWorktree = createWorktree;
39
+ exports.installDependencies = installDependencies;
40
+ exports.removeWorktree = removeWorktree;
41
+ /**
42
+ * Git worktree helpers for player isolation.
43
+ *
44
+ * Creates and manages git worktrees so each player can work on an
45
+ * isolated copy of the repository without conflicting with others.
46
+ */
47
+ const child_process_1 = require("child_process");
48
+ const fs_1 = require("fs");
49
+ const path = __importStar(require("path"));
50
+ const validation_1 = require("./validation");
51
+ const log = (...args) => console.error('[agent-tempo:worktree]', ...args);
52
+ /**
53
+ * Compute the base directory for all worktrees in an ensemble.
54
+ * Convention: `{gitRoot}/../.ct-worktrees/{ensemble}/`
55
+ */
56
+ function worktreeBasePath(gitRoot, ensemble) {
57
+ return path.join(path.dirname(gitRoot), '.ct-worktrees', ensemble);
58
+ }
59
+ /**
60
+ * Ensure the worktree at `wtPath` is checked out on `targetBranch`.
61
+ *
62
+ * Fix for #261: the prior reuse path returned the *requested* branch name in
63
+ * its result without ever consulting the worktree's actual HEAD, silently
64
+ * papering over mismatches when a worktree from a prior task was recycled for
65
+ * a new branch. This helper does the repointing that was missing — and
66
+ * refuses (rather than silently discarding) if the target worktree has
67
+ * uncommitted work on a different branch.
68
+ *
69
+ * Decision tree (mirrors the conductor's guidance on #261):
70
+ * 1. current branch === targetBranch → no-op, return `'same'`. The
71
+ * hot path. Deliberately does NOT run `status --porcelain`: if we're
72
+ * not flipping the branch, dirty work is fine.
73
+ * 2. `git status --porcelain` non-empty → throw `"uncommitted changes"`
74
+ * with path + current branch. Must precede any checkout so we never
75
+ * silently discard work on a branch flip.
76
+ * 3. target branch exists locally → `git checkout <target>`.
77
+ * Preserves the branch's recorded state; no `-B`, no force-reset.
78
+ * 4. target branch does not exist locally → `git checkout -b <target> origin/main`.
79
+ * Matches the semantics of the fresh-worktree `git worktree add -B`
80
+ * path — new branch rooted at the current main tip.
81
+ *
82
+ * Caller is expected to have already verified `wtPath` is an existing git
83
+ * worktree (this helper runs the git commands with `-C <wtPath>` and does no
84
+ * path-existence checks of its own).
85
+ */
86
+ function switchWorktreeToBranch(wtPath, targetBranch) {
87
+ const current = (0, child_process_1.execFileSync)('git', ['-C', wtPath, 'branch', '--show-current'], {
88
+ encoding: 'utf8',
89
+ stdio: ['pipe', 'pipe', 'pipe'],
90
+ }).trim();
91
+ if (current === targetBranch) {
92
+ log(`Worktree at "${wtPath}" already on "${targetBranch}" — no-op`);
93
+ return 'same';
94
+ }
95
+ // Branch mismatch → dirty-tree guard before any checkout. `--porcelain`
96
+ // emits one line per change with no color/decoration; empty output means
97
+ // the working tree + index are clean (ignored files don't count).
98
+ const dirty = (0, child_process_1.execFileSync)('git', ['-C', wtPath, 'status', '--porcelain'], {
99
+ encoding: 'utf8',
100
+ stdio: ['pipe', 'pipe', 'pipe'],
101
+ });
102
+ if (dirty.trim().length > 0) {
103
+ throw new Error(`Worktree at "${wtPath}" has uncommitted changes on branch "${current}"; ` +
104
+ `cannot repoint to "${targetBranch}". Commit or discard changes first.`);
105
+ }
106
+ // Does the target branch already exist locally? `rev-parse --verify` exits
107
+ // 0 on hit, non-zero on miss.
108
+ let branchExistsLocally = false;
109
+ try {
110
+ (0, child_process_1.execFileSync)('git', ['-C', wtPath, 'rev-parse', '--verify', `refs/heads/${targetBranch}`], {
111
+ encoding: 'utf8',
112
+ stdio: ['pipe', 'pipe', 'pipe'],
113
+ });
114
+ branchExistsLocally = true;
115
+ }
116
+ catch {
117
+ // refs/heads/<target> doesn't exist — fall through to create-from-main.
118
+ }
119
+ if (branchExistsLocally) {
120
+ log(`Worktree at "${wtPath}" switching "${current}" → "${targetBranch}" (existing local branch)`);
121
+ try {
122
+ (0, child_process_1.execFileSync)('git', ['-C', wtPath, 'checkout', targetBranch], {
123
+ encoding: 'utf8',
124
+ stdio: ['pipe', 'pipe', 'pipe'],
125
+ });
126
+ }
127
+ catch (err) {
128
+ const msg = err.stderr || err.stdout || err.message || String(err);
129
+ throw new Error(`Failed to switch "${wtPath}" to "${targetBranch}": ${msg.trim()}`);
130
+ }
131
+ return 'switched';
132
+ }
133
+ log(`Worktree at "${wtPath}" switching "${current}" → "${targetBranch}" (new local branch from origin/main)`);
134
+ try {
135
+ (0, child_process_1.execFileSync)('git', ['-C', wtPath, 'checkout', '-b', targetBranch, 'origin/main'], {
136
+ encoding: 'utf8',
137
+ stdio: ['pipe', 'pipe', 'pipe'],
138
+ });
139
+ }
140
+ catch (err) {
141
+ const msg = err.stderr || err.stdout || err.message || String(err);
142
+ throw new Error(`Failed to create "${targetBranch}" from origin/main in "${wtPath}": ${msg.trim()}`);
143
+ }
144
+ return 'created-from-main';
145
+ }
146
+ /**
147
+ * Create a git worktree for a player. If the worktree already exists
148
+ * at the expected path, returns it after repointing to the requested branch
149
+ * via {@link switchWorktreeToBranch} — the fix for #261, which previously
150
+ * reused the directory without ever consulting its actual HEAD.
151
+ *
152
+ * Branch defaults to `{ensemble}/{playerName}` if not specified.
153
+ */
154
+ function createWorktree(opts) {
155
+ const { gitRoot, ensemble, playerName } = opts;
156
+ const branch = opts.branch || `${ensemble}/${playerName}`;
157
+ const basePath = worktreeBasePath(gitRoot, ensemble);
158
+ const wtPath = path.join(basePath, playerName);
159
+ // If worktree already exists, reuse it — but verify its HEAD matches the
160
+ // requested branch (repoint if not). This is the #261 fix: the previous
161
+ // early-return trusted `branch` from the request as ground truth, so a
162
+ // worktree left on a prior task's branch would be silently misreported.
163
+ if ((0, fs_1.existsSync)(path.join(wtPath, '.git'))) {
164
+ log(`Worktree already exists at "${wtPath}" — reusing, verifying branch`);
165
+ const switched = switchWorktreeToBranch(wtPath, branch);
166
+ return { path: wtPath, branch, created: false, switched };
167
+ }
168
+ // #594 defect 2: stale-orphan recovery. A half-removed worktree leaves the
169
+ // directory on disk with its `.git` file already deleted (`git worktree
170
+ // remove` deletes metadata before the rmdir, which then fails under a
171
+ // Windows file lock). The reuse guard above keys on `.git` presence, so it
172
+ // is skipped — and `git worktree add` below refuses a non-empty pre-existing
173
+ // directory with a confusing `fatal: '...' already exists`. Detect the
174
+ // orphan and clear it first, with a clear error if the lock is still held.
175
+ if ((0, fs_1.existsSync)(wtPath)) {
176
+ log(`Stale worktree directory at "${wtPath}" (no \`.git\`) — attempting cleanup`);
177
+ try {
178
+ (0, fs_1.rmSync)(wtPath, { recursive: true, force: true });
179
+ }
180
+ catch (err) {
181
+ // Swallow — the existsSync re-check below is the authoritative gate.
182
+ log(`Warning: \`rmSync\` on stale worktree "${wtPath}" failed: ${err?.message ?? err}`);
183
+ }
184
+ if ((0, fs_1.existsSync)(wtPath)) {
185
+ throw new Error(`Stale worktree directory at "${wtPath}" could not be removed — kill any ` +
186
+ `processes running inside it (e.g. a dev server) and retry. On Windows, ` +
187
+ `memory-mapped native \`.node\` modules hold the lock until the owning ` +
188
+ `process exits.`);
189
+ }
190
+ // Directory cleared — prune any dangling git metadata so `git worktree add`
191
+ // doesn't trip over a stale registration for the same path/branch.
192
+ try {
193
+ (0, child_process_1.execFileSync)('git', ['worktree', 'prune'], {
194
+ cwd: gitRoot,
195
+ encoding: 'utf8',
196
+ stdio: ['pipe', 'pipe', 'pipe'],
197
+ });
198
+ }
199
+ catch {
200
+ // Best-effort — prune failure is non-fatal; the add below will surface
201
+ // any real conflict.
202
+ }
203
+ }
204
+ // Ensure base directory exists
205
+ (0, fs_1.mkdirSync)(basePath, { recursive: true });
206
+ // Check if the branch already has a worktree (would cause git error)
207
+ try {
208
+ const existing = (0, child_process_1.execFileSync)('git', ['worktree', 'list', '--porcelain'], {
209
+ cwd: gitRoot,
210
+ encoding: 'utf8',
211
+ stdio: ['pipe', 'pipe', 'pipe'],
212
+ });
213
+ // Parse porcelain output: "branch refs/heads/{branch}" lines
214
+ const branchRef = `refs/heads/${branch}`;
215
+ if (existing.includes(`branch ${branchRef}`)) {
216
+ throw new Error(`Branch "${branch}" already has an active worktree. ` +
217
+ `Remove it first with \`git worktree remove\` or choose a different branch.`);
218
+ }
219
+ }
220
+ catch (err) {
221
+ // Re-throw our own error, swallow git failures (e.g., no worktrees yet)
222
+ if (err.message?.includes('already has an active worktree'))
223
+ throw err;
224
+ }
225
+ // Create the worktree. Use -B to create/reset the branch.
226
+ try {
227
+ log(`Creating worktree: git worktree add -B ${branch} ${wtPath}`);
228
+ (0, child_process_1.execFileSync)('git', ['worktree', 'add', '-B', branch, wtPath], {
229
+ cwd: gitRoot,
230
+ encoding: 'utf8',
231
+ stdio: ['pipe', 'pipe', 'pipe'],
232
+ });
233
+ }
234
+ catch (err) {
235
+ const msg = err.stderr || err.stdout || err.message || String(err);
236
+ throw new Error(`Failed to create worktree at "${wtPath}": ${msg.trim()}`);
237
+ }
238
+ return { path: wtPath, branch, created: true };
239
+ }
240
+ /**
241
+ * Install dependencies in a worktree directory.
242
+ *
243
+ * Detects the package manager (npm, yarn, pnpm) by lockfile presence.
244
+ * Failure or timeout is logged but does not throw — the recruit proceeds
245
+ * with whatever state the worktree is in.
246
+ */
247
+ function installDependencies(worktreePath, timeoutMs = validation_1.WORKTREE_INSTALL_TIMEOUT) {
248
+ // Detect package manager by lockfile
249
+ let cmd;
250
+ let args;
251
+ if ((0, fs_1.existsSync)(path.join(worktreePath, 'pnpm-lock.yaml'))) {
252
+ cmd = 'pnpm';
253
+ args = ['install', '--frozen-lockfile'];
254
+ }
255
+ else if ((0, fs_1.existsSync)(path.join(worktreePath, 'yarn.lock'))) {
256
+ cmd = 'yarn';
257
+ args = ['install', '--frozen-lockfile'];
258
+ }
259
+ else if ((0, fs_1.existsSync)(path.join(worktreePath, 'package-lock.json')) || (0, fs_1.existsSync)(path.join(worktreePath, 'package.json'))) {
260
+ cmd = 'npm';
261
+ args = ['install'];
262
+ }
263
+ else {
264
+ log(`No package.json found in "${worktreePath}" — skipping install`);
265
+ return;
266
+ }
267
+ try {
268
+ log(`Installing dependencies in "${worktreePath}": ${cmd} ${args.join(' ')}`);
269
+ (0, child_process_1.execFileSync)(cmd, args, {
270
+ cwd: worktreePath,
271
+ encoding: 'utf8',
272
+ timeout: timeoutMs,
273
+ stdio: ['pipe', 'pipe', 'pipe'],
274
+ });
275
+ log(`Dependencies installed successfully in "${worktreePath}"`);
276
+ }
277
+ catch (err) {
278
+ // Log warning but don't throw — recruit should still proceed
279
+ const msg = err.killed ? `Timed out after ${timeoutMs}ms` : (err.stderr || err.message || String(err));
280
+ log(`Warning: dependency install failed in "${worktreePath}": ${msg}`);
281
+ }
282
+ }
283
+ /**
284
+ * Remove a git worktree.
285
+ *
286
+ * Throws if the worktree directory survives the removal (#594). On Windows,
287
+ * `git worktree remove --force` deletes `.git/worktrees/<name>` metadata
288
+ * *first*, then `rmdir`s the directory — so when a native `.node` module
289
+ * inside the worktree is memory-mapped by a live process, the directory
290
+ * deletion fails while the metadata is already gone. The pre-#594 code
291
+ * swallowed that failure (log-only, no throw), so the caller reported
292
+ * success and Temporal state diverged from disk. Now the post-removal
293
+ * `existsSync` check turns a half-removal into a hard error the caller can
294
+ * surface.
295
+ *
296
+ * `gitRoot` scopes the `git worktree remove` invocation to the owning
297
+ * repository. Pre-#594 the command ran with no `cwd`, so it only worked when
298
+ * `process.cwd()` happened to be the right repo — fragile, and wrong outright
299
+ * when the conductor's cwd is a different checkout than the worktree's repo.
300
+ * Callers should pass `entry.gitRoot` from the `WorktreeEntry`; it defaults to
301
+ * `process.cwd()` for backward compatibility.
302
+ */
303
+ function removeWorktree(worktreePath, gitRoot = process.cwd()) {
304
+ try {
305
+ (0, child_process_1.execFileSync)('git', ['worktree', 'remove', '--force', worktreePath], {
306
+ cwd: gitRoot,
307
+ encoding: 'utf8',
308
+ stdio: ['pipe', 'pipe', 'pipe'],
309
+ });
310
+ }
311
+ catch (err) {
312
+ const msg = err.stderr || err.message || String(err);
313
+ log(`Warning: \`git worktree remove\` failed at "${worktreePath}": ${msg.trim()}`);
314
+ // Don't return here — fall through to the post-removal check. git may have
315
+ // deleted the metadata but failed the rmdir; the existsSync gate below is
316
+ // the real success criterion.
317
+ }
318
+ // #594 defect 1: post-removal verification. If the directory is still on
319
+ // disk, the removal half-succeeded — surface it instead of returning void.
320
+ if ((0, fs_1.existsSync)(worktreePath)) {
321
+ throw new Error(`Worktree directory "${worktreePath}" still exists after \`git worktree remove\`. ` +
322
+ `On Windows this usually means a process is holding a file lock — e.g. a dev ` +
323
+ `server with a memory-mapped native \`.node\` module. Stop any processes running ` +
324
+ `inside the worktree and retry.`);
325
+ }
326
+ log(`Removed worktree at "${worktreePath}"`);
327
+ }
@@ -0,0 +1,14 @@
1
+ import { Worker } from '@temporalio/worker';
2
+ import { Config } from './config';
3
+ export interface DualWorkers {
4
+ /** Shared queue worker: workflows + delivery activities + schedule activities */
5
+ sharedWorker: Worker;
6
+ /** Per-host queue worker: spawnProcess activity only */
7
+ hostWorker: Worker;
8
+ }
9
+ /**
10
+ * Create dual workers:
11
+ * - Shared queue: workflows + all delivery activities (deliverCue, deliverReport, terminateSession, startRecruitedSession) + schedule activities
12
+ * - Per-host queue: spawnProcess only (routes recruit spawns to the correct machine)
13
+ */
14
+ export declare function createWorkers(config: Config): Promise<DualWorkers>;
package/dist/worker.js ADDED
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createWorkers = createWorkers;
37
+ const path = __importStar(require("path"));
38
+ const os = __importStar(require("os"));
39
+ const fs = __importStar(require("fs"));
40
+ const worker_1 = require("@temporalio/worker");
41
+ const client_1 = require("@temporalio/client");
42
+ const config_1 = require("./config");
43
+ const connection_1 = require("./connection");
44
+ const connection_2 = require("./connection");
45
+ const schedule_fire_1 = require("./activities/schedule-fire");
46
+ const outbox_1 = require("./activities/outbox");
47
+ const maestro_1 = require("./activities/maestro");
48
+ const log = (...args) => console.error('[agent-tempo:worker]', ...args);
49
+ const BUNDLE_PATH = path.resolve(__dirname, '..', 'workflow-bundle.js');
50
+ /**
51
+ * #274 — deliberately set worker identity so host-discovery (`listHosts` in
52
+ * `src/utils/hosts.ts`) can parse pollers back into `hostname:pid:version`
53
+ * tuples without guessing at the SDK default (`<pid>@<hostname>`, which
54
+ * loses the version axis and is only informally guaranteed).
55
+ *
56
+ * Format: `agent-tempo:<hostname>:<pid>:<version>`. Colons are safe
57
+ * because the middle segments have their own validation:
58
+ * - hostname passes `PLAYER_NAME_REGEX` on the signal side (≤64 chars,
59
+ * no colons by construction on any platform the daemon supports)
60
+ * - pid is numeric
61
+ * - version is a semver-ish string (no colons)
62
+ *
63
+ * Legacy identities (`<pid>@<hostname>`) from pre-#274 daemons remain
64
+ * parseable at the join site — see `parseIdentity` in
65
+ * `src/utils/hosts.ts` for the dual-format tolerance.
66
+ */
67
+ function workerIdentity() {
68
+ // Lazy-require so the test build (which compiles worker.ts into
69
+ // `dist-test/src/` where `../package.json` doesn't resolve) doesn't
70
+ // throw MODULE_NOT_FOUND at module-load time when daemon tests
71
+ // transitively import this file. `createWorkers` is only called from
72
+ // production code paths, so this runs against the real `dist/`
73
+ // layout where `../package.json` is the repo root.
74
+ const { version } = require('../package.json');
75
+ return `agent-tempo:${os.hostname()}:${process.pid}:${version}`;
76
+ }
77
+ async function getWorkflowBundle() {
78
+ // Use pre-built bundle if it exists, otherwise bundle from source
79
+ if (fs.existsSync(BUNDLE_PATH)) {
80
+ log(`Loading pre-built workflow bundle from ${BUNDLE_PATH}`);
81
+ return { code: fs.readFileSync(BUNDLE_PATH, 'utf-8') };
82
+ }
83
+ log('No pre-built workflow bundle found — bundling from source (run `npm run build` to avoid this)');
84
+ const bundle = await (0, worker_1.bundleWorkflowCode)({
85
+ workflowsPath: path.resolve(__dirname, 'workflows', 'index'),
86
+ });
87
+ // Cache for subsequent workers
88
+ fs.writeFileSync(BUNDLE_PATH, bundle.code);
89
+ return bundle;
90
+ }
91
+ /**
92
+ * Create dual workers:
93
+ * - Shared queue: workflows + all delivery activities (deliverCue, deliverReport, terminateSession, startRecruitedSession) + schedule activities
94
+ * - Per-host queue: spawnProcess only (routes recruit spawns to the correct machine)
95
+ */
96
+ async function createWorkers(config) {
97
+ const connection = await (0, connection_1.createTemporalNativeConnection)(config);
98
+ // Create a Client connection for activities that need to interact with Temporal
99
+ const clientConnection = await (0, connection_2.createTemporalConnection)(config);
100
+ const client = new client_1.Client({ connection: clientConnection, namespace: config.temporalNamespace });
101
+ const scheduleActivities = (0, schedule_fire_1.createScheduleActivities)(client);
102
+ const outboxActivities = (0, outbox_1.createOutboxActivities)(client, config);
103
+ const maestroActivities = (0, maestro_1.createMaestroActivities)(client);
104
+ const workflowBundle = await getWorkflowBundle();
105
+ const SHUTDOWN_GRACE_TIME = '10s';
106
+ const SHUTDOWN_FORCE_TIME = '15s';
107
+ const sharedWorker = await worker_1.Worker.create({
108
+ connection,
109
+ namespace: config.temporalNamespace,
110
+ taskQueue: config.taskQueue,
111
+ identity: workerIdentity(), // #274 — parseable agent-tempo:<host>:<pid>:<version>
112
+ workflowBundle,
113
+ shutdownGraceTime: SHUTDOWN_GRACE_TIME,
114
+ shutdownForceTime: SHUTDOWN_FORCE_TIME,
115
+ activities: {
116
+ ...scheduleActivities,
117
+ ...maestroActivities,
118
+ // Shared-queue delivery activities (everything except spawnProcess)
119
+ deliverCue: outboxActivities.deliverCue,
120
+ deliverReport: outboxActivities.deliverReport,
121
+ terminateSession: outboxActivities.terminateSession,
122
+ startRecruitedSession: outboxActivities.startRecruitedSession,
123
+ releasePlayer: outboxActivities.releasePlayer,
124
+ deliverDetach: outboxActivities.deliverDetach,
125
+ deliverDestroy: outboxActivities.deliverDestroy,
126
+ deliverRestart: outboxActivities.deliverRestart,
127
+ },
128
+ });
129
+ // Per-host worker — spawnProcess only, no workflow bundle
130
+ const hostConnection = await (0, connection_1.createTemporalNativeConnection)(config);
131
+ const hostWorker = await worker_1.Worker.create({
132
+ connection: hostConnection,
133
+ namespace: config.temporalNamespace,
134
+ taskQueue: (0, config_1.hostTaskQueue)(config.taskQueue, os.hostname()),
135
+ identity: workerIdentity(), // #274 — same format, both pollers under one identity
136
+ shutdownGraceTime: SHUTDOWN_GRACE_TIME,
137
+ shutdownForceTime: SHUTDOWN_FORCE_TIME,
138
+ activities: {
139
+ spawnProcess: outboxActivities.spawnProcess,
140
+ // #159 Gap 2: host-local OS-process kill. Must live on the per-host queue so it runs
141
+ // on the machine where the claude.exe / bridge process actually lives.
142
+ hardTerminateAttachment: outboxActivities.hardTerminateAttachment,
143
+ },
144
+ });
145
+ return { sharedWorker, hostWorker };
146
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Pure attachment-math helpers for the session workflow.
3
+ *
4
+ * **Workflow-sandbox safe**: this file imports only types. No `@temporalio/*`
5
+ * runtime imports, no `Date.now()`, no random, no I/O — every caller passes
6
+ * `now` as a parameter so the same inputs always produce the same output.
7
+ * That makes it:
8
+ * - Cheap to unit-test from Mocha without `TestWorkflowEnvironment`, and
9
+ * - Safe to call from deterministic workflow code (caller is responsible
10
+ * for sourcing `now` via the SDK-intercepted `new Date().getTime()`).
11
+ *
12
+ * Extracted in PR #127-fix as a follow-up to PR-G (#125) architect review:
13
+ * the alternative was a ~60 LOC history-fill harness that would have tested
14
+ * Temporal's CAN-trigger heuristic rather than our extension logic, and
15
+ * would have been brittle to Temporal-SDK internals. Pure-function + direct
16
+ * unit tests is the durable choice.
17
+ */
18
+ import type { Attachment } from '../types';
19
+ /**
20
+ * Produce a new {@link Attachment} whose lease window is extended so an
21
+ * adapter that was beating normally at the moment of `continueAsNew` has room
22
+ * to land its next heartbeat before the new execution's first main-loop tick
23
+ * reaps the lease.
24
+ *
25
+ * **Design rationale (session-lifecycle-rebuild-v2.md §2.3):** the CAN
26
+ * transition is not instantaneous. If we were to write the pre-CAN
27
+ * `expiresAt` verbatim into the new execution, a transition that takes
28
+ * ~100-500ms could leave the new run's first deadline race observing an
29
+ * already-expired lease and reaping a healthy attachment. Pushing
30
+ * `expiresAt` out to `now + extendMs` guarantees the adapter has room to land
31
+ * its next heartbeat.
32
+ *
33
+ * Why this is a total function (returns a new object unconditionally,
34
+ * rather than accepting `null` and returning `undefined`): null-handling is
35
+ * the caller's business — a workflow that has no current attachment simply
36
+ * skips the call. Keeping this function non-nullable keeps the unit tests
37
+ * focused on math rather than null-propagation.
38
+ *
39
+ * @param attachment - the pre-CAN attachment record. All non-timestamp
40
+ * fields (`attachmentId`, `hostname`, `adapterId`, `adapterClass`,
41
+ * `claimedAt`, `leaseMs`, `runId`) are carried forward verbatim.
42
+ * @param extendMs - how far past `now` to push `expiresAt`, in milliseconds.
43
+ * Post-#249 callers pass `attachment.leaseMs` (= 3 × heartbeatMs — covers one
44
+ * full lease window and therefore at least one full heartbeat interval for
45
+ * every adapter class). Pre-#249 callers passed a hardcoded 30_000 constant
46
+ * which under-covered the claude-code adapter's 60s cadence — the rename
47
+ * from `heartbeatMs` disambiguates that the parameter is a raw extension
48
+ * duration, not a cadence. The function does not validate — any non-negative
49
+ * integer is accepted.
50
+ * @param now - current time in epoch milliseconds. In workflow context
51
+ * callers pass `new Date().getTime()` (the Temporal SDK intercepts `new
52
+ * Date()` to return replay-consistent time). In unit tests callers pass
53
+ * an arbitrary fixed value.
54
+ * @returns a new `Attachment` object — the input is not mutated.
55
+ */
56
+ export declare function extendAttachmentForCAN(attachment: Attachment, extendMs: number, now: number): Attachment;