agent-tempo 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/CLAUDE.md +253 -219
  2. package/LICENSE +21 -21
  3. package/README.md +293 -289
  4. package/assets/icon-dark.svg +9 -9
  5. package/assets/icon.svg +9 -9
  6. package/assets/logo-dark.svg +11 -11
  7. package/assets/logo-light.svg +11 -11
  8. package/dashboard/README.md +91 -91
  9. package/dashboard/dist/assets/{index-D6Xyje_n.js → index-jmYe6rmS.js} +2 -2
  10. package/dashboard/dist/assets/index-jmYe6rmS.js.map +1 -0
  11. package/dashboard/dist/index.html +20 -20
  12. package/dashboard/package.json +47 -47
  13. package/dist/activities/outbox.d.ts +30 -1
  14. package/dist/activities/outbox.js +96 -3
  15. package/dist/adapters/base.js +5 -0
  16. package/dist/adapters/copilot/adapter.js +12 -1
  17. package/dist/adapters/index.d.ts +1 -1
  18. package/dist/adapters/index.js +7 -0
  19. package/dist/adapters/pi/adapter.d.ts +2 -0
  20. package/dist/adapters/pi/adapter.js +43 -0
  21. package/dist/adapters/pi/index.d.ts +16 -0
  22. package/dist/adapters/pi/index.js +10 -0
  23. package/dist/cli/global-wrapper.d.ts +19 -0
  24. package/dist/cli/global-wrapper.js +169 -0
  25. package/dist/cli/help-text.js +97 -97
  26. package/dist/cli/startup.js +11 -0
  27. package/dist/cli/upgrade-command.js +81 -81
  28. package/dist/cli.js +12 -0
  29. package/dist/client/core.js +9 -2
  30. package/dist/client/interface.d.ts +6 -0
  31. package/dist/config.d.ts +79 -0
  32. package/dist/config.js +74 -0
  33. package/dist/daemon.js +37 -1
  34. package/dist/http/aggregate.d.ts +22 -1
  35. package/dist/http/aggregate.js +41 -0
  36. package/dist/http/auth.d.ts +94 -8
  37. package/dist/http/auth.js +93 -9
  38. package/dist/http/body.d.ts +4 -1
  39. package/dist/http/body.js +6 -3
  40. package/dist/http/event-bus.js +1 -0
  41. package/dist/http/event-types.d.ts +34 -2
  42. package/dist/http/event-types.js +1 -0
  43. package/dist/http/gate-audit.d.ts +12 -0
  44. package/dist/http/gate-audit.js +95 -0
  45. package/dist/http/gate-registry.d.ts +167 -0
  46. package/dist/http/gate-registry.js +163 -0
  47. package/dist/http/gate-routes.d.ts +48 -0
  48. package/dist/http/gate-routes.js +102 -0
  49. package/dist/http/ingest-registry.d.ts +30 -0
  50. package/dist/http/ingest-registry.js +108 -0
  51. package/dist/http/inner-loop-routes.d.ts +66 -0
  52. package/dist/http/inner-loop-routes.js +182 -0
  53. package/dist/http/inner-loop.d.ts +92 -0
  54. package/dist/http/inner-loop.js +155 -0
  55. package/dist/http/server.d.ts +38 -3
  56. package/dist/http/server.js +211 -6
  57. package/dist/http/snapshot.d.ts +6 -0
  58. package/dist/http/snapshot.js +6 -0
  59. package/dist/pi/cue-pump.d.ts +61 -0
  60. package/dist/pi/cue-pump.js +95 -0
  61. package/dist/pi/extension.d.ts +45 -0
  62. package/dist/pi/extension.js +407 -0
  63. package/dist/pi/gate-client.d.ts +54 -0
  64. package/dist/pi/gate-client.js +136 -0
  65. package/dist/pi/headless.d.ts +85 -0
  66. package/dist/pi/headless.js +224 -0
  67. package/dist/pi/index.d.ts +28 -0
  68. package/dist/pi/index.js +43 -0
  69. package/dist/pi/inner-loop-client.d.ts +67 -0
  70. package/dist/pi/inner-loop-client.js +164 -0
  71. package/dist/pi/inner-loop-publisher.d.ts +187 -0
  72. package/dist/pi/inner-loop-publisher.js +236 -0
  73. package/dist/pi/lazy-proxy.d.ts +37 -0
  74. package/dist/pi/lazy-proxy.js +55 -0
  75. package/dist/pi/mission-control/actions.d.ts +48 -0
  76. package/dist/pi/mission-control/actions.js +98 -0
  77. package/dist/pi/mission-control/board.d.ts +53 -0
  78. package/dist/pi/mission-control/board.js +104 -0
  79. package/dist/pi/mission-control/extension.d.ts +44 -0
  80. package/dist/pi/mission-control/extension.js +251 -0
  81. package/dist/pi/mission-control/index.d.ts +15 -0
  82. package/dist/pi/mission-control/index.js +32 -0
  83. package/dist/pi/mission-control/inner-tail.d.ts +48 -0
  84. package/dist/pi/mission-control/inner-tail.js +76 -0
  85. package/dist/pi/mission-control/pi-ui.d.ts +43 -0
  86. package/dist/pi/mission-control/pi-ui.js +10 -0
  87. package/dist/pi/mission-control/render.d.ts +6 -0
  88. package/dist/pi/mission-control/render.js +95 -0
  89. package/dist/pi/phase-driver.d.ts +74 -0
  90. package/dist/pi/phase-driver.js +122 -0
  91. package/dist/pi/pi-types.d.ts +208 -0
  92. package/dist/pi/pi-types.js +21 -0
  93. package/dist/pi/probe.d.ts +80 -0
  94. package/dist/pi/probe.js +154 -0
  95. package/dist/pi/render-tools.d.ts +17 -0
  96. package/dist/pi/render-tools.js +51 -0
  97. package/dist/pi/reset-pump.d.ts +47 -0
  98. package/dist/pi/reset-pump.js +85 -0
  99. package/dist/pi/tool-capability.d.ts +60 -0
  100. package/dist/pi/tool-capability.js +156 -0
  101. package/dist/pi/workflow-client.d.ts +158 -0
  102. package/dist/pi/workflow-client.js +289 -0
  103. package/dist/pi/zod-to-typebox.d.ts +74 -0
  104. package/dist/pi/zod-to-typebox.js +191 -0
  105. package/dist/scripts/verify-daemon-isolation-guard.js +24 -24
  106. package/dist/server-tools.d.ts +2 -0
  107. package/dist/server-tools.js +50 -46
  108. package/dist/server.js +4 -0
  109. package/dist/spawn.d.ts +55 -0
  110. package/dist/spawn.js +84 -12
  111. package/dist/tools/agent-types.d.ts +2 -2
  112. package/dist/tools/agent-types.js +22 -17
  113. package/dist/tools/attachment-info.d.ts +2 -2
  114. package/dist/tools/attachment-info.js +38 -33
  115. package/dist/tools/broadcast.d.ts +2 -2
  116. package/dist/tools/broadcast.js +69 -64
  117. package/dist/tools/cancel-stage.d.ts +2 -2
  118. package/dist/tools/cancel-stage.js +20 -15
  119. package/dist/tools/clear-state.d.ts +2 -2
  120. package/dist/tools/clear-state.js +25 -20
  121. package/dist/tools/coat-check-evict.d.ts +2 -2
  122. package/dist/tools/coat-check-evict.js +30 -25
  123. package/dist/tools/coat-check-get.d.ts +2 -2
  124. package/dist/tools/coat-check-get.js +39 -34
  125. package/dist/tools/coat-check-list.d.ts +2 -2
  126. package/dist/tools/coat-check-list.js +48 -43
  127. package/dist/tools/coat-check-put.d.ts +2 -2
  128. package/dist/tools/coat-check-put.js +41 -36
  129. package/dist/tools/cue.d.ts +2 -2
  130. package/dist/tools/cue.js +57 -52
  131. package/dist/tools/descriptor.d.ts +72 -0
  132. package/dist/tools/descriptor.js +39 -0
  133. package/dist/tools/destroy.d.ts +2 -2
  134. package/dist/tools/destroy.js +153 -148
  135. package/dist/tools/ensemble.d.ts +2 -2
  136. package/dist/tools/ensemble.js +71 -66
  137. package/dist/tools/evaluate-gate.d.ts +2 -2
  138. package/dist/tools/evaluate-gate.js +33 -27
  139. package/dist/tools/fetch-state.d.ts +2 -2
  140. package/dist/tools/fetch-state.js +43 -38
  141. package/dist/tools/gates.d.ts +2 -2
  142. package/dist/tools/gates.js +39 -34
  143. package/dist/tools/hosts.d.ts +2 -2
  144. package/dist/tools/hosts.js +25 -20
  145. package/dist/tools/listen.d.ts +2 -2
  146. package/dist/tools/listen.js +23 -18
  147. package/dist/tools/load-lineup.d.ts +2 -2
  148. package/dist/tools/load-lineup.js +324 -319
  149. package/dist/tools/migrate.d.ts +2 -2
  150. package/dist/tools/migrate.js +45 -40
  151. package/dist/tools/pause.d.ts +2 -2
  152. package/dist/tools/pause.js +34 -29
  153. package/dist/tools/play.d.ts +2 -2
  154. package/dist/tools/play.js +53 -48
  155. package/dist/tools/quality-gate.d.ts +2 -2
  156. package/dist/tools/quality-gate.js +26 -21
  157. package/dist/tools/recall.d.ts +2 -2
  158. package/dist/tools/recall.js +32 -27
  159. package/dist/tools/recruit.d.ts +2 -2
  160. package/dist/tools/recruit.js +325 -256
  161. package/dist/tools/release.d.ts +2 -2
  162. package/dist/tools/release.js +85 -80
  163. package/dist/tools/report.d.ts +2 -2
  164. package/dist/tools/report.js +28 -23
  165. package/dist/tools/reset.d.ts +3 -0
  166. package/dist/tools/reset.js +51 -0
  167. package/dist/tools/restart.d.ts +2 -2
  168. package/dist/tools/restart.js +51 -46
  169. package/dist/tools/restore.d.ts +2 -2
  170. package/dist/tools/restore.js +76 -71
  171. package/dist/tools/save-lineup.d.ts +2 -2
  172. package/dist/tools/save-lineup.js +32 -27
  173. package/dist/tools/save-state.d.ts +2 -2
  174. package/dist/tools/save-state.js +43 -38
  175. package/dist/tools/schedule.d.ts +2 -2
  176. package/dist/tools/schedule.js +133 -128
  177. package/dist/tools/schedules.d.ts +2 -2
  178. package/dist/tools/schedules.js +41 -36
  179. package/dist/tools/set-ensemble-description.d.ts +2 -2
  180. package/dist/tools/set-ensemble-description.js +26 -21
  181. package/dist/tools/set-name.d.ts +2 -2
  182. package/dist/tools/set-name.js +38 -33
  183. package/dist/tools/set-part.d.ts +2 -2
  184. package/dist/tools/set-part.js +20 -15
  185. package/dist/tools/shutdown.d.ts +2 -2
  186. package/dist/tools/shutdown.js +39 -34
  187. package/dist/tools/stage.d.ts +2 -2
  188. package/dist/tools/stage.js +28 -23
  189. package/dist/tools/stages.d.ts +2 -2
  190. package/dist/tools/stages.js +36 -31
  191. package/dist/tools/unschedule.d.ts +2 -2
  192. package/dist/tools/unschedule.js +30 -25
  193. package/dist/tools/who-am-i.d.ts +2 -2
  194. package/dist/tools/who-am-i.js +36 -31
  195. package/dist/tools/worktree.d.ts +2 -2
  196. package/dist/tools/worktree.js +134 -129
  197. package/dist/tui/index.js +6 -6
  198. package/dist/types.d.ts +47 -2
  199. package/dist/types.js +1 -1
  200. package/dist/utils/default-part.js +1 -0
  201. package/dist/utils/grpc-shutdown-guard.d.ts +52 -0
  202. package/dist/utils/grpc-shutdown-guard.js +88 -0
  203. package/dist/utils/sdk-probe.d.ts +23 -0
  204. package/dist/utils/sdk-probe.js +46 -7
  205. package/dist/worker.d.ts +3 -1
  206. package/dist/worker.js +6 -2
  207. package/dist/workflows/session.js +70 -2
  208. package/dist/workflows/signals.d.ts +32 -2
  209. package/dist/workflows/signals.js +25 -2
  210. package/examples/agents/tempo-composer.md +56 -56
  211. package/examples/agents/tempo-conductor.md +117 -117
  212. package/examples/agents/tempo-critic.md +73 -73
  213. package/examples/agents/tempo-improv.md +74 -74
  214. package/examples/agents/tempo-liner.md +75 -75
  215. package/examples/agents/tempo-roadie.md +61 -61
  216. package/examples/agents/tempo-soloist.md +71 -71
  217. package/examples/agents/tempo-tuner.md +94 -94
  218. package/examples/ensembles/tempo-big-band.yaml +146 -146
  219. package/examples/ensembles/tempo-dev-team.yaml +58 -58
  220. package/examples/ensembles/tempo-headless-jam.yaml +77 -77
  221. package/examples/ensembles/tempo-jam-session.yaml +41 -41
  222. package/examples/ensembles/tempo-mock-jam.yaml +79 -79
  223. package/examples/ensembles/tempo-review-squad.yaml +32 -32
  224. package/package.json +176 -173
  225. package/packaging/launchd/com.agent.tempo.plist +46 -46
  226. package/packaging/systemd/agent-tempo.service +32 -32
  227. package/packaging/windows/install-task.ps1 +71 -71
  228. package/scenarios/conductor-recruit-mock.yaml +33 -33
  229. package/scenarios/echo-roundtrip.yaml +15 -15
  230. package/scenarios/multi-player-handoff.yaml +38 -38
  231. package/scenarios/recruit-cascade.yaml +38 -38
  232. package/scenarios/two-player-conversation.yaml +33 -33
  233. package/workflow-bundle.js +97 -6
  234. package/dashboard/dist/assets/index-D6Xyje_n.js.map +0 -1
  235. package/dist/activities/claude-stop.d.ts +0 -21
  236. package/dist/activities/claude-stop.js +0 -94
  237. package/dist/channel.d.ts +0 -3
  238. package/dist/channel.js +0 -48
  239. package/dist/copilot-bridge.d.ts +0 -22
  240. package/dist/copilot-bridge.js +0 -565
  241. package/dist/scripts/258-spotcheck.js +0 -303
  242. package/dist/tools/detach.d.ts +0 -4
  243. package/dist/tools/detach.js +0 -45
  244. package/dist/tools/encore.d.ts +0 -4
  245. package/dist/tools/encore.js +0 -31
  246. package/dist/tools/helpers.d.ts +0 -21
  247. package/dist/tools/helpers.js +0 -25
  248. package/dist/tools/pause-ensemble.d.ts +0 -4
  249. package/dist/tools/pause-ensemble.js +0 -58
  250. package/dist/tools/resume-ensemble.d.ts +0 -4
  251. package/dist/tools/resume-ensemble.js +0 -79
  252. package/dist/tools/stop.d.ts +0 -4
  253. package/dist/tools/stop.js +0 -29
  254. package/dist/tui/client.d.ts +0 -6
  255. package/dist/tui/client.js +0 -9
  256. package/dist/tui/components/ActivityLog.d.ts +0 -16
  257. package/dist/tui/components/ActivityLog.js +0 -36
  258. package/dist/tui/components/CommandOverlay.d.ts +0 -15
  259. package/dist/tui/components/CommandOverlay.js +0 -34
  260. package/dist/tui/components/ConductorChat.d.ts +0 -16
  261. package/dist/tui/components/ConductorChat.js +0 -32
  262. package/dist/tui/components/EnsembleListView.d.ts +0 -14
  263. package/dist/tui/components/EnsembleListView.js +0 -32
  264. package/dist/tui/components/EnsemblePanel.d.ts +0 -12
  265. package/dist/tui/components/EnsemblePanel.js +0 -40
  266. package/dist/tui/components/InputBar.d.ts +0 -13
  267. package/dist/tui/components/InputBar.js +0 -58
  268. package/dist/tui/components/ScheduleOverlay.d.ts +0 -13
  269. package/dist/tui/components/ScheduleOverlay.js +0 -113
  270. package/dist/tui/components/TopBar.d.ts +0 -12
  271. package/dist/tui/components/TopBar.js +0 -15
  272. package/dist/tui/core-api.d.ts +0 -26
  273. package/dist/tui/core-api.js +0 -67
  274. package/dist/tui/hooks/useEnsembleDiscovery.d.ts +0 -3
  275. package/dist/tui/hooks/useEnsembleDiscovery.js +0 -30
  276. package/dist/tui/hooks/useMaestroPoller.d.ts +0 -3
  277. package/dist/tui/hooks/useMaestroPoller.js +0 -36
  278. package/dist/tui/hooks/useSendCommand.d.ts +0 -7
  279. package/dist/tui/hooks/useSendCommand.js +0 -29
  280. package/dist/utils/bg-preflight.d.ts +0 -25
  281. package/dist/utils/bg-preflight.js +0 -154
@@ -1,21 +1,21 @@
1
- <!doctype html>
2
- <html lang="en" data-theme="dark" data-density="6" data-accent="terracotta">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="color-scheme" content="dark light" />
7
- <meta name="description" content="agent-tempo Maestro Dashboard" />
8
- <title>agent-tempo · Maestro</title>
9
- <link rel="preconnect" href="https://fonts.googleapis.com" />
10
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
- <link
12
- rel="stylesheet"
13
- href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap"
14
- />
15
- <script type="module" crossorigin src="/dashboard/assets/index-D6Xyje_n.js"></script>
1
+ <!doctype html>
2
+ <html lang="en" data-theme="dark" data-density="6" data-accent="terracotta">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="dark light" />
7
+ <meta name="description" content="agent-tempo Maestro Dashboard" />
8
+ <title>agent-tempo · Maestro</title>
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link
12
+ rel="stylesheet"
13
+ href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap"
14
+ />
15
+ <script type="module" crossorigin src="/dashboard/assets/index-jmYe6rmS.js"></script>
16
16
  <link rel="stylesheet" crossorigin href="/dashboard/assets/index-CB78ToNE.css">
17
- </head>
18
- <body>
19
- <div id="root"></div>
20
- </body>
21
- </html>
17
+ </head>
18
+ <body>
19
+ <div id="root"></div>
20
+ </body>
21
+ </html>
@@ -1,47 +1,47 @@
1
- {
2
- "name": "agent-tempo-dashboard",
3
- "private": true,
4
- "version": "1.2.0",
5
- "type": "module",
6
- "description": "Web dashboard for agent-tempo. Bundled into the npm package; served by the daemon at /dashboard/*.",
7
- "scripts": {
8
- "dev": "vite",
9
- "build": "tsc -b && vite build",
10
- "build:overflow": "tsc -b && vite build --mode overflow",
11
- "preview": "vite preview",
12
- "lint": "eslint src/ tests/",
13
- "test": "vitest run",
14
- "test:watch": "vitest",
15
- "test:e2e": "playwright test",
16
- "test:e2e:install": "playwright install chromium",
17
- "test:overflow": "playwright test --config tests-overflow/playwright.config.ts"
18
- },
19
- "dependencies": {
20
- "@radix-ui/react-dialog": "~1.1.15",
21
- "@tanstack/react-query": "5.100.5",
22
- "react": "19.2.5",
23
- "react-dom": "19.2.5",
24
- "react-router-dom": "7.14.2",
25
- "zustand": "^5.0.0"
26
- },
27
- "devDependencies": {
28
- "@eslint/js": "^9.0.0",
29
- "@playwright/test": "^1.50.0",
30
- "@tailwindcss/vite": "4.2.4",
31
- "@testing-library/dom": "^10.0.0",
32
- "@testing-library/jest-dom": "^6.6.0",
33
- "@testing-library/react": "^16.1.0",
34
- "@types/node": "^22.0.0",
35
- "@types/react": "^19.2.0",
36
- "@types/react-dom": "^19.2.0",
37
- "@typescript-eslint/parser": "^8.0.0",
38
- "@vitejs/plugin-react": "^5.0.0",
39
- "eslint": "^9.0.0",
40
- "eslint-plugin-react-hooks": "^5.1.0",
41
- "jsdom": "^25.0.0",
42
- "tailwindcss": "4.2.4",
43
- "typescript": "^5.7.0",
44
- "vite": "8.0.10",
45
- "vitest": "^2.1.9"
46
- }
47
- }
1
+ {
2
+ "name": "agent-tempo-dashboard",
3
+ "private": true,
4
+ "version": "1.4.0",
5
+ "type": "module",
6
+ "description": "Web dashboard for agent-tempo. Bundled into the npm package; served by the daemon at /dashboard/*.",
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "tsc -b && vite build",
10
+ "build:overflow": "tsc -b && vite build --mode overflow",
11
+ "preview": "vite preview",
12
+ "lint": "eslint src/ tests/",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "test:e2e": "playwright test",
16
+ "test:e2e:install": "playwright install chromium",
17
+ "test:overflow": "playwright test --config tests-overflow/playwright.config.ts"
18
+ },
19
+ "dependencies": {
20
+ "@radix-ui/react-dialog": "~1.1.15",
21
+ "@tanstack/react-query": "5.100.5",
22
+ "react": "19.2.5",
23
+ "react-dom": "19.2.5",
24
+ "react-router-dom": "7.14.2",
25
+ "zustand": "^5.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@eslint/js": "^9.0.0",
29
+ "@playwright/test": "^1.50.0",
30
+ "@tailwindcss/vite": "4.2.4",
31
+ "@testing-library/dom": "^10.0.0",
32
+ "@testing-library/jest-dom": "^6.6.0",
33
+ "@testing-library/react": "^16.1.0",
34
+ "@types/node": "^22.0.0",
35
+ "@types/react": "^19.2.0",
36
+ "@types/react-dom": "^19.2.0",
37
+ "@typescript-eslint/parser": "^8.0.0",
38
+ "@vitejs/plugin-react": "^5.0.0",
39
+ "eslint": "^9.0.0",
40
+ "eslint-plugin-react-hooks": "^5.1.0",
41
+ "jsdom": "^25.0.0",
42
+ "tailwindcss": "4.2.4",
43
+ "typescript": "^5.7.0",
44
+ "vite": "8.0.10",
45
+ "vitest": "^2.1.9"
46
+ }
47
+ }
@@ -2,6 +2,8 @@ import { Client } from '@temporalio/client';
2
2
  import { Config } from '../config';
3
3
  import { AgentType, MockMode, DetachReason } from '../types';
4
4
  import type { ClaudeCodeHeadlessPermissionMode } from '../adapters/claude-code-headless/types';
5
+ import type { IngestTokenRegistry } from '../http/ingest-registry';
6
+ import type { GateRegistry } from '../http/gate-registry';
5
7
  import { type HardTerminateInput, type HardTerminateResult } from './hard-terminate';
6
8
  export interface DeliverCueInput {
7
9
  ensemble: string;
@@ -76,6 +78,17 @@ export interface DeliverDestroyInput {
76
78
  terminatedBy: string;
77
79
  notifyConductor?: boolean;
78
80
  }
81
+ export interface DeliverResetInput {
82
+ ensemble: string;
83
+ targetPlayerId: string;
84
+ /** Correlation id (the originating outbox entry id) — the extension acks with it. */
85
+ resetId: string;
86
+ /** Clean-wipe (D14 default true). */
87
+ fresh: boolean;
88
+ reason?: string;
89
+ /** Who requested the reset (audit). */
90
+ requestedBy?: string;
91
+ }
79
92
  export interface DeliverRestartInput {
80
93
  ensemble: string;
81
94
  targetPlayerId: string;
@@ -155,6 +168,14 @@ export interface SpawnProcessInput {
155
168
  * exclusive with {@link permissionMode}.
156
169
  */
157
170
  dangerouslySkipPermissions?: boolean;
171
+ /**
172
+ * Phase 3a / MD-C — headless Pi tool-class policy. Forwarded as
173
+ * `AGENT_TEMPO_TOOL_ACCESS`. Only meaningful when `agent === 'pi'`. One of
174
+ * `'restricted'` (default; Bash hard-blocked) | `'standard'` | `'full'`.
175
+ * Inline literal — kept off the workflow-sandbox import path (see the
176
+ * RecruitOutboxEntry note in src/types.ts).
177
+ */
178
+ toolAccess?: 'restricted' | 'standard' | 'full';
158
179
  }
159
180
  export interface OutboxActivityResult {
160
181
  success: boolean;
@@ -174,6 +195,7 @@ export interface OutboxActivities {
174
195
  deliverDetach(input: DeliverDetachInput): Promise<OutboxActivityResult>;
175
196
  deliverDestroy(input: DeliverDestroyInput): Promise<OutboxActivityResult>;
176
197
  deliverRestart(input: DeliverRestartInput): Promise<OutboxActivityResult>;
198
+ deliverReset(input: DeliverResetInput): Promise<OutboxActivityResult>;
177
199
  /**
178
200
  * OS-level child-process-tree kill for the target session. Runs on the per-host
179
201
  * task queue (`agent-tempo-{hostname}`) so the kill happens where the process
@@ -184,5 +206,12 @@ export interface OutboxActivities {
184
206
  /**
185
207
  * Create outbox delivery activities bound to a Temporal client and config.
186
208
  * The returned object is registered with the worker as activities.
209
+ *
210
+ * @param ingestTokens 3c Tier-2 ingest-auth registry (daemon-owned singleton,
211
+ * shared with the HTTP `/inner/ingest` + `/inner/presence` validators). The pi
212
+ * spawn branch MINTS a per-player token here (single-token-per-workflowId —
213
+ * re-mint REPLACES, so a restart naturally revokes the stale token); the
214
+ * destroy path REVOKES it. Optional: undefined disables ingest-token minting
215
+ * (e.g. the dev test harness that constructs activities without the daemon).
187
216
  */
188
- export declare function createOutboxActivities(client: Client, config: Config): OutboxActivities;
217
+ export declare function createOutboxActivities(client: Client, config: Config, ingestTokens?: IngestTokenRegistry, gate?: GateRegistry): OutboxActivities;
@@ -136,8 +136,15 @@ function classifyAndRethrow(err, contextPrefix) {
136
136
  /**
137
137
  * Create outbox delivery activities bound to a Temporal client and config.
138
138
  * The returned object is registered with the worker as activities.
139
+ *
140
+ * @param ingestTokens 3c Tier-2 ingest-auth registry (daemon-owned singleton,
141
+ * shared with the HTTP `/inner/ingest` + `/inner/presence` validators). The pi
142
+ * spawn branch MINTS a per-player token here (single-token-per-workflowId —
143
+ * re-mint REPLACES, so a restart naturally revokes the stale token); the
144
+ * destroy path REVOKES it. Optional: undefined disables ingest-token minting
145
+ * (e.g. the dev test harness that constructs activities without the daemon).
139
146
  */
140
- function createOutboxActivities(client, config) {
147
+ function createOutboxActivities(client, config, ingestTokens, gate) {
141
148
  return {
142
149
  async deliverCue(input) {
143
150
  const { ensemble, fromPlayerId, targetPlayerId, message, broadcastId, attachmentTicket } = input;
@@ -247,7 +254,7 @@ function createOutboxActivities(client, config) {
247
254
  // across CAN. Both adapters use the same `model` metadata field
248
255
  // (different value shapes — bare vs `provider/model`) — the spawn
249
256
  // path inspects `metadata.agentType` to know which env var to set.
250
- ...((agent === 'claude-api' || agent === 'opencode') && model ? { model } : {}),
257
+ ...((agent === 'claude-api' || agent === 'opencode' || agent === 'pi') && model ? { model } : {}),
251
258
  ...(agentDefinition ? { playerType: agentDefinition } : {}),
252
259
  ...(agentDefinitionDescription ? { playerTypeDescription: agentDefinitionDescription } : {}),
253
260
  recruitedBy: fromPlayerId,
@@ -305,7 +312,7 @@ function createOutboxActivities(client, config) {
305
312
  }
306
313
  },
307
314
  async spawnProcess(input) {
308
- const { targetName, workDir, isConductor, agent, systemPrompt, ensemble, temporalAddress, temporalNamespace, agentDefinition, agentDefinitionPath, nativeResolvable, resume, sessionId, allowedTools, claudeBin, attachmentId, attachmentRunId, adapterId, mockMode, mockScenario, model, permissionMode, dangerouslySkipPermissions } = input;
315
+ const { targetName, workDir, isConductor, agent, systemPrompt, ensemble, temporalAddress, temporalNamespace, agentDefinition, agentDefinitionPath, nativeResolvable, resume, sessionId, allowedTools, claudeBin, attachmentId, attachmentRunId, adapterId, mockMode, mockScenario, model, permissionMode, dangerouslySkipPermissions, toolAccess } = input;
309
316
  // Read secrets from the worker's config closure — never from workflow state
310
317
  const { temporalApiKey, temporalTlsCertPath, temporalTlsKeyPath } = config;
311
318
  try {
@@ -436,6 +443,43 @@ function createOutboxActivities(client, config) {
436
443
  });
437
444
  log(`Spawned claude-code-headless adapter (pid ${pid}) in ${workDir} as "${targetName}"${permissionMode ? ` (permissionMode=${permissionMode})` : ''}${dangerouslySkipPermissions ? ' (dangerouslySkipPermissions=true)' : ''}${attachmentId ? ` (attachmentId=${attachmentId})` : ''}`);
438
445
  }
446
+ else if (agent === 'pi') {
447
+ // Phase 3a — headless Pi runtime. Injects the src/pi extension into
448
+ // Pi's createAgentSession; the module-scope singleton owns the
449
+ // lifecycle (claim/heartbeat/tools/cue-pump). Tool access is governed
450
+ // by the MD-C `toolAccess` policy (restricted hard-blocks Bash via the
451
+ // extension's tool_call gate), NOT per-tool allowlists.
452
+ if (allowedTools && allowedTools.length > 0) {
453
+ log(`Warning: allowedTools [${allowedTools.join(', ')}] specified for pi agent "${targetName}" — Pi tool access is governed by toolAccess (MD-C), skipping allowedTools`);
454
+ }
455
+ // 3c Tier-2 — mint a per-player ingest token scoped to this player's
456
+ // session workflowId so the headless Pi subprocess can authenticate its
457
+ // `POST /inner/ingest` frames. Single-token-per-workflowId (mint
458
+ // REPLACES) means a restart re-mints and naturally revokes the stale
459
+ // token. Injected into the subprocess env as AGENT_TEMPO_INGEST_TOKEN.
460
+ const ingestToken = ingestTokens?.mint((0, config_1.sessionWorkflowId)(ensemble, targetName));
461
+ const { pid } = (0, spawn_1.spawnPiHeadless)({
462
+ name: targetName,
463
+ ensemble,
464
+ temporalAddress,
465
+ temporalNamespace,
466
+ temporalApiKey,
467
+ temporalTlsCertPath,
468
+ temporalTlsKeyPath,
469
+ isConductor,
470
+ workDir,
471
+ model,
472
+ // Restart-resume: continue the prior Pi conversation only on a
473
+ // restart (resume=true); a fresh recruit starts a new Pi session.
474
+ continueSessionId: resume ? sessionId : undefined,
475
+ toolAccess,
476
+ attachmentId,
477
+ attachmentRunId,
478
+ adapterId,
479
+ ingestToken,
480
+ });
481
+ log(`Spawned pi headless adapter (pid ${pid}) in ${workDir} as "${targetName}" (toolAccess=${toolAccess ?? 'restricted'})${model ? ` (model=${model})` : ''}${resume && sessionId ? ` (continue=${sessionId})` : ''}${attachmentId ? ` (attachmentId=${attachmentId})` : ''}`);
482
+ }
439
483
  else {
440
484
  // Resolve agent flags: --agent (native) > --system-prompt (shipped/legacy)
441
485
  let agentFlags = [];
@@ -551,6 +595,14 @@ function createOutboxActivities(client, config) {
551
595
  throw activity_1.ApplicationFailure.nonRetryable(`Cannot detach "${targetPlayerId}" — session is destroyed`);
552
596
  }
553
597
  await handle.signal(signals_1.requestDetachSignal, { reason, deadlineMs });
598
+ // 3c Tier-2 — revoke the player's ingest token on detach so a dead
599
+ // holder's loopback POST /inner/ingest can no longer authenticate once
600
+ // the player goes away. Mirrors the destroy-side revoke; idempotent and a
601
+ // no-op for non-Pi players (they never minted one). Re-attach re-mints.
602
+ ingestTokens?.revoke((0, config_1.sessionWorkflowId)(ensemble, targetPlayerId));
603
+ // 3d MD-G — auto-disarm the gate on detach (the operator's gate posture
604
+ // shouldn't survive the player going away; re-attach re-arms). Idempotent.
605
+ gate?.clearPlayer((0, config_1.sessionWorkflowId)(ensemble, targetPlayerId));
554
606
  log(`Detach signaled for "${targetPlayerId}" (deadline=${deadlineMs}ms)`);
555
607
  return { success: true };
556
608
  }
@@ -580,6 +632,21 @@ function createOutboxActivities(client, config) {
580
632
  }],
581
633
  });
582
634
  log(`Destroyed "${targetPlayerId}"${reason ? ` (reason: ${reason})` : ''}`);
635
+ // 3c Tier-2 — revoke the player's ingest token on destroy so a dead
636
+ // holder's loopback POST /inner/ingest can no longer authenticate.
637
+ // Idempotent; a no-op for non-Pi players (they never minted one).
638
+ // NOTE (security cond. 2): the ingest endpoint authenticates on TOKEN
639
+ // ALONE — it does not inspect workflow phase (neither rejects nor
640
+ // buffers detached-phase players). So the residual surface is bounded
641
+ // not by phase-checking but by (a) this destroy-revoke and (b) the
642
+ // single-token-per-workflowId replacement on re-attach/restart.
643
+ // TODO(Phase 4): wire aggregate player-gone detection →
644
+ // revokeIngestToken(workflowId) on detach — deferred; residual surface
645
+ // negligible (dead holder + loopback-only + single-token replacement).
646
+ ingestTokens?.revoke((0, config_1.sessionWorkflowId)(ensemble, targetPlayerId));
647
+ // 3d MD-G — auto-disarm: drop the gate's armed-state + any pending
648
+ // requests for the destroyed player (idempotent; no-op for non-Pi).
649
+ gate?.clearPlayer((0, config_1.sessionWorkflowId)(ensemble, targetPlayerId));
583
650
  if (notifyConductor) {
584
651
  try {
585
652
  const condId = (0, config_1.conductorWorkflowId)(ensemble);
@@ -603,6 +670,32 @@ function createOutboxActivities(client, config) {
603
670
  classifyAndRethrow(err, `Destroy failed for "${targetPlayerId}"`);
604
671
  }
605
672
  },
673
+ /**
674
+ * D14 `deliverReset` — set a `pendingReset` flag on the target via
675
+ * `setPendingResetSignal` (a signal, like deliverCue — NOT a direct
676
+ * subprocess call). The Pi extension polls `pendingResetQuery`, performs the
677
+ * clean-wipe (`newSession`), then clears it via `ackResetSignal(resetId)`.
678
+ */
679
+ async deliverReset(input) {
680
+ const { ensemble, targetPlayerId, resetId, fresh, reason, requestedBy } = input;
681
+ try {
682
+ const handle = await (0, resolve_1.resolveSession)(client, ensemble, targetPlayerId);
683
+ if (!handle) {
684
+ throw activity_1.ApplicationFailure.nonRetryable(`No session found for "${targetPlayerId}"`);
685
+ }
686
+ await handle.signal(signals_1.setPendingResetSignal, {
687
+ resetId,
688
+ fresh,
689
+ ...(reason !== undefined ? { reason } : {}),
690
+ ...(requestedBy !== undefined ? { requestedBy } : {}),
691
+ });
692
+ log(`Reset queued for "${targetPlayerId}"${reason ? ` (reason: ${reason})` : ''}`);
693
+ return { success: true };
694
+ }
695
+ catch (err) {
696
+ classifyAndRethrow(err, `Reset failed for "${targetPlayerId}"`);
697
+ }
698
+ },
606
699
  /**
607
700
  * PR-D `deliverRestart` — owns the §8.2 restart algorithm on the target.
608
701
  * Graceful `requestDetach` → re-query phase → `forceDetach` (if --force
@@ -1264,6 +1264,11 @@ class AdapterRegistry {
1264
1264
  // Claude Code OAuth login so turns bill against subscription extra-usage.
1265
1265
  if (agent === 'claude-code-headless')
1266
1266
  return 'claude-code-headless';
1267
+ // Phase 3a — headless Pi runtime. The 'pi' descriptor is registry/identity
1268
+ // ONLY: the module-scope Pi extension singleton owns claim/heartbeat/phase
1269
+ // (no BaseAttachment subprocess driver). Opt-in via `recruit({ agent: 'pi' })`.
1270
+ if (agent === 'pi')
1271
+ return 'pi';
1267
1272
  return 'claude-code';
1268
1273
  }
1269
1274
  }
@@ -274,6 +274,7 @@ class CopilotSdkAttachment extends base_1.SdkAttachment {
274
274
  // Spawn Copilot SDK client and session
275
275
  const copilotClient = new CopilotClient({
276
276
  logLevel: 'debug',
277
+ workingDirectory: workDir,
277
278
  env: {
278
279
  ...cleanEnv(),
279
280
  ...(process.env.GITHUB_TOKEN ? { GITHUB_TOKEN: process.env.GITHUB_TOKEN } : {}),
@@ -286,7 +287,6 @@ class CopilotSdkAttachment extends base_1.SdkAttachment {
286
287
  // All tool calls are auto-approved by design — the bridge operator accepts
287
288
  // this when launching the bridge process.
288
289
  onPermissionRequest: approveAll,
289
- workingDirectory: workDir,
290
290
  mcpServers: {
291
291
  'agent-tempo': {
292
292
  command: serverCommand,
@@ -302,6 +302,17 @@ class CopilotSdkAttachment extends base_1.SdkAttachment {
302
302
  // `--append-system-prompt` argv. Behavior here is unchanged.
303
303
  content: (0, system_prompt_1.buildSdkSystemPrompt)({ ensemble: config.ensemble }),
304
304
  },
305
+ hooks: {
306
+ // Auto-allow agent-tempo MCP tools to skip the permission prompt round-trip.
307
+ // This eliminates the permission.requested → handler → approval cycle for
308
+ // every MCP tool call, reducing latency.
309
+ onPreToolUse: async (input) => {
310
+ if (input.toolName?.startsWith('mcp__agent-tempo__')) {
311
+ return { permissionDecision: 'allow' };
312
+ }
313
+ return undefined;
314
+ },
315
+ },
305
316
  excludedTools: ['write_powershell', 'read_powershell', 'list_powershell'],
306
317
  ...(model ? { model } : {}),
307
318
  };
@@ -31,7 +31,7 @@ export declare const registry: AdapterRegistry;
31
31
  * Mock adapter is intentionally excluded — it's dev-mode-only and stripped
32
32
  * from the npm tarball at prepack time (ADR 0014 §7 gate 1).
33
33
  */
34
- export declare const CANONICAL_ADAPTER_IDS: readonly ["claude-code", "copilot", "claude-api", "opencode", "claude-code-headless"];
34
+ export declare const CANONICAL_ADAPTER_IDS: readonly ["claude-code", "copilot", "claude-api", "opencode", "claude-code-headless", "pi"];
35
35
  export { BaseAttachment, AdapterRegistry } from './base';
36
36
  export { SdkAttachment } from './sdk/base';
37
37
  export { InteractiveAttachment } from './claude-code';
@@ -24,6 +24,7 @@ const copilot_1 = require("./copilot");
24
24
  const claude_api_1 = require("./claude-api");
25
25
  const opencode_1 = require("./opencode");
26
26
  const claude_code_headless_1 = require("./claude-code-headless");
27
+ const pi_1 = require("./pi");
27
28
  const config_1 = require("../config");
28
29
  exports.registry = new base_1.AdapterRegistry();
29
30
  exports.registry.register(claude_code_1.claudeCodeDescriptor);
@@ -45,6 +46,11 @@ exports.registry.register(opencode_1.opencodeDescriptor);
45
46
  // `claude` binary is a system binary, not an npm dep; recruit pre-flight
46
47
  // probes for installation + login state via `pre-flight.ts`.
47
48
  exports.registry.register(claude_code_headless_1.claudeCodeHeadlessDescriptor);
49
+ // Phase 3a — headless Pi runtime. Registry/identity descriptor ONLY: the Pi
50
+ // extension singleton (Phase 2) owns the lifecycle, not a BaseAttachment driver
51
+ // (MD-D). Always-registered — the optional `@earendil-works/pi-coding-agent` SDK
52
+ // only matters at spawn time; recruit pre-flight gates on it (or `force: true`).
53
+ exports.registry.register(pi_1.piDescriptor);
48
54
  /**
49
55
  * Canonical list of production adapters registered at module-import time.
50
56
  *
@@ -65,6 +71,7 @@ exports.CANONICAL_ADAPTER_IDS = [
65
71
  'claude-api',
66
72
  'opencode',
67
73
  'claude-code-headless',
74
+ 'pi',
68
75
  ];
69
76
  // ADR 0014 §7 gate 2 — import-time registration gate. The mock adapter's
70
77
  // descriptor only enters the registry when `isDevMode()` is true.
@@ -0,0 +1,2 @@
1
+ /** Parse the spawn-provided env into options and run. Exported for testing. */
2
+ export declare function main(): Promise<void>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = main;
4
+ /**
5
+ * Headless Pi adapter entry point (Phase 3a). Spawned as a detached subprocess
6
+ * by `spawnPiHeadless` (src/spawn.ts) on a recruited `agent: 'pi'`. Reads its
7
+ * config from the env the spawn set, then delegates to `runHeadlessPi`, which
8
+ * injects the agent-tempo extension into Pi's `createAgentSession`.
9
+ *
10
+ * Unlike the other headless adapters, there is NO `BaseAttachment` driver here:
11
+ * the module-scope Pi extension singleton (Phase 2) owns claim / heartbeat /
12
+ * phase / tool registration / cue pump (MD-D). This file is purely the process
13
+ * entry + env→options wiring.
14
+ *
15
+ * Dual-purpose: importing this module is inert; only running it as the process
16
+ * entry (`require.main === module`) boots the runtime.
17
+ */
18
+ const config_1 = require("../../config");
19
+ const headless_1 = require("../../pi/headless");
20
+ const log = (...args) => {
21
+ // eslint-disable-next-line no-console
22
+ console.error('[agent-tempo:pi]', ...args);
23
+ };
24
+ /** Normalize the env tool-access value to the MD-C policy (default 'restricted'). */
25
+ function readToolAccess() {
26
+ const raw = process.env[config_1.ENV.TOOL_ACCESS];
27
+ return raw === 'standard' || raw === 'full' ? raw : 'restricted';
28
+ }
29
+ /** Parse the spawn-provided env into options and run. Exported for testing. */
30
+ async function main() {
31
+ await (0, headless_1.runHeadlessPi)({
32
+ toolAccess: readToolAccess(),
33
+ model: process.env[config_1.ENV.PI_MODEL] || undefined,
34
+ continueSessionId: process.env[config_1.ENV.PI_CONTINUE_SESSION] || undefined,
35
+ });
36
+ }
37
+ if (require.main === module) {
38
+ main().catch((err) => {
39
+ log('FATAL — headless Pi adapter crashed:', err instanceof Error ? (err.stack ?? err.message) : err);
40
+ // eslint-disable-next-line no-process-exit
41
+ process.exit(1);
42
+ });
43
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Pi adapter — registry/identity descriptor ONLY (Phase 3a).
3
+ *
4
+ * Unlike the other headless adapters (copilot / opencode / claude-api /
5
+ * claude-code-headless), Pi does NOT have a `BaseAttachment` subprocess driver.
6
+ * The headless Pi runtime injects the Phase 2 `src/pi` EXTENSION into Pi's
7
+ * `createAgentSession` as an inline factory; the module-scope extension singleton
8
+ * owns claim / heartbeat / phase / tool registration / cue pump (MD-D). This
9
+ * descriptor exists purely for adapter identity, registry resolution, spawn
10
+ * routing, and heartbeat-cadence config (MD-A: 30s heartbeat, lease = 3×).
11
+ *
12
+ * Spawn entry: `src/adapters/pi/adapter.ts` (A2) → `src/pi/headless.ts`.
13
+ */
14
+ import type { AdapterDescriptor } from '../../types';
15
+ /** Pi headless adapter descriptor. `sdk` class (blocks on the LLM turn); 30s heartbeat. */
16
+ export declare const piDescriptor: AdapterDescriptor;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.piDescriptor = void 0;
4
+ /** Pi headless adapter descriptor. `sdk` class (blocks on the LLM turn); 30s heartbeat. */
5
+ exports.piDescriptor = {
6
+ adapterId: 'pi',
7
+ adapterClass: 'sdk',
8
+ blocksOnLLMTurn: true,
9
+ heartbeatMs: 30_000,
10
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Refresh the entrypoint pointer so the global wrapper resolves to the
3
+ * currently-running binary. Called on every successful CLI boot — cheap
4
+ * (one `writeFileSync`) and idempotent.
5
+ */
6
+ export declare function refreshEntrypoint(): void;
7
+ /**
8
+ * Ensure the wrapper scripts exist. Called once per binary version (guarded
9
+ * by the bootstrap cache). Returns `true` if a PATH hint should be shown
10
+ * to the user (i.e., the bin dir is not yet on PATH).
11
+ */
12
+ export declare function provisionWrapperScripts(): {
13
+ created: boolean;
14
+ needsPathHint: boolean;
15
+ };
16
+ /**
17
+ * Returns a one-liner PATH hint appropriate for the current platform/shell.
18
+ */
19
+ export declare function getPathHint(): string;