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,113 @@
1
+ /**
2
+ * Shared input validation constants for player names, ensemble names, messages, etc.
3
+ * Used by MCP tool Zod schemas and config validation.
4
+ */
5
+ /** Player names: alphanumeric, hyphens, underscores. */
6
+ export declare const PLAYER_NAME_REGEX: RegExp;
7
+ export declare const PLAYER_NAME_MAX = 64;
8
+ /**
9
+ * Ensemble names: must start and end with alphanumeric, may contain dots, hyphens, underscores.
10
+ * Minimum 1 char (single alphanumeric), maximum 64 chars.
11
+ */
12
+ export declare const ENSEMBLE_NAME_REGEX: RegExp;
13
+ /** Stage name max length. */
14
+ export declare const STAGE_NAME_MAX = 64;
15
+ /** Maximum players per stage. */
16
+ export declare const STAGE_PLAYERS_MAX = 20;
17
+ /** Maximum message size for cue/report (100KB). */
18
+ export declare const MESSAGE_MAX = 102400;
19
+ /** Maximum part (status) length. */
20
+ export declare const PART_MAX = 500;
21
+ /** Default slot key when callers omit `key`. */
22
+ export declare const PLAYER_STATE_DEFAULT_KEY = "main";
23
+ /** Slot keys: alphanumeric + underscore + hyphen. Mirrors PLAYER_NAME_REGEX shape. */
24
+ export declare const PLAYER_STATE_KEY_REGEX: RegExp;
25
+ /** Maximum slot key length. */
26
+ export declare const PLAYER_STATE_KEY_MAX = 32;
27
+ /** Maximum content size per slot — 32 KiB. Mirrors coat-check's per-entry cap. */
28
+ export declare const PLAYER_STATE_CONTENT_MAX: number;
29
+ /** Maximum number of populated slots per player. Saturation rejects with `PlayerStateSlotsFull`. */
30
+ export declare const PLAYER_STATE_SLOTS_MAX = 4;
31
+ /** Coat-check ticket id pattern. Alphanumeric + underscore + hyphen, generated server-side via `uuid4()`. */
32
+ export declare const COAT_CHECK_TICKET_REGEX: RegExp;
33
+ /** Maximum coat-check ticket id length. Generous to accommodate uuid4 + future versioning prefixes. */
34
+ export declare const COAT_CHECK_TICKET_MAX = 64;
35
+ /** Maximum content size per coat-check entry — 32 KiB. Mirrors `PLAYER_STATE_CONTENT_MAX`. */
36
+ export declare const COAT_CHECK_CONTENT_MAX: number;
37
+ /** Maximum summary length per coat-check entry — short, listing-friendly preamble. */
38
+ export declare const COAT_CHECK_SUMMARY_MAX = 500;
39
+ /** Maximum free-form contentType string (e.g. `'text/markdown'`). */
40
+ export declare const COAT_CHECK_CONTENT_TYPE_MAX = 64;
41
+ /** Maximum populated coat-check slots per ensemble. Saturation rejects with `CoatCheckSlotsFull`. */
42
+ export declare const COAT_CHECK_SLOTS_MAX = 20;
43
+ /** Minimum allowed `ttlMs` argument on `coat_check_put` — 1 hour. */
44
+ export declare const COAT_CHECK_TTL_MIN_MS: number;
45
+ /** Maximum allowed `ttlMs` argument on `coat_check_put` — 30 days. */
46
+ export declare const COAT_CHECK_TTL_MAX_MS: number;
47
+ /** Default `ttlMs` when caller omits the argument — 7 days. */
48
+ export declare const COAT_CHECK_TTL_DEFAULT_MS: number;
49
+ /**
50
+ * Maximum length of the ensemble description set via
51
+ * `set_ensemble_description` (#399 W1, Q5.1). Soft cap — the MCP tool
52
+ * boundary rejects oversized inputs; the maestro workflow clamps as a
53
+ * defence-in-depth measure.
54
+ */
55
+ export declare const ENSEMBLE_DESCRIPTION_MAX = 100;
56
+ /** Maximum file path length. */
57
+ export declare const PATH_MAX = 1024;
58
+ /** Maximum schedule name length. */
59
+ export declare const SCHEDULE_NAME_MAX = 64;
60
+ /** Maximum schedule message size (10KB). */
61
+ export declare const SCHEDULE_MESSAGE_MAX = 10240;
62
+ /** Maximum cron expression length. */
63
+ export declare const CRON_EXPRESSION_MAX = 128;
64
+ /** Maximum quality gate task name length. */
65
+ export declare const GATE_TASK_MAX = 64;
66
+ /** Maximum number of criteria per quality gate. */
67
+ export declare const GATE_CRITERIA_MAX = 20;
68
+ /** Maximum length for individual criterion text. */
69
+ export declare const GATE_CRITERION_TEXT_MAX = 512;
70
+ /** Maximum length for gate criterion notes. */
71
+ export declare const GATE_NOTES_MAX = 1024;
72
+ /** Timeout for npm install in worktrees (60s). */
73
+ export declare const WORKTREE_INSTALL_TIMEOUT = 60000;
74
+ /** Maximum length for message preview truncation. */
75
+ export declare const PREVIEW_MAX_LENGTH = 200;
76
+ /** Maximum `contextMessages` arg for restart / migrate tools (QA B4). */
77
+ export declare const RESTART_CONTEXT_MESSAGES_MAX = 50;
78
+ /** Maximum `deadlineMs` arg for detach tool. */
79
+ export declare const MAX_DETACH_DEADLINE_MS = 120000;
80
+ /**
81
+ * Default graceful-detach deadline used by `deliverRestart`'s Step 2
82
+ * (`requestDetach` before a forced attachment handover). Internal, not
83
+ * user-controllable — well below `MAX_DETACH_DEADLINE_MS`. Extracted from
84
+ * a raw `5_000` literal in PR #136 F5 follow-up (#139).
85
+ */
86
+ export declare const DEFAULT_RESTART_DETACH_DEADLINE_MS = 5000;
87
+ /**
88
+ * Default attachment lease (ms) used by `deliverRestart`'s Step 4
89
+ * (`claimAttachment`). Ninety seconds gives the freshly-spawned adapter
90
+ * enough runway to boot, renew, and begin heartbeating. Extracted from a
91
+ * raw `90_000` literal in PR #136 F5 follow-up (#139).
92
+ */
93
+ export declare const DEFAULT_RESTART_LEASE_MS = 90000;
94
+ /**
95
+ * Whether a session should be included in a broadcast based on its attachment phase.
96
+ *
97
+ * Option-B mapping (see #176 PR description):
98
+ * - `attached` / `processing` / `awaiting` → include (talkable)
99
+ * - `booting` → exclude (not ready — legacy "pending")
100
+ * - `draining` / `detached` → include only if includeDisconnected
101
+ * - `gone` → exclude (terminal — legacy "terminated")
102
+ *
103
+ * Undefined phase (older workflows pre-attachment-lifecycle, or transient
104
+ * search-attribute propagation) is treated as `booting` — safe default.
105
+ *
106
+ * The `includeDisconnected` parameter is surfaced to callers via the `includeStale`
107
+ * MCP tool argument (kept for wire compat; description updated).
108
+ */
109
+ export declare function shouldIncludeInBroadcast(phase: string | undefined, includeDisconnected: boolean): boolean;
110
+ /** Validate a player name string. Returns an error message or null if valid. */
111
+ export declare function validatePlayerName(name: string): string | null;
112
+ /** Validate an ensemble name string. Returns an error message or null if valid. */
113
+ export declare function validateEnsembleName(name: string): string | null;
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ /**
3
+ * Shared input validation constants for player names, ensemble names, messages, etc.
4
+ * Used by MCP tool Zod schemas and config validation.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DEFAULT_RESTART_LEASE_MS = exports.DEFAULT_RESTART_DETACH_DEADLINE_MS = exports.MAX_DETACH_DEADLINE_MS = exports.RESTART_CONTEXT_MESSAGES_MAX = exports.PREVIEW_MAX_LENGTH = exports.WORKTREE_INSTALL_TIMEOUT = exports.GATE_NOTES_MAX = exports.GATE_CRITERION_TEXT_MAX = exports.GATE_CRITERIA_MAX = exports.GATE_TASK_MAX = exports.CRON_EXPRESSION_MAX = exports.SCHEDULE_MESSAGE_MAX = exports.SCHEDULE_NAME_MAX = exports.PATH_MAX = exports.ENSEMBLE_DESCRIPTION_MAX = exports.COAT_CHECK_TTL_DEFAULT_MS = exports.COAT_CHECK_TTL_MAX_MS = exports.COAT_CHECK_TTL_MIN_MS = exports.COAT_CHECK_SLOTS_MAX = exports.COAT_CHECK_CONTENT_TYPE_MAX = exports.COAT_CHECK_SUMMARY_MAX = exports.COAT_CHECK_CONTENT_MAX = exports.COAT_CHECK_TICKET_MAX = exports.COAT_CHECK_TICKET_REGEX = exports.PLAYER_STATE_SLOTS_MAX = exports.PLAYER_STATE_CONTENT_MAX = exports.PLAYER_STATE_KEY_MAX = exports.PLAYER_STATE_KEY_REGEX = exports.PLAYER_STATE_DEFAULT_KEY = exports.PART_MAX = exports.MESSAGE_MAX = exports.STAGE_PLAYERS_MAX = exports.STAGE_NAME_MAX = exports.ENSEMBLE_NAME_REGEX = exports.PLAYER_NAME_MAX = exports.PLAYER_NAME_REGEX = void 0;
8
+ exports.shouldIncludeInBroadcast = shouldIncludeInBroadcast;
9
+ exports.validatePlayerName = validatePlayerName;
10
+ exports.validateEnsembleName = validateEnsembleName;
11
+ /** Player names: alphanumeric, hyphens, underscores. */
12
+ exports.PLAYER_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
13
+ exports.PLAYER_NAME_MAX = 64;
14
+ /**
15
+ * Ensemble names: must start and end with alphanumeric, may contain dots, hyphens, underscores.
16
+ * Minimum 1 char (single alphanumeric), maximum 64 chars.
17
+ */
18
+ exports.ENSEMBLE_NAME_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9._-]{0,62}[a-zA-Z0-9])?$/;
19
+ /** Stage name max length. */
20
+ exports.STAGE_NAME_MAX = 64;
21
+ /** Maximum players per stage. */
22
+ exports.STAGE_PLAYERS_MAX = 20;
23
+ /** Maximum message size for cue/report (100KB). */
24
+ exports.MESSAGE_MAX = 102400;
25
+ /** Maximum part (status) length. */
26
+ exports.PART_MAX = 500;
27
+ // ── Player saveable state (#334 PR-1) ──────────────────────────────────────
28
+ //
29
+ // Per-session, player-curated state slots. Sized per design §3.3:
30
+ // per-key 32 KiB × max 4 slots → 128 KiB structural max per session.
31
+ // At a 1.2 MiB p99 session footprint, that lands at ~33 % of Temporal's
32
+ // 4 MiB CAN-payload ceiling — comfortable. Saturation refuses with a
33
+ // `PlayerStateSlotsFull` ApplicationFailure rather than evicting LRU
34
+ // (Anthropic harness-design blog: explicit eviction reinforces authorial
35
+ // discipline). See docs/adr/0011-player-saveable-state.md.
36
+ /** Default slot key when callers omit `key`. */
37
+ exports.PLAYER_STATE_DEFAULT_KEY = 'main';
38
+ /** Slot keys: alphanumeric + underscore + hyphen. Mirrors PLAYER_NAME_REGEX shape. */
39
+ exports.PLAYER_STATE_KEY_REGEX = /^[a-zA-Z0-9_-]+$/;
40
+ /** Maximum slot key length. */
41
+ exports.PLAYER_STATE_KEY_MAX = 32;
42
+ /** Maximum content size per slot — 32 KiB. Mirrors coat-check's per-entry cap. */
43
+ exports.PLAYER_STATE_CONTENT_MAX = 32 * 1024;
44
+ /** Maximum number of populated slots per player. Saturation rejects with `PlayerStateSlotsFull`. */
45
+ exports.PLAYER_STATE_SLOTS_MAX = 4;
46
+ // ── Coat-check (#318, ADR 0008) ────────────────────────────────────────────
47
+ //
48
+ // Ensemble-shared, ticket-keyed stash for content too large to inline in a
49
+ // `cue` message body. Lives on per-ensemble Maestro workflow state.
50
+ //
51
+ // Sizing per the #318 architect verdict (which adjusts ADR 0008's 50-slot
52
+ // proposal):
53
+ // per-entry 32 KiB × max 20 slots → 640 KiB structural max per ensemble.
54
+ // That lands at ~16 % of Temporal's 4 MiB CAN-payload ceiling — comfortable
55
+ // headroom on top of existing maestro state (~316 KiB). Saturation refuses
56
+ // with a `CoatCheckSlotsFull` ApplicationFailure rather than evicting LRU
57
+ // — cross-host scope makes silent peer eviction a sharper footgun than
58
+ // the rejection's diagnostic UX.
59
+ /** Coat-check ticket id pattern. Alphanumeric + underscore + hyphen, generated server-side via `uuid4()`. */
60
+ exports.COAT_CHECK_TICKET_REGEX = /^[a-zA-Z0-9_-]+$/;
61
+ /** Maximum coat-check ticket id length. Generous to accommodate uuid4 + future versioning prefixes. */
62
+ exports.COAT_CHECK_TICKET_MAX = 64;
63
+ /** Maximum content size per coat-check entry — 32 KiB. Mirrors `PLAYER_STATE_CONTENT_MAX`. */
64
+ exports.COAT_CHECK_CONTENT_MAX = 32 * 1024;
65
+ /** Maximum summary length per coat-check entry — short, listing-friendly preamble. */
66
+ exports.COAT_CHECK_SUMMARY_MAX = 500;
67
+ /** Maximum free-form contentType string (e.g. `'text/markdown'`). */
68
+ exports.COAT_CHECK_CONTENT_TYPE_MAX = 64;
69
+ /** Maximum populated coat-check slots per ensemble. Saturation rejects with `CoatCheckSlotsFull`. */
70
+ exports.COAT_CHECK_SLOTS_MAX = 20;
71
+ /** Minimum allowed `ttlMs` argument on `coat_check_put` — 1 hour. */
72
+ exports.COAT_CHECK_TTL_MIN_MS = 60 * 60 * 1000;
73
+ /** Maximum allowed `ttlMs` argument on `coat_check_put` — 30 days. */
74
+ exports.COAT_CHECK_TTL_MAX_MS = 30 * 24 * 60 * 60 * 1000;
75
+ /** Default `ttlMs` when caller omits the argument — 7 days. */
76
+ exports.COAT_CHECK_TTL_DEFAULT_MS = 7 * 24 * 60 * 60 * 1000;
77
+ /**
78
+ * Maximum length of the ensemble description set via
79
+ * `set_ensemble_description` (#399 W1, Q5.1). Soft cap — the MCP tool
80
+ * boundary rejects oversized inputs; the maestro workflow clamps as a
81
+ * defence-in-depth measure.
82
+ */
83
+ exports.ENSEMBLE_DESCRIPTION_MAX = 100;
84
+ /** Maximum file path length. */
85
+ exports.PATH_MAX = 1024;
86
+ /** Maximum schedule name length. */
87
+ exports.SCHEDULE_NAME_MAX = 64;
88
+ /** Maximum schedule message size (10KB). */
89
+ exports.SCHEDULE_MESSAGE_MAX = 10240;
90
+ /** Maximum cron expression length. */
91
+ exports.CRON_EXPRESSION_MAX = 128;
92
+ /** Maximum quality gate task name length. */
93
+ exports.GATE_TASK_MAX = 64;
94
+ /** Maximum number of criteria per quality gate. */
95
+ exports.GATE_CRITERIA_MAX = 20;
96
+ /** Maximum length for individual criterion text. */
97
+ exports.GATE_CRITERION_TEXT_MAX = 512;
98
+ /** Maximum length for gate criterion notes. */
99
+ exports.GATE_NOTES_MAX = 1024;
100
+ /** Timeout for npm install in worktrees (60s). */
101
+ exports.WORKTREE_INSTALL_TIMEOUT = 60000;
102
+ // `BLOCKED_WINDOW_MS` constant removed in v0.26 (#175 / #178) — the blocked
103
+ // session heuristic it gated was replaced by the attachment-phase lifecycle.
104
+ /** Maximum length for message preview truncation. */
105
+ exports.PREVIEW_MAX_LENGTH = 200;
106
+ /** Maximum `contextMessages` arg for restart / migrate tools (QA B4). */
107
+ exports.RESTART_CONTEXT_MESSAGES_MAX = 50;
108
+ /** Maximum `deadlineMs` arg for detach tool. */
109
+ exports.MAX_DETACH_DEADLINE_MS = 120_000;
110
+ /**
111
+ * Default graceful-detach deadline used by `deliverRestart`'s Step 2
112
+ * (`requestDetach` before a forced attachment handover). Internal, not
113
+ * user-controllable — well below `MAX_DETACH_DEADLINE_MS`. Extracted from
114
+ * a raw `5_000` literal in PR #136 F5 follow-up (#139).
115
+ */
116
+ exports.DEFAULT_RESTART_DETACH_DEADLINE_MS = 5_000;
117
+ /**
118
+ * Default attachment lease (ms) used by `deliverRestart`'s Step 4
119
+ * (`claimAttachment`). Ninety seconds gives the freshly-spawned adapter
120
+ * enough runway to boot, renew, and begin heartbeating. Extracted from a
121
+ * raw `90_000` literal in PR #136 F5 follow-up (#139).
122
+ */
123
+ exports.DEFAULT_RESTART_LEASE_MS = 90_000;
124
+ /**
125
+ * Whether a session should be included in a broadcast based on its attachment phase.
126
+ *
127
+ * Option-B mapping (see #176 PR description):
128
+ * - `attached` / `processing` / `awaiting` → include (talkable)
129
+ * - `booting` → exclude (not ready — legacy "pending")
130
+ * - `draining` / `detached` → include only if includeDisconnected
131
+ * - `gone` → exclude (terminal — legacy "terminated")
132
+ *
133
+ * Undefined phase (older workflows pre-attachment-lifecycle, or transient
134
+ * search-attribute propagation) is treated as `booting` — safe default.
135
+ *
136
+ * The `includeDisconnected` parameter is surfaced to callers via the `includeStale`
137
+ * MCP tool argument (kept for wire compat; description updated).
138
+ */
139
+ function shouldIncludeInBroadcast(phase, includeDisconnected) {
140
+ const p = phase || 'booting';
141
+ if (p === 'gone' || p === 'booting')
142
+ return false;
143
+ if ((p === 'draining' || p === 'detached') && !includeDisconnected)
144
+ return false;
145
+ return true;
146
+ }
147
+ /** Validate a player name string. Returns an error message or null if valid. */
148
+ function validatePlayerName(name) {
149
+ if (name.length > exports.PLAYER_NAME_MAX) {
150
+ return `Name too long (${name.length} chars, max ${exports.PLAYER_NAME_MAX}).`;
151
+ }
152
+ if (!exports.PLAYER_NAME_REGEX.test(name)) {
153
+ return `Invalid name "${name}". Names must contain only letters, numbers, hyphens, and underscores.`;
154
+ }
155
+ return null;
156
+ }
157
+ /** Validate an ensemble name string. Returns an error message or null if valid. */
158
+ function validateEnsembleName(name) {
159
+ if (!exports.ENSEMBLE_NAME_REGEX.test(name)) {
160
+ return `Invalid ensemble name "${name}". Must start/end with alphanumeric, may contain letters, numbers, dots, hyphens, underscores (max 64 chars).`;
161
+ }
162
+ return null;
163
+ }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Iterator-level deadlines for unbounded Temporal visibility queries
3
+ * (`client.workflow.list({ query })`). Closes #336 + #529.
4
+ *
5
+ * ## Background
6
+ *
7
+ * Six daemon hot-path sites consume `for await (const wf of
8
+ * client.workflow.list({ query }))` without any iterator-level deadline.
9
+ * Temporal's visibility API is page-based: each `next()` may fetch
10
+ * additional pages over gRPC. A wedged worker, a slow page on a deep
11
+ * scan, or a backend hiccup can stall the iterator indefinitely while
12
+ * the gRPC stream retains buffer state. Researcher's spike on #336
13
+ * traced 17h-runtime memory growth to retained `WorkflowExecutionInfo`
14
+ * protobufs hanging off un-completed iterator streams.
15
+ *
16
+ * The fix per site is small (≤ 12 LoC), but the **caller's correctness
17
+ * model around partial enumeration is what varies** — three patterns:
18
+ *
19
+ * - **Partial-tolerant + warn-log**: silently breaking out is safe;
20
+ * the caller treats the truncated result as a best-effort snapshot
21
+ * that the next tick / retry will fill in. (Sites 2, 3, 5)
22
+ * - **Structured outcome**: the caller branches on whether enumeration
23
+ * completed. Sites 4 (`fireSchedule target='all'`) extends its
24
+ * existing `{delivered, failures}` result. Site 1 (`resolveSession`)
25
+ * throws {@link VisibilityIteratorTimeoutError} so callers can
26
+ * distinguish "definitely absent" from "scan didn't finish."
27
+ * - **Skip the entire tick / preserve prior state**: AggregateRunner's
28
+ * ensemble-set diff (site 6) — partial results would emit phantom
29
+ * `ensemble.destroyed` SSE events. Handled separately via the
30
+ * architect-approved invariant in `src/http/aggregate.ts`.
31
+ *
32
+ * ## Deadline tuning rationale
33
+ *
34
+ * Per-site defaults live in {@link VISIBILITY_DEADLINES_MS}. Numbers
35
+ * chosen to balance:
36
+ *
37
+ * - The caller's tick cadence (a 5s deadline is "instant" if the
38
+ * caller polls every 750ms but "an eternity" if they boot once and
39
+ * never retry).
40
+ * - The expected scan depth (orphan boot scan walks every running
41
+ * session workflow across every host; aggregate poll walks the same
42
+ * set but happens 80× per minute).
43
+ * - Headroom against the activity-level StartToClose timeout
44
+ * (typically 60s) — the iterator deadline should fire well before
45
+ * StartToClose so the activity returns a structured "timed out"
46
+ * outcome rather than getting force-cancelled by Temporal.
47
+ *
48
+ * Tune per site rather than chasing a single magic number; reviewer
49
+ * sanity-checks the values in this map during PR review.
50
+ */
51
+ import type { WorkflowExecutionInfo } from '@temporalio/client';
52
+ /**
53
+ * Per-site deadline budgets for visibility iterators (#336/#529).
54
+ *
55
+ * Adding a new site? Pick a deadline that:
56
+ * 1. Comfortably fits within the caller's StartToClose if it runs as an activity.
57
+ * 2. Is short enough that a wedged iterator can't dominate the caller's tick budget.
58
+ * 3. Documents the rationale below.
59
+ */
60
+ export declare const VISIBILITY_DEADLINES_MS: {
61
+ /**
62
+ * `resolveSession` — finds a single `(ensemble, playerId)` in the
63
+ * running-session set. Called from outbox / CLI / tools on every
64
+ * cue/signal/restart. 10s gives plenty of headroom for a healthy
65
+ * lookup while preventing a wedged session worker from holding the
66
+ * outbox loop indefinitely (per-workflow `getMetadata` already
67
+ * bounded at #433's `queryHandleWithTimeout`).
68
+ */
69
+ readonly resolveSession: 10000;
70
+ /**
71
+ * `scanEnsembleSessions` — full ensemble enumeration with metadata
72
+ * + part + activity-state per session. Called from the `ensemble`
73
+ * MCP tool and the maestro refresh activity. 15s allows scanning
74
+ * hundreds of workflows with the per-query bounds at #433.
75
+ */
76
+ readonly scanEnsembleSessions: 15000;
77
+ /**
78
+ * `discoverEnsembles` (maestro activity) — aggregates unique ensemble
79
+ * names. 10s; the maestro retries on its own schedule, so a partial
80
+ * result self-heals on the next tick.
81
+ */
82
+ readonly discoverEnsembles: 10000;
83
+ /**
84
+ * `fireSchedule target='all'` — broadcast loop. 20s; broadcasts can
85
+ * fan out to many players, and the caller's existing `failures: []`
86
+ * surface already records partial delivery — extending it with a
87
+ * `timedOut` flag preserves the "scheduler promised 'all'" semantic.
88
+ */
89
+ readonly fireScheduleAll: 20000;
90
+ /**
91
+ * `queryOrphanedSessions` boot scan — runs once at daemon startup.
92
+ * 60s budget because losing an orphan means a session goes
93
+ * un-reconciled, but the function's existing comment explicitly
94
+ * marks partial results as acceptable ("next tick will retry").
95
+ */
96
+ readonly orphanQueryBoot: 60000;
97
+ /**
98
+ * `queryOrphanedSessions` cleanup loop — 6h-cadence sweep. 30s;
99
+ * shorter than boot because the cleanup loop runs frequently
100
+ * enough to amortize partial scans across many sweeps.
101
+ */
102
+ readonly orphanQueryCleanup: 30000;
103
+ };
104
+ export type VisibilitySite = keyof typeof VISIBILITY_DEADLINES_MS;
105
+ /**
106
+ * Thrown by {@link iterateWithDeadline} when the per-iterator deadline
107
+ * fires. Callers that want to distinguish "scan didn't finish" from
108
+ * "scan completed with N results" should catch this error specifically.
109
+ *
110
+ * Carries `site` (which deadline tripped) and `partialCount` (how many
111
+ * entries were yielded before the timeout) so warn-log surfaces are
112
+ * actionable — `"orphanQueryBoot timed out after 60000ms, partial=423"`
113
+ * tells the operator both which budget is too tight AND how close to
114
+ * complete the scan got.
115
+ */
116
+ export declare class VisibilityIteratorTimeoutError extends Error {
117
+ readonly site: string;
118
+ readonly deadlineMs: number;
119
+ readonly partialCount: number;
120
+ readonly name = "VisibilityIteratorTimeoutError";
121
+ constructor(site: string, deadlineMs: number, partialCount: number);
122
+ }
123
+ /**
124
+ * Wrap an async iterable of `WorkflowExecutionInfo` (the type yielded
125
+ * by `client.workflow.list({ query })`) with a wall-clock deadline.
126
+ *
127
+ * Yields entries until either the upstream iterator exhausts (normal
128
+ * end) or `Date.now() > deadline` (timeout). On timeout, throws
129
+ * {@link VisibilityIteratorTimeoutError} after the in-progress
130
+ * iteration completes — so the caller can choose whether to swallow
131
+ * the throw (partial-tolerant pattern) or propagate it.
132
+ *
133
+ * The deadline check fires **before** each yield, not after — so the
134
+ * iterator never spends time fetching a page it won't consume. The
135
+ * `partialCount` reported in the error reflects entries yielded, not
136
+ * pages fetched, which matches what operators care about.
137
+ *
138
+ * ## Usage pattern (partial-tolerant)
139
+ *
140
+ * ```ts
141
+ * try {
142
+ * for await (const wf of iterateWithDeadline(
143
+ * client.workflow.list({ query }),
144
+ * VISIBILITY_DEADLINES_MS.scanEnsembleSessions,
145
+ * 'scanEnsembleSessions',
146
+ * )) {
147
+ * // existing loop body
148
+ * }
149
+ * } catch (err) {
150
+ * if (err instanceof VisibilityIteratorTimeoutError) {
151
+ * log('warn: ' + err.message + ' — returning partial results');
152
+ * // fall through to return whatever we accumulated
153
+ * } else {
154
+ * throw err;
155
+ * }
156
+ * }
157
+ * ```
158
+ *
159
+ * ## Usage pattern (structured outcome)
160
+ *
161
+ * ```ts
162
+ * let timedOut = false;
163
+ * try {
164
+ * for await (const wf of iterateWithDeadline(...)) { ... }
165
+ * } catch (err) {
166
+ * if (err instanceof VisibilityIteratorTimeoutError) {
167
+ * timedOut = true;
168
+ * // fall through — caller surfaces `timedOut` in the result
169
+ * } else {
170
+ * throw err;
171
+ * }
172
+ * }
173
+ * return { success: !timedOut, ..., timedOut };
174
+ * ```
175
+ */
176
+ export declare function iterateWithDeadline(source: AsyncIterable<WorkflowExecutionInfo>, deadlineMs: number, site: string,
177
+ /** Test-only — defaults to `Date.now`; injectable so unit tests can advance the clock. */
178
+ now?: () => number): AsyncGenerator<WorkflowExecutionInfo>;
179
+ /**
180
+ * Compose `iterateWithDeadline` with the partial-tolerant catch pattern
181
+ * for sites that just want "log a warn, return what we got."
182
+ *
183
+ * Sites 2, 3, 5 use this; sites 1 + 4 use the raw iterator so they can
184
+ * carry the timeout signal into their return shape.
185
+ */
186
+ export declare function isVisibilityTimeout(err: unknown): err is VisibilityIteratorTimeoutError;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VisibilityIteratorTimeoutError = exports.VISIBILITY_DEADLINES_MS = void 0;
4
+ exports.iterateWithDeadline = iterateWithDeadline;
5
+ exports.isVisibilityTimeout = isVisibilityTimeout;
6
+ /**
7
+ * Per-site deadline budgets for visibility iterators (#336/#529).
8
+ *
9
+ * Adding a new site? Pick a deadline that:
10
+ * 1. Comfortably fits within the caller's StartToClose if it runs as an activity.
11
+ * 2. Is short enough that a wedged iterator can't dominate the caller's tick budget.
12
+ * 3. Documents the rationale below.
13
+ */
14
+ exports.VISIBILITY_DEADLINES_MS = {
15
+ /**
16
+ * `resolveSession` — finds a single `(ensemble, playerId)` in the
17
+ * running-session set. Called from outbox / CLI / tools on every
18
+ * cue/signal/restart. 10s gives plenty of headroom for a healthy
19
+ * lookup while preventing a wedged session worker from holding the
20
+ * outbox loop indefinitely (per-workflow `getMetadata` already
21
+ * bounded at #433's `queryHandleWithTimeout`).
22
+ */
23
+ resolveSession: 10_000,
24
+ /**
25
+ * `scanEnsembleSessions` — full ensemble enumeration with metadata
26
+ * + part + activity-state per session. Called from the `ensemble`
27
+ * MCP tool and the maestro refresh activity. 15s allows scanning
28
+ * hundreds of workflows with the per-query bounds at #433.
29
+ */
30
+ scanEnsembleSessions: 15_000,
31
+ /**
32
+ * `discoverEnsembles` (maestro activity) — aggregates unique ensemble
33
+ * names. 10s; the maestro retries on its own schedule, so a partial
34
+ * result self-heals on the next tick.
35
+ */
36
+ discoverEnsembles: 10_000,
37
+ /**
38
+ * `fireSchedule target='all'` — broadcast loop. 20s; broadcasts can
39
+ * fan out to many players, and the caller's existing `failures: []`
40
+ * surface already records partial delivery — extending it with a
41
+ * `timedOut` flag preserves the "scheduler promised 'all'" semantic.
42
+ */
43
+ fireScheduleAll: 20_000,
44
+ /**
45
+ * `queryOrphanedSessions` boot scan — runs once at daemon startup.
46
+ * 60s budget because losing an orphan means a session goes
47
+ * un-reconciled, but the function's existing comment explicitly
48
+ * marks partial results as acceptable ("next tick will retry").
49
+ */
50
+ orphanQueryBoot: 60_000,
51
+ /**
52
+ * `queryOrphanedSessions` cleanup loop — 6h-cadence sweep. 30s;
53
+ * shorter than boot because the cleanup loop runs frequently
54
+ * enough to amortize partial scans across many sweeps.
55
+ */
56
+ orphanQueryCleanup: 30_000,
57
+ };
58
+ /**
59
+ * Thrown by {@link iterateWithDeadline} when the per-iterator deadline
60
+ * fires. Callers that want to distinguish "scan didn't finish" from
61
+ * "scan completed with N results" should catch this error specifically.
62
+ *
63
+ * Carries `site` (which deadline tripped) and `partialCount` (how many
64
+ * entries were yielded before the timeout) so warn-log surfaces are
65
+ * actionable — `"orphanQueryBoot timed out after 60000ms, partial=423"`
66
+ * tells the operator both which budget is too tight AND how close to
67
+ * complete the scan got.
68
+ */
69
+ class VisibilityIteratorTimeoutError extends Error {
70
+ site;
71
+ deadlineMs;
72
+ partialCount;
73
+ name = 'VisibilityIteratorTimeoutError';
74
+ constructor(site, deadlineMs, partialCount) {
75
+ super(`Visibility iterator "${site}" exceeded ${deadlineMs}ms deadline ` +
76
+ `after ${partialCount} entries`);
77
+ this.site = site;
78
+ this.deadlineMs = deadlineMs;
79
+ this.partialCount = partialCount;
80
+ }
81
+ }
82
+ exports.VisibilityIteratorTimeoutError = VisibilityIteratorTimeoutError;
83
+ /**
84
+ * Wrap an async iterable of `WorkflowExecutionInfo` (the type yielded
85
+ * by `client.workflow.list({ query })`) with a wall-clock deadline.
86
+ *
87
+ * Yields entries until either the upstream iterator exhausts (normal
88
+ * end) or `Date.now() > deadline` (timeout). On timeout, throws
89
+ * {@link VisibilityIteratorTimeoutError} after the in-progress
90
+ * iteration completes — so the caller can choose whether to swallow
91
+ * the throw (partial-tolerant pattern) or propagate it.
92
+ *
93
+ * The deadline check fires **before** each yield, not after — so the
94
+ * iterator never spends time fetching a page it won't consume. The
95
+ * `partialCount` reported in the error reflects entries yielded, not
96
+ * pages fetched, which matches what operators care about.
97
+ *
98
+ * ## Usage pattern (partial-tolerant)
99
+ *
100
+ * ```ts
101
+ * try {
102
+ * for await (const wf of iterateWithDeadline(
103
+ * client.workflow.list({ query }),
104
+ * VISIBILITY_DEADLINES_MS.scanEnsembleSessions,
105
+ * 'scanEnsembleSessions',
106
+ * )) {
107
+ * // existing loop body
108
+ * }
109
+ * } catch (err) {
110
+ * if (err instanceof VisibilityIteratorTimeoutError) {
111
+ * log('warn: ' + err.message + ' — returning partial results');
112
+ * // fall through to return whatever we accumulated
113
+ * } else {
114
+ * throw err;
115
+ * }
116
+ * }
117
+ * ```
118
+ *
119
+ * ## Usage pattern (structured outcome)
120
+ *
121
+ * ```ts
122
+ * let timedOut = false;
123
+ * try {
124
+ * for await (const wf of iterateWithDeadline(...)) { ... }
125
+ * } catch (err) {
126
+ * if (err instanceof VisibilityIteratorTimeoutError) {
127
+ * timedOut = true;
128
+ * // fall through — caller surfaces `timedOut` in the result
129
+ * } else {
130
+ * throw err;
131
+ * }
132
+ * }
133
+ * return { success: !timedOut, ..., timedOut };
134
+ * ```
135
+ */
136
+ async function* iterateWithDeadline(source, deadlineMs, site,
137
+ /** Test-only — defaults to `Date.now`; injectable so unit tests can advance the clock. */
138
+ now = Date.now) {
139
+ const deadline = now() + deadlineMs;
140
+ let count = 0;
141
+ for await (const entry of source) {
142
+ if (now() > deadline) {
143
+ throw new VisibilityIteratorTimeoutError(site, deadlineMs, count);
144
+ }
145
+ yield entry;
146
+ count++;
147
+ }
148
+ }
149
+ /**
150
+ * Compose `iterateWithDeadline` with the partial-tolerant catch pattern
151
+ * for sites that just want "log a warn, return what we got."
152
+ *
153
+ * Sites 2, 3, 5 use this; sites 1 + 4 use the raw iterator so they can
154
+ * carry the timeout signal into their return shape.
155
+ */
156
+ function isVisibilityTimeout(err) {
157
+ return err instanceof VisibilityIteratorTimeoutError;
158
+ }