@ours.network/fleet 1.2.0-nightly.3 → 1.2.0-nightly.31

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 (458) hide show
  1. package/README.md +158 -28
  2. package/dist/account-origin.d.ts +2 -0
  3. package/dist/account-origin.js +6 -0
  4. package/dist/agent-ours/bridge.d.ts +3 -0
  5. package/dist/agent-ours/bridge.js +178 -0
  6. package/dist/agent-ours/controller.d.ts +14 -0
  7. package/dist/agent-ours/controller.js +60 -0
  8. package/dist/agent-ours/correspondence.d.ts +10 -0
  9. package/dist/agent-ours/correspondence.js +1 -0
  10. package/dist/agent-ours/file-rpc.d.ts +23 -0
  11. package/dist/agent-ours/file-rpc.js +123 -0
  12. package/dist/agent-ours/harness.d.ts +14 -0
  13. package/dist/agent-ours/harness.js +72 -0
  14. package/dist/agent-ours/mcp-endpoint.d.ts +15 -0
  15. package/dist/agent-ours/mcp-endpoint.js +111 -0
  16. package/dist/agent-ours/runtime.d.ts +59 -0
  17. package/dist/agent-ours/runtime.js +283 -0
  18. package/dist/agent-ours/service.d.ts +23 -0
  19. package/dist/agent-ours/service.js +372 -0
  20. package/dist/agent-ours/state.d.ts +45 -0
  21. package/dist/agent-ours/state.js +95 -0
  22. package/dist/agent-ours/wire.d.ts +14 -0
  23. package/dist/agent-ours/wire.js +55 -0
  24. package/dist/application/conversation-history.d.ts +25 -0
  25. package/dist/application/conversation-history.js +189 -0
  26. package/dist/application/fleet-query-service.d.ts +1 -1
  27. package/dist/application/fleet-query-service.js +2 -2
  28. package/dist/application/legacy-supervisor-identity.d.ts +7 -0
  29. package/dist/application/legacy-supervisor-identity.js +43 -0
  30. package/dist/application/model-catalog.d.ts +1 -1
  31. package/dist/application/model-catalog.js +5 -2
  32. package/dist/application/preset-provenance.d.ts +19 -0
  33. package/dist/application/preset-provenance.js +59 -0
  34. package/dist/application/room-layout-definitions.d.ts +45 -0
  35. package/dist/application/room-layout-definitions.js +130 -0
  36. package/dist/application/session-control.d.ts +18 -0
  37. package/dist/application/session-control.js +54 -3
  38. package/dist/application/supervisor-ours-tools.d.ts +159 -0
  39. package/dist/application/supervisor-ours-tools.js +113 -0
  40. package/dist/application/task-layouts.d.ts +91 -0
  41. package/dist/application/task-layouts.js +249 -0
  42. package/dist/application/task-room-service.d.ts +99 -3
  43. package/dist/application/task-room-service.js +296 -31
  44. package/dist/atomic-file.d.ts +5 -0
  45. package/dist/atomic-file.js +62 -1
  46. package/dist/briefing.js +10 -59
  47. package/dist/build-info.json +6 -4
  48. package/dist/capabilities.d.ts +3 -1
  49. package/dist/capabilities.js +4 -0
  50. package/dist/cli.js +131 -5
  51. package/dist/client-profile.d.ts +5 -16
  52. package/dist/client-profile.js +4 -112
  53. package/dist/config.d.ts +4 -0
  54. package/dist/config.js +7 -0
  55. package/dist/creation.d.ts +1 -1
  56. package/dist/creation.js +5 -16
  57. package/dist/daemon-recovery.d.ts +1 -8
  58. package/dist/daemon-recovery.js +8 -113
  59. package/dist/docs.d.ts +3 -3
  60. package/dist/docs.js +43 -23
  61. package/dist/doctor.d.ts +1 -1
  62. package/dist/doctor.js +46 -59
  63. package/dist/erased-resources.d.ts +9 -0
  64. package/dist/erased-resources.js +87 -0
  65. package/dist/fleet-command-audit.d.ts +1 -0
  66. package/dist/fleet-command-audit.js +12 -7
  67. package/dist/harness/agent-session.d.ts +2 -0
  68. package/dist/harness/claude-code-session.js +4 -2
  69. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  70. package/dist/harness/codex-app-server-proxy.js +41 -5
  71. package/dist/harness/codex-session.js +9 -2
  72. package/dist/harness/codex.d.ts +3 -2
  73. package/dist/harness/codex.js +4 -3
  74. package/dist/harness/hermes-session.js +7 -1
  75. package/dist/init-wizard.js +20 -9
  76. package/dist/isolation/policy.js +2 -0
  77. package/dist/isolation/types.d.ts +5 -0
  78. package/dist/monitor.d.ts +1 -34
  79. package/dist/monitor.js +24 -151
  80. package/dist/notifications/fleet-producer.d.ts +18 -0
  81. package/dist/notifications/fleet-producer.js +129 -0
  82. package/dist/notifications/outbox.d.ts +31 -0
  83. package/dist/notifications/outbox.js +104 -0
  84. package/dist/owner-channel/channel.d.ts +3 -0
  85. package/dist/owner-channel/channel.js +34 -6
  86. package/dist/owner-channel/commands.d.ts +4 -0
  87. package/dist/owner-channel/commands.js +8 -0
  88. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  89. package/dist/owner-channel/ours-client.js +2 -17
  90. package/dist/preset-migration.js +15 -0
  91. package/dist/rooms-tasks/add-member.d.ts +48 -0
  92. package/dist/rooms-tasks/add-member.js +83 -0
  93. package/dist/rooms-tasks/archived-absence.d.ts +8 -0
  94. package/dist/rooms-tasks/archived-absence.js +48 -0
  95. package/dist/rooms-tasks/cli.js +34 -5
  96. package/dist/rooms-tasks/close.d.ts +5 -2
  97. package/dist/rooms-tasks/close.js +208 -28
  98. package/dist/rooms-tasks/config.js +3 -1
  99. package/dist/rooms-tasks/cowork-adapter.d.ts +6 -4
  100. package/dist/rooms-tasks/cowork-adapter.js +11 -117
  101. package/dist/rooms-tasks/cowork-http.d.ts +3 -0
  102. package/dist/rooms-tasks/cowork-http.js +70 -0
  103. package/dist/rooms-tasks/deletion.d.ts +1 -1
  104. package/dist/rooms-tasks/deletion.js +74 -5
  105. package/dist/rooms-tasks/erasure.d.ts +6 -0
  106. package/dist/rooms-tasks/erasure.js +169 -0
  107. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  108. package/dist/rooms-tasks/external-worker.js +3 -4
  109. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  110. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  111. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  112. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  113. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  114. package/dist/rooms-tasks/layout-cli.js +107 -0
  115. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  116. package/dist/rooms-tasks/layout-config.js +89 -0
  117. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  118. package/dist/rooms-tasks/layout-control.js +52 -0
  119. package/dist/rooms-tasks/layout-service.d.ts +42 -0
  120. package/dist/rooms-tasks/layout-service.js +185 -0
  121. package/dist/rooms-tasks/layout.d.ts +114 -0
  122. package/dist/rooms-tasks/layout.js +250 -0
  123. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  124. package/dist/rooms-tasks/live-readiness.js +85 -0
  125. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  126. package/dist/rooms-tasks/member-startup.js +2 -0
  127. package/dist/rooms-tasks/provision.d.ts +14 -0
  128. package/dist/rooms-tasks/provision.js +182 -48
  129. package/dist/rooms-tasks/room-state.d.ts +4 -2
  130. package/dist/rooms-tasks/room-state.js +53 -8
  131. package/dist/rooms-tasks/task-state.d.ts +42 -7
  132. package/dist/rooms-tasks/task-state.js +153 -23
  133. package/dist/rooms-tasks/types.d.ts +28 -0
  134. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  135. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  136. package/dist/rooms-tasks/workspace.d.ts +26 -0
  137. package/dist/rooms-tasks/workspace.js +195 -0
  138. package/dist/runner.d.ts +23 -3
  139. package/dist/runner.js +581 -494
  140. package/dist/session/acp.d.ts +3 -0
  141. package/dist/session/acp.js +14 -0
  142. package/dist/session/arbiter.d.ts +3 -0
  143. package/dist/session/arbiter.js +20 -2
  144. package/dist/session/codex-app-server-transport.js +1 -1
  145. package/dist/session/codex-app-server.d.ts +3 -0
  146. package/dist/session/codex-app-server.js +25 -1
  147. package/dist/session/control.d.ts +10 -1
  148. package/dist/session/control.js +37 -2
  149. package/dist/session/conversation-normalizer.d.ts +2 -1
  150. package/dist/session/conversation-normalizer.js +1 -1
  151. package/dist/session/conversation-types.d.ts +5 -3
  152. package/dist/session/task-notice.d.ts +14 -0
  153. package/dist/session/task-notice.js +13 -0
  154. package/dist/session/types.d.ts +3 -0
  155. package/dist/socket-path.d.ts +2 -0
  156. package/dist/socket-path.js +22 -0
  157. package/dist/spawn.js +19 -16
  158. package/dist/startup-readiness.d.ts +13 -0
  159. package/dist/startup-readiness.js +38 -0
  160. package/dist/subscriptions/cli.d.ts +78 -0
  161. package/dist/subscriptions/cli.js +186 -0
  162. package/dist/subscriptions/launch.d.ts +37 -0
  163. package/dist/subscriptions/launch.js +93 -0
  164. package/dist/subscriptions/login.d.ts +75 -0
  165. package/dist/subscriptions/login.js +182 -0
  166. package/dist/subscriptions/observed.d.ts +7 -0
  167. package/dist/subscriptions/observed.js +44 -0
  168. package/dist/subscriptions/probe.d.ts +10 -0
  169. package/dist/subscriptions/probe.js +73 -0
  170. package/dist/subscriptions/service.d.ts +102 -0
  171. package/dist/subscriptions/service.js +364 -0
  172. package/dist/subscriptions/store.d.ts +71 -0
  173. package/dist/subscriptions/store.js +140 -0
  174. package/dist/supervisor/launchd.js +2 -1
  175. package/dist/supervisor/systemd.js +9 -23
  176. package/dist/temp-idle.d.ts +17 -0
  177. package/dist/temp-idle.js +42 -0
  178. package/dist/temp-lifecycle.d.ts +6 -1
  179. package/dist/temp-lifecycle.js +29 -13
  180. package/dist/temp-supervisor-recovery.d.ts +3 -0
  181. package/dist/temp-supervisor-recovery.js +46 -0
  182. package/dist/watchdog/briefing.js +3 -16
  183. package/dist/watchdog/run.js +19 -5
  184. package/dist/web/agent-attachments.d.ts +29 -0
  185. package/dist/web/agent-attachments.js +162 -0
  186. package/dist/web/auth.d.ts +28 -2
  187. package/dist/web/auth.js +81 -8
  188. package/dist/web/available-port.d.ts +2 -0
  189. package/dist/web/available-port.js +23 -0
  190. package/dist/web/control.d.ts +3 -2
  191. package/dist/web/control.js +11 -7
  192. package/dist/web/fleet-config-service.d.ts +4 -1
  193. package/dist/web/fleet-config-service.js +46 -15
  194. package/dist/web/prefix-gateway.d.ts +23 -0
  195. package/dist/web/prefix-gateway.js +156 -0
  196. package/dist/web/runtime.d.ts +4 -0
  197. package/dist/web/runtime.js +106 -20
  198. package/dist/web/server.d.ts +11 -0
  199. package/dist/web/server.js +445 -31
  200. package/dist/web/service.d.ts +11 -2
  201. package/dist/web/service.js +30 -4
  202. package/dist/web/workspace-devices.d.ts +29 -0
  203. package/dist/web/workspace-devices.js +84 -0
  204. package/dist/web/workspace-tunnel.d.ts +1 -0
  205. package/dist/web/workspace-tunnel.js +32 -0
  206. package/dist/web-app/assets/FleetApp-D58F4xje.css +1 -0
  207. package/dist/web-app/assets/FleetApp-DP5cBY0o.js +302 -0
  208. package/dist/web-app/assets/FleetApp-DP5cBY0o.js.map +1 -0
  209. package/dist/web-app/assets/abnfDiagram-VCTEODGH-BvJIz7wN.js +2 -0
  210. package/dist/web-app/assets/abnfDiagram-VCTEODGH-BvJIz7wN.js.map +1 -0
  211. package/dist/web-app/assets/arc-AT_BEfpe.js +2 -0
  212. package/dist/web-app/assets/arc-AT_BEfpe.js.map +1 -0
  213. package/dist/web-app/assets/architectureDiagram-5GKGNRK7-vSgJa9Xb.js +37 -0
  214. package/dist/web-app/assets/architectureDiagram-5GKGNRK7-vSgJa9Xb.js.map +1 -0
  215. package/dist/web-app/assets/blockDiagram-I7D4REHJ-DCFk_4Kv.js +130 -0
  216. package/dist/web-app/assets/blockDiagram-I7D4REHJ-DCFk_4Kv.js.map +1 -0
  217. package/dist/web-app/assets/browser-CMIwJ_8L.js +9 -0
  218. package/dist/web-app/assets/browser-CMIwJ_8L.js.map +1 -0
  219. package/dist/web-app/assets/c4Diagram-7LVT6UL2-8J_dVUtF.js +39 -0
  220. package/dist/web-app/assets/c4Diagram-7LVT6UL2-8J_dVUtF.js.map +1 -0
  221. package/dist/web-app/assets/channel-BHCBlfND.js +2 -0
  222. package/dist/web-app/assets/channel-BHCBlfND.js.map +1 -0
  223. package/dist/web-app/assets/chunk-2Q5K7J3B-31RX-jnL.js +2 -0
  224. package/dist/web-app/assets/chunk-2Q5K7J3B-31RX-jnL.js.map +1 -0
  225. package/dist/web-app/assets/chunk-5VM5RSS4-CFF8_ZJH.js +16 -0
  226. package/dist/web-app/assets/chunk-5VM5RSS4-CFF8_ZJH.js.map +1 -0
  227. package/dist/web-app/assets/chunk-F27PBJKO-Dx1l5wLI.js +2 -0
  228. package/dist/web-app/assets/chunk-F27PBJKO-Dx1l5wLI.js.map +1 -0
  229. package/dist/web-app/assets/chunk-IMKFNOWR-Ba2_9bl_.js +232 -0
  230. package/dist/web-app/assets/chunk-IMKFNOWR-Ba2_9bl_.js.map +1 -0
  231. package/dist/web-app/assets/chunk-JWPE2WC7-_mnRB2OH.js +2 -0
  232. package/dist/web-app/assets/chunk-JWPE2WC7-_mnRB2OH.js.map +1 -0
  233. package/dist/web-app/assets/chunk-POPQ4Y6H-B8jQTxQO.js +2 -0
  234. package/dist/web-app/assets/chunk-POPQ4Y6H-B8jQTxQO.js.map +1 -0
  235. package/dist/web-app/assets/chunk-SVP7TREG-BO_Jnb_c.js +89 -0
  236. package/dist/web-app/assets/chunk-SVP7TREG-BO_Jnb_c.js.map +1 -0
  237. package/dist/web-app/assets/chunk-TICWLB2K-ZYZ9hFu5.js +207 -0
  238. package/dist/web-app/assets/chunk-TICWLB2K-ZYZ9hFu5.js.map +1 -0
  239. package/dist/web-app/assets/chunk-XXDRQBXY-ByUAYXI3.js +2 -0
  240. package/dist/web-app/assets/chunk-XXDRQBXY-ByUAYXI3.js.map +1 -0
  241. package/dist/web-app/assets/classDiagram-ZZMXUADV-Ddx7RAuT.js +2 -0
  242. package/dist/web-app/assets/classDiagram-ZZMXUADV-Ddx7RAuT.js.map +1 -0
  243. package/dist/web-app/assets/classDiagram-v2-VYDZK3BY-Ddx7RAuT.js +2 -0
  244. package/dist/web-app/assets/classDiagram-v2-VYDZK3BY-Ddx7RAuT.js.map +1 -0
  245. package/dist/web-app/assets/cose-bilkent-JH36ORCC-BuOGJgHG.js +2 -0
  246. package/dist/web-app/assets/cose-bilkent-JH36ORCC-BuOGJgHG.js.map +1 -0
  247. package/dist/web-app/assets/cynefin-OW5HDTMX-DLksGPh8.js +179 -0
  248. package/dist/web-app/assets/cynefin-OW5HDTMX-DLksGPh8.js.map +1 -0
  249. package/dist/web-app/assets/cynefinDiagram-5FMLGOSQ-nJQb5qZR.js +63 -0
  250. package/dist/web-app/assets/cynefinDiagram-5FMLGOSQ-nJQb5qZR.js.map +1 -0
  251. package/dist/web-app/assets/cytoscape.esm-CtNdOvlO.js +332 -0
  252. package/dist/web-app/assets/cytoscape.esm-CtNdOvlO.js.map +1 -0
  253. package/dist/web-app/assets/dagre-GXQ25YYZ-CCF5O_UD.js +5 -0
  254. package/dist/web-app/assets/dagre-GXQ25YYZ-CCF5O_UD.js.map +1 -0
  255. package/dist/web-app/assets/defaultLocale-DX6XiGOO.js +2 -0
  256. package/dist/web-app/assets/defaultLocale-DX6XiGOO.js.map +1 -0
  257. package/dist/web-app/assets/diagram-S7CK7UJ4-C88au4NC.js +31 -0
  258. package/dist/web-app/assets/diagram-S7CK7UJ4-C88au4NC.js.map +1 -0
  259. package/dist/web-app/assets/diagram-UQ7AKVKN-B4QnPs7U.js +42 -0
  260. package/dist/web-app/assets/diagram-UQ7AKVKN-B4QnPs7U.js.map +1 -0
  261. package/dist/web-app/assets/diagram-VSXAHHWV-DeANdVWA.js +4 -0
  262. package/dist/web-app/assets/diagram-VSXAHHWV-DeANdVWA.js.map +1 -0
  263. package/dist/web-app/assets/diagram-VX7I27RA-YzlB_2AY.js +25 -0
  264. package/dist/web-app/assets/diagram-VX7I27RA-YzlB_2AY.js.map +1 -0
  265. package/dist/web-app/assets/diagram-Z3DM3KII-YY9NFaz_.js +25 -0
  266. package/dist/web-app/assets/diagram-Z3DM3KII-YY9NFaz_.js.map +1 -0
  267. package/dist/web-app/assets/ebnfDiagram-PWID7BFC-Cqu9kHUC.js +2 -0
  268. package/dist/web-app/assets/ebnfDiagram-PWID7BFC-Cqu9kHUC.js.map +1 -0
  269. package/dist/web-app/assets/erDiagram-RLTQ6QDP-IHi93MdG.js +100 -0
  270. package/dist/web-app/assets/erDiagram-RLTQ6QDP-IHi93MdG.js.map +1 -0
  271. package/dist/web-app/assets/flowDiagram-HODETNUW-19bm7W5P.js +169 -0
  272. package/dist/web-app/assets/flowDiagram-HODETNUW-19bm7W5P.js.map +1 -0
  273. package/dist/web-app/assets/ganttDiagram-EL5Y4UJY-BvCqvyiB.js +293 -0
  274. package/dist/web-app/assets/ganttDiagram-EL5Y4UJY-BvCqvyiB.js.map +1 -0
  275. package/dist/web-app/assets/gitGraphDiagram-WWUBYQGX-G4Ubl8Fs.js +107 -0
  276. package/dist/web-app/assets/gitGraphDiagram-WWUBYQGX-G4Ubl8Fs.js.map +1 -0
  277. package/dist/web-app/assets/index-C4BdeFB9.css +1 -0
  278. package/dist/web-app/assets/index-Dtn3ZY6J.js +430 -0
  279. package/dist/web-app/assets/index-Dtn3ZY6J.js.map +1 -0
  280. package/dist/web-app/assets/infoDiagram-27XIBGKW-B6rtfbuC.js +3 -0
  281. package/dist/web-app/assets/infoDiagram-27XIBGKW-B6rtfbuC.js.map +1 -0
  282. package/dist/web-app/assets/init-Gi6I4Gst.js +2 -0
  283. package/dist/web-app/assets/init-Gi6I4Gst.js.map +1 -0
  284. package/dist/web-app/assets/ishikawaDiagram-5VMMS53U-Lp8q1D21.js +71 -0
  285. package/dist/web-app/assets/ishikawaDiagram-5VMMS53U-Lp8q1D21.js.map +1 -0
  286. package/dist/web-app/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  287. package/dist/web-app/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  288. package/dist/web-app/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  289. package/dist/web-app/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  290. package/dist/web-app/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  291. package/dist/web-app/assets/journeyDiagram-3NMN7TZE-Av03B9l3.js +140 -0
  292. package/dist/web-app/assets/journeyDiagram-3NMN7TZE-Av03B9l3.js.map +1 -0
  293. package/dist/web-app/assets/kanban-definition-UXKFOSKX-Ddd3_ejb.js +90 -0
  294. package/dist/web-app/assets/kanban-definition-UXKFOSKX-Ddd3_ejb.js.map +1 -0
  295. package/dist/web-app/assets/katex-HP8lGamR.js +258 -0
  296. package/dist/web-app/assets/katex-HP8lGamR.js.map +1 -0
  297. package/dist/web-app/assets/layout-CNjBeOlp.js +2 -0
  298. package/dist/web-app/assets/layout-CNjBeOlp.js.map +1 -0
  299. package/dist/web-app/assets/linear-DDONU9Ir.js +2 -0
  300. package/dist/web-app/assets/linear-DDONU9Ir.js.map +1 -0
  301. package/dist/web-app/assets/mermaid.core-B9X3C61k.js +313 -0
  302. package/dist/web-app/assets/mermaid.core-B9X3C61k.js.map +1 -0
  303. package/dist/web-app/assets/mindmap-definition-YA3MSWOX-I2UME2Ce.js +97 -0
  304. package/dist/web-app/assets/mindmap-definition-YA3MSWOX-I2UME2Ce.js.map +1 -0
  305. package/dist/web-app/assets/ordinal-Cboi1Yqb.js +2 -0
  306. package/dist/web-app/assets/ordinal-Cboi1Yqb.js.map +1 -0
  307. package/dist/web-app/assets/pegDiagram-XKGWAZYB-BER8lNbi.js +2 -0
  308. package/dist/web-app/assets/pegDiagram-XKGWAZYB-BER8lNbi.js.map +1 -0
  309. package/dist/web-app/assets/pieDiagram-E7YTZNPT-FVWVg8rH.js +40 -0
  310. package/dist/web-app/assets/pieDiagram-E7YTZNPT-FVWVg8rH.js.map +1 -0
  311. package/dist/web-app/assets/quadrantDiagram-AXDQQJYC-YlvT1u77.js +8 -0
  312. package/dist/web-app/assets/quadrantDiagram-AXDQQJYC-YlvT1u77.js.map +1 -0
  313. package/dist/web-app/assets/railroadDiagram-O6MQD6OU-CvxT6dMW.js +2 -0
  314. package/dist/web-app/assets/railroadDiagram-O6MQD6OU-CvxT6dMW.js.map +1 -0
  315. package/dist/web-app/assets/requirementDiagram-BXWQKSXE-Caav4EkP.js +85 -0
  316. package/dist/web-app/assets/requirementDiagram-BXWQKSXE-Caav4EkP.js.map +1 -0
  317. package/dist/web-app/assets/sankeyDiagram-P5KCCOFB-B5Uw70Gn.js +41 -0
  318. package/dist/web-app/assets/sankeyDiagram-P5KCCOFB-B5Uw70Gn.js.map +1 -0
  319. package/dist/web-app/assets/sequenceDiagram-WJ2MYXX4-D2SLKVJl.js +163 -0
  320. package/dist/web-app/assets/sequenceDiagram-WJ2MYXX4-D2SLKVJl.js.map +1 -0
  321. package/dist/web-app/assets/sizeCapture-INFHLROL-BVaBfbwa.js +2 -0
  322. package/dist/web-app/assets/sizeCapture-INFHLROL-BVaBfbwa.js.map +1 -0
  323. package/dist/web-app/assets/stateDiagram-D77RDMKH-BlV9y2tf.js +2 -0
  324. package/dist/web-app/assets/stateDiagram-D77RDMKH-BlV9y2tf.js.map +1 -0
  325. package/dist/web-app/assets/stateDiagram-v2-MP3YSRHH-BU4Tu2pp.js +2 -0
  326. package/dist/web-app/assets/stateDiagram-v2-MP3YSRHH-BU4Tu2pp.js.map +1 -0
  327. package/dist/web-app/assets/swimlanes-42K2YHIH-Pv3Wv8c7.js +2 -0
  328. package/dist/web-app/assets/swimlanes-42K2YHIH-Pv3Wv8c7.js.map +1 -0
  329. package/dist/web-app/assets/swimlanesDiagram-VR7AAH4N-BNKjOvPH.js +9 -0
  330. package/dist/web-app/assets/swimlanesDiagram-VR7AAH4N-BNKjOvPH.js.map +1 -0
  331. package/dist/web-app/assets/timeline-definition-24CTP7MA-C9TOilaR.js +121 -0
  332. package/dist/web-app/assets/timeline-definition-24CTP7MA-C9TOilaR.js.map +1 -0
  333. package/dist/web-app/assets/vennDiagram-4TSXK5OY-DeSDprN4.js +35 -0
  334. package/dist/web-app/assets/vennDiagram-4TSXK5OY-DeSDprN4.js.map +1 -0
  335. package/dist/web-app/assets/wardleyDiagram-VM6X3IG4-SulZn-nm.js +79 -0
  336. package/dist/web-app/assets/wardleyDiagram-VM6X3IG4-SulZn-nm.js.map +1 -0
  337. package/dist/web-app/assets/xychartDiagram-S5SC5T6Z-CC6MrQ0h.js +8 -0
  338. package/dist/web-app/assets/xychartDiagram-S5SC5T6Z-CC6MrQ0h.js.map +1 -0
  339. package/dist/web-app/fleet-index.html +19 -0
  340. package/dist/web-app/fleet.webmanifest +37 -0
  341. package/dist/web-app/icons/apple-touch-icon.png +0 -0
  342. package/dist/web-app/icons/favicon-16.png +0 -0
  343. package/dist/web-app/icons/favicon-32.png +0 -0
  344. package/dist/web-app/icons/icon-192-maskable.png +0 -0
  345. package/dist/web-app/icons/icon-192.png +0 -0
  346. package/dist/web-app/icons/icon-512-maskable.png +0 -0
  347. package/dist/web-app/icons/icon-512.png +0 -0
  348. package/dist/web-app/index.html +9 -7
  349. package/dist/web-app/manifest.webmanifest +10 -8
  350. package/dist/web-app/sw.js +210 -40
  351. package/dist/web-app/version.json +1 -0
  352. package/dist/web-app/workspace-install.sh +148 -0
  353. package/dist/workspace-enrollment.d.ts +28 -0
  354. package/dist/workspace-enrollment.js +129 -0
  355. package/docs/room-layouts.md +227 -0
  356. package/docs/task-workspaces.md +130 -0
  357. package/examples/room-layouts/fresh.yaml +27 -0
  358. package/examples/room-layouts/scoped.yaml +21 -0
  359. package/examples/room-layouts/shared.yaml +19 -0
  360. package/package.json +14 -17
  361. package/presets/README.md +78 -0
  362. package/presets/brain-catalog.json +8 -2
  363. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  364. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  365. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  366. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  367. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  368. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  369. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  370. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  371. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  372. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  373. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  374. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  375. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  376. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  377. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  378. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  379. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  380. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  381. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  382. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  383. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  384. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  385. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  386. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  387. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  388. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  389. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  390. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  391. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  392. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  393. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  394. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  395. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  396. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  397. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  398. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  399. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  400. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  401. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  402. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  403. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  404. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  405. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  406. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  407. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  408. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  409. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  410. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  411. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  412. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  413. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  414. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  415. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  416. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  417. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  418. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  419. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  420. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  421. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  422. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  423. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  424. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  425. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  426. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  427. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  428. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  429. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  430. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  431. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  432. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  433. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  434. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  435. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  436. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  437. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  438. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  439. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  440. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  441. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  442. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  443. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  444. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  445. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  446. package/presets/fleet/roles/Coordinator.yaml +22 -0
  447. package/presets/fleet/roles/Engineer.yaml +40 -0
  448. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  449. package/presets/fleet/room_layouts/pair.yaml +24 -0
  450. package/presets/fleet/room_layouts/single.yaml +17 -0
  451. package/presets/fleet/room_layouts/team.yaml +30 -0
  452. package/presets/fleet/room_templates/engineering.yaml +19 -0
  453. package/presets/manifest.json +2 -2
  454. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  455. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  456. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  457. package/dist/web-app/icons/ours-fleet.svg +0 -4
  458. package/dist/web-app/offline.html +0 -18
@@ -0,0 +1,104 @@
1
+ import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ export function producerConfig(env = process.env) {
4
+ const origin = env.OURS_NOTIFICATIONS_ORIGIN, token = env.OURS_NOTIFICATIONS_PRODUCER_TOKEN;
5
+ if (!origin && !token)
6
+ return;
7
+ if (!origin || !token || token.length < 32)
8
+ throw new Error('notifications producer requires origin and scoped token');
9
+ const url = new URL(origin);
10
+ if (!['http:', 'https:'].includes(url.protocol) || url.origin !== origin || url.username || url.password)
11
+ throw new Error('invalid notification service origin');
12
+ if (url.protocol === 'http:' && !['127.0.0.1', '[::1]', 'localhost'].includes(url.hostname))
13
+ throw new Error('notification credentials require HTTPS or loopback');
14
+ return { origin, token };
15
+ }
16
+ /** Durable producer queue. Service dedupe makes crash-after-acceptance replay safe. */
17
+ export class NotificationOutbox {
18
+ file;
19
+ config;
20
+ project;
21
+ warn;
22
+ entries;
23
+ cursor;
24
+ checkpoint;
25
+ running;
26
+ timer;
27
+ constructor(file, config, project, warn = () => { }) {
28
+ this.file = file;
29
+ this.config = config;
30
+ this.project = project;
31
+ this.warn = warn;
32
+ mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
33
+ const saved = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : { entries: [] };
34
+ this.entries = Array.isArray(saved) ? saved : saved.entries;
35
+ this.cursor = saved.cursor;
36
+ this.checkpoint = saved.checkpoint;
37
+ if (!Array.isArray(this.entries))
38
+ throw new Error('invalid notification outbox');
39
+ this.timer = setInterval(() => { void this.drain(); }, 3000);
40
+ this.timer.unref();
41
+ }
42
+ persist(entries, cursor = this.cursor, checkpoint = this.checkpoint) {
43
+ const tmp = this.file + '.tmp', fd = openSync(tmp, 'w', 0o600);
44
+ try {
45
+ writeFileSync(fd, JSON.stringify({ entries, cursor, checkpoint }));
46
+ fsyncSync(fd);
47
+ }
48
+ finally {
49
+ closeSync(fd);
50
+ }
51
+ renameSync(tmp, this.file);
52
+ const dir = openSync(dirname(this.file), 'r');
53
+ try {
54
+ fsyncSync(dir);
55
+ }
56
+ finally {
57
+ closeSync(dir);
58
+ }
59
+ this.entries = entries;
60
+ this.cursor = cursor;
61
+ this.checkpoint = checkpoint;
62
+ }
63
+ advance(cursor) { this.persist(this.entries, cursor); }
64
+ saveCheckpoint(checkpoint) { this.persist(this.entries, this.cursor, checkpoint); }
65
+ enqueue(id, value, cursor = this.cursor) {
66
+ if (this.entries.some(e => e.id === id)) {
67
+ if (cursor !== this.cursor)
68
+ this.advance(cursor);
69
+ return true;
70
+ }
71
+ if (this.entries.length >= 2000)
72
+ return false;
73
+ this.persist([...this.entries, { id, value }], cursor);
74
+ return true;
75
+ }
76
+ drain() {
77
+ return this.running ??= this.drainOnce().finally(() => { this.running = undefined; });
78
+ }
79
+ async drainOnce() {
80
+ for (const entry of [...this.entries].slice(0, 32)) {
81
+ try {
82
+ const value = entry.payload ?? await this.project(entry.value, entry.id);
83
+ // Freeze the canonical projection before any network attempt. A crash
84
+ // after service acceptance must replay the identical dedupe payload.
85
+ if (!entry.payload)
86
+ this.persist(this.entries.map(e => e.id === entry.id ? { ...e, payload: value } : e));
87
+ const response = await fetch(this.config.origin + '/api/v1/send', {
88
+ method: 'POST', redirect: 'error', signal: AbortSignal.timeout(10_000),
89
+ headers: { Authorization: `Bearer ${this.config.token}`, 'Content-Type': 'application/json' },
90
+ body: JSON.stringify(value),
91
+ });
92
+ await response.body?.cancel();
93
+ if (!response.ok)
94
+ throw new Error('notification service rejected event');
95
+ this.persist(this.entries.filter(e => e.id !== entry.id));
96
+ }
97
+ catch {
98
+ this.warn('Notification producer delivery pending; retrying from durable outbox');
99
+ break;
100
+ }
101
+ }
102
+ }
103
+ async close() { clearInterval(this.timer); await this.running; }
104
+ }
@@ -14,6 +14,8 @@ export interface OwnerChannelOptions {
14
14
  harness: string;
15
15
  config: OwnerChannelConfig;
16
16
  session: AgentSession;
17
+ /** Ordinary owner input must not cancel the initial briefing turn. */
18
+ startupPending?: () => boolean;
17
19
  stateDir: string;
18
20
  env?: Record<string, string>;
19
21
  log(line: string): void;
@@ -269,6 +271,7 @@ export declare class OwnerChannel implements OwnerChannelHandle {
269
271
  private attachmentGroups;
270
272
  private handleAttachmentGroup;
271
273
  private handle;
274
+ private ownerPromptPolicy;
272
275
  /**
273
276
  * Deterministic command path: the message never becomes an agent prompt.
274
277
  * Authorization already happened — the managed-agent relay branch and the
@@ -883,8 +883,15 @@ export class OwnerChannel {
883
883
  const recovered = [];
884
884
  for (const claim of this.messageRecovery.list()) {
885
885
  const item = await this.client.getHistoryItem(claim.wireId);
886
- if (!item)
887
- throw new Error(`journaled owner message ${claim.wireId} is missing from persistent history`);
886
+ if (!item) {
887
+ // The daemon has definitively lost this body. Retrying the claim would
888
+ // block every later owner message, including after a supervisor restart.
889
+ // Keep transient lookup errors retryable; only an explicit absence skips.
890
+ this.messageRecovery.pruneHandled(wireId => wireId === claim.wireId);
891
+ this.options.log(`[${this.options.role}] skipped journaled owner message ${claim.wireId} `
892
+ + `(seq=${claim.seq}): missing from persistent history`);
893
+ continue;
894
+ }
888
895
  recovered.push(this.historyMessage(item, claim));
889
896
  }
890
897
  const listed = await this.client.listIncomingMessages();
@@ -1123,6 +1130,13 @@ export class OwnerChannel {
1123
1130
  const retrieved = unread.length
1124
1131
  ? parseRetrievedAttachments(await this.client.getFiles(unread.map(file => file.wireId)), unread)
1125
1132
  : [];
1133
+ // getFiles returns daemon-local paths, which need not exist in Fleet's
1134
+ // filesystem (for example with an HTTP daemon in a container). Fetch
1135
+ // through the bound client and keep the daemon's integrity metadata for
1136
+ // admission below; never trust or remap the returned filesystem path.
1137
+ for (const file of retrieved) {
1138
+ file.path = await writeRecoveredAttachment(requestDir, file.wireId, await this.client.fetchFile(file.wireId));
1139
+ }
1126
1140
  for (const file of historyRecovered) {
1127
1141
  if (!group.recovery)
1128
1142
  throw new Error('unexpected read attachment without recovery route');
@@ -1136,8 +1150,7 @@ export class OwnerChannel {
1136
1150
  await mkdir(outbox, { recursive: true, mode: 0o700 });
1137
1151
  const activityCursor = this.latestEventSeq(this.options.session.eventsSince(0));
1138
1152
  const queued = await queueSessionPrompt(this.options.session, this.ownerAttachmentPrompt(sender, originWireId, requestId, admitted, group.caption), {
1139
- interrupt: this.options.config.interrupt,
1140
- ...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
1153
+ ...this.ownerPromptPolicy(),
1141
1154
  origin: { kind: 'owner', requestId,
1142
1155
  ...(group.caption ? { displayText: String(group.caption.text ?? '') } : {}) },
1143
1156
  });
@@ -1263,8 +1276,7 @@ export class OwnerChannel {
1263
1276
  const activityCursor = this.latestEventSeq(this.options.session.eventsSince(0));
1264
1277
  try {
1265
1278
  queued = await queueSessionPrompt(this.options.session, this.ownerPrompt(sender, text, wireId), {
1266
- interrupt: this.options.config.interrupt,
1267
- ...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
1279
+ ...this.ownerPromptPolicy(),
1268
1280
  origin: { kind: 'owner', requestId, displayText: text },
1269
1281
  });
1270
1282
  }
@@ -1309,6 +1321,14 @@ export class OwnerChannel {
1309
1321
  this.completionTasks.add(task);
1310
1322
  return true;
1311
1323
  }
1324
+ ownerPromptPolicy() {
1325
+ if (this.options.startupPending?.())
1326
+ return { interrupt: false, steer: true };
1327
+ return {
1328
+ interrupt: this.options.config.interrupt,
1329
+ ...(this.options.config.interrupt ? { interruptSource: 'owner' } : {}),
1330
+ };
1331
+ }
1312
1332
  /**
1313
1333
  * Deterministic command path: the message never becomes an agent prompt.
1314
1334
  * Authorization already happened — the managed-agent relay branch and the
@@ -1378,6 +1398,7 @@ export class OwnerChannel {
1378
1398
  await this.fleetOps.provisionTask(task.task_id);
1379
1399
  return outcome;
1380
1400
  }),
1401
+ observeTaskReadiness: taskId => new TaskRoomApplicationService(this.options.configPath).observeTaskReadiness(taskId),
1381
1402
  taskProvisioningOutcome: taskId => new TaskRoomApplicationService(this.options.configPath).taskProvisioningOutcome(taskId),
1382
1403
  listTasks: filter => new TaskRoomApplicationService(this.options.configPath).listTasks(filter),
1383
1404
  groupedTasks: filter => new TaskRoomApplicationService(this.options.configPath).groupedTasks(filter),
@@ -1762,6 +1783,13 @@ export class OwnerChannel {
1762
1783
  const retrieved = unread.length
1763
1784
  ? parseRetrievedAttachments(await this.client.getFiles(unread.map(file => file.wireId)), unread)
1764
1785
  : [];
1786
+ // getFiles returns daemon-local paths, which need not exist in Fleet's
1787
+ // filesystem (for example with an HTTP daemon in a container). Fetch
1788
+ // through the bound client and keep the daemon's integrity metadata for
1789
+ // admission below; never trust or remap the returned filesystem path.
1790
+ for (const file of retrieved) {
1791
+ file.path = await writeRecoveredAttachment(requestDir, file.wireId, await this.client.fetchFile(file.wireId));
1792
+ }
1765
1793
  for (const file of historyRecovered) {
1766
1794
  if (!group.recovery)
1767
1795
  throw new Error('unexpected read attachment without recovery route');
@@ -1,3 +1,4 @@
1
+ import type { TaskReadinessIssue } from '../rooms-tasks/live-readiness.js';
1
2
  import type { InterruptOutcome, SessionEvent, SessionSnapshot } from '../session/types.js';
2
3
  import type { RoomOrchestrationRecord, TaskOutcome, TaskRecord, TaskTerminalIntent, TaskListRecord } from '../rooms-tasks/types.js';
3
4
  import { type OwnerCommentsState } from './notices.js';
@@ -58,6 +59,9 @@ export interface OwnerCommandContext {
58
59
  terminalTask(taskId: string, kind: TaskTerminalIntent['kind'], outcome?: TaskOutcome): Promise<void>;
59
60
  createTask(input: Omit<CreateTaskRequest, 'actor'>): Promise<TaskRecord>;
60
61
  startTask(taskId: string): Promise<TaskProvisioningOutcome | TaskRecord>;
62
+ observeTaskReadiness?(taskId: string): Promise<{
63
+ state: 'ready';
64
+ } | TaskReadinessIssue>;
61
65
  taskProvisioningOutcome?(taskId: string): TaskProvisioningOutcome;
62
66
  listTasks(filter?: {
63
67
  state?: TaskState | TaskState[];
@@ -47,6 +47,11 @@ function isKnownOwnerRoomState(message) {
47
47
  ].some(pattern => pattern.test(message));
48
48
  }
49
49
  function ownerTaskFailure(error) {
50
+ if (error instanceof TaskRoomApplicationError && error.code === 'task_not_ready')
51
+ return {
52
+ kind: 'state', detail: error.message,
53
+ action: 'Ask Fleet Coordinator to inspect room and member status and choose supported recovery.',
54
+ };
50
55
  if (error instanceof TaskListError)
51
56
  return {
52
57
  kind: error.code === 'list_not_found' ? 'not_found'
@@ -301,6 +306,7 @@ export const ownerCommands = [
301
306
  const trailingLines = argLines.slice(1).join('\n').trim() || undefined;
302
307
  const showTask = async (id) => {
303
308
  const { task: t } = ctx.getTask(id);
309
+ const readiness = t.state === 'active' ? await ctx.observeTaskReadiness?.(id) : undefined;
304
310
  await ctx.reply(renderMarkdownResult({
305
311
  icon: '📋', title: 'Task details',
306
312
  fields: [
@@ -308,6 +314,8 @@ export const ownerCommands = [
308
314
  { label: 'Title', value: t.title },
309
315
  { label: 'Status', value: taskStatus(t.state), kind: 'markdown' },
310
316
  { label: 'List', value: t.list_name ?? 'default', kind: 'code' },
317
+ ...(readiness ? [{ label: 'Readiness', value: readiness.state },
318
+ ...('reason' in readiness ? [{ label: 'Reason', value: readiness.reason }] : [])] : []),
311
319
  ...(t.blocked ? [{ label: 'Blocked', value: t.blocked.reason }] : []),
312
320
  ...(t.template ? [{ label: 'Template', value: `${t.template.name}@${t.template.version}`, kind: 'code' }] : []),
313
321
  ...(t.room_id ? [{ label: 'Room', value: t.room_id, kind: 'code' }] : []),
@@ -1,6 +1,6 @@
1
+ import { redactErasedContent, writePrivacyFilteredLedger } from '../erased-resources.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { chmodSync, existsSync, readFileSync } from 'node:fs';
3
- import { replaceFileAtomically } from '../atomic-file.js';
4
4
  import { lifecycleEventDigestBasis, validateFleetAuditPresentations, } from '../fleet-command-audit.js';
5
5
  const DIGEST = /^[a-f0-9]{64}$/u;
6
6
  const LIMIT = 5_000;
@@ -63,7 +63,7 @@ export class FleetLifecycleOutbox {
63
63
  }
64
64
  pending() {
65
65
  this.assertHealthy();
66
- return this.entries.filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
66
+ return redactErasedContent(this.entries).filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
67
67
  }
68
68
  finish(digest, delivery) {
69
69
  this.assertHealthy();
@@ -82,6 +82,7 @@ export class FleetLifecycleOutbox {
82
82
  throw new Error(this.corruptReason);
83
83
  }
84
84
  persist() {
85
- replaceFileAtomically(this.path, `${JSON.stringify({ version: 1, entries: this.entries })}\n`, 0o600);
85
+ this.entries = redactErasedContent(this.entries);
86
+ writePrivacyFilteredLedger(this.path, { version: 1, entries: this.entries });
86
87
  }
87
88
  }
@@ -1,7 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { readFile } from 'node:fs/promises';
3
- import { extname, join } from 'node:path';
4
- import { readDaemonConfig, resolveEndpoint } from '../monitor.js';
3
+ import { extname } from 'node:path';
5
4
  import { readClientProfile } from '../client-profile.js';
6
5
  import { OursError, attachOursClient, } from '@ours.network/sdk/client';
7
6
  /** Any failure of a daemon operation. Never carries a message body or a token. */
@@ -131,24 +130,10 @@ export class OursSdkClient {
131
130
  return;
132
131
  const environment = { ...process.env, ...this.env };
133
132
  const profile = readClientProfile(environment);
134
- // Reuse existing connection configuration. Identity selection checks the
135
- // daemon capability before reading the client's protected token delivery file.
136
- const endpoint = !profile && environment.OURS_DAEMON_ID
137
- ? resolveEndpoint(environment, false) : undefined;
138
- const token = endpoint ? environment.OURS_API_TOKEN?.trim() || readDaemonConfig(environment).apiToken : undefined;
139
- const options = profile ? {
133
+ const options = {
140
134
  endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
141
135
  credentialPath: profile.credentialPath,
142
136
  sessionMode: 'external', leaseToken: this.leaseToken, env: {},
143
- } : endpoint ? {
144
- endpoint: endpoint.origin, expectedInstanceId: environment.OURS_DAEMON_ID,
145
- sessionMode: 'external', leaseToken: this.leaseToken,
146
- ...(token ? { token } : { credentialPath: join(endpoint.stateDir, 'daemon-token') }),
147
- } : {
148
- env: environment,
149
- leaseToken: this.leaseToken,
150
- clientPid: process.pid,
151
- fetch: notificationDeadlineFetch(this.deps.fetch ?? globalThis.fetch, this.deps.notificationRequestDeadlineMs ?? NOTIFICATION_REQUEST_DEADLINE_MS),
152
137
  };
153
138
  this.client = await (this.deps.attachClient?.(options) ?? attachOursClient(options));
154
139
  this.terminalReleasePending = true;
@@ -69,8 +69,11 @@ const V5_GENERATED_ROLE_DEFAULT_FINGERPRINTS = Object.freeze({
69
69
  });
70
70
  const CURRENT_ROLE_DEFAULTS = new Set([
71
71
  'roles/Coordinator.yaml', 'roles/LocalCoordinator.yaml', 'roles/Developer.yaml', 'roles/Critic.yaml',
72
+ 'roles/Engineer.yaml',
72
73
  'agent_templates/LocalCoordinator.yaml', 'agent_templates/Developer.yaml', 'agent_templates/Critic.yaml',
74
+ 'agent_templates/Engineer.yaml',
73
75
  'room_templates/single.yaml', 'room_templates/pair.yaml', 'room_templates/team.yaml',
76
+ 'room_templates/engineering.yaml',
74
77
  'agents/FleetCoordinator.yaml',
75
78
  ]);
76
79
  export const legacyStarterMigrationManifest = Object.freeze({
@@ -258,6 +261,18 @@ export function migratePackagedRoleDefaults(configuration, options = {}, hooks =
258
261
  unlinkSync(target);
259
262
  copyFileSync(join(source, relative), target, constants.COPYFILE_EXCL);
260
263
  chmodSync(target, 0o600);
264
+ // New Engineer seats use the existing Developer's selected brain. This
265
+ // preserves wizard/custom provider choices without copying permissions.
266
+ if (relative === 'agent_templates/Engineer.yaml' && classified.additions.includes(path)) {
267
+ const developer = join(root, 'agent_templates/Developer.yaml');
268
+ if (existsSync(developer)) {
269
+ const value = parseFleetDocument(developer, readFileSync(developer, 'utf8'), 'strict').value;
270
+ if (value.brain !== undefined && JSON.stringify(value.brain) !== JSON.stringify({ ref: 'claude-default' })) {
271
+ const bytes = readFileSync(target, 'utf8').replace('brain: { ref: claude-default }', () => `brain: ${JSON.stringify(value.brain)}`);
272
+ writeFileSync(target, bytes, { mode: 0o600 });
273
+ }
274
+ }
275
+ }
261
276
  fsyncPath(target);
262
277
  }
263
278
  for (const kind of ['roles', 'agent_templates', 'room_templates', 'agents'])
@@ -0,0 +1,48 @@
1
+ import type { FleetConfig } from '../config.js';
2
+ import { TaskStateError } from './task-state.js';
3
+ import { provisionMembers } from './provision.js';
4
+ import type { CoworkAdapter } from './cowork-adapter.js';
5
+ export declare class MemberAdditionRejected extends TaskStateError {
6
+ readonly accepted = false;
7
+ }
8
+ export interface AddMemberRequest {
9
+ requestId: string;
10
+ slot: string;
11
+ role: string;
12
+ brain: string;
13
+ agentTemplate: string;
14
+ }
15
+ export declare function memberAddition(taskId: string, requestId: string): {
16
+ requestId: string;
17
+ taskId: string;
18
+ roleId: string;
19
+ state: "running" | "succeeded" | "attention" | "failed";
20
+ error?: string;
21
+ } | {
22
+ state: string;
23
+ error: string;
24
+ requestId: string;
25
+ taskId: string;
26
+ roleId: string;
27
+ };
28
+ export declare function requestMemberAddition(input: {
29
+ taskId: string;
30
+ request: AddMemberRequest;
31
+ cfg: FleetConfig;
32
+ cowork: CoworkAdapter;
33
+ configPath?: string;
34
+ binPath: string;
35
+ provision?: typeof provisionMembers;
36
+ }): Promise<{
37
+ requestId: string;
38
+ taskId: string;
39
+ roleId: string;
40
+ state: "running" | "succeeded" | "attention" | "failed";
41
+ error?: string;
42
+ } | {
43
+ state: string;
44
+ error: string;
45
+ requestId: string;
46
+ taskId: string;
47
+ roleId: string;
48
+ }>;
@@ -0,0 +1,83 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { replaceFileAtomically, withFileLock } from '../atomic-file.js';
5
+ import { canonicalJson } from '../canonical-json.js';
6
+ import { stateRoot } from '../paths.js';
7
+ import { getTask, TaskStateError } from './task-state.js';
8
+ import { getRoomRecord } from './room-state.js';
9
+ import { prepareExecutionPlan } from './member-overrides.js';
10
+ import { sealTemplateSnapshot } from './templates.js';
11
+ import { provisionMembers } from './provision.js';
12
+ export class MemberAdditionRejected extends TaskStateError {
13
+ accepted = false;
14
+ }
15
+ const running = new Set();
16
+ function pathFor(taskId, requestId) {
17
+ if (!/^[a-z0-9]{10,40}$/.test(taskId) || !/^[a-zA-Z0-9_-]{8,80}$/.test(requestId))
18
+ throw new TaskStateError('Invalid task or request ID');
19
+ return join(stateRoot(), 'member-additions', taskId, requestId + '.json');
20
+ }
21
+ export function memberAddition(taskId, requestId) {
22
+ getTask(taskId);
23
+ const path = pathFor(taskId, requestId);
24
+ if (!existsSync(path))
25
+ throw new TaskStateError('Member request not found');
26
+ const receipt = JSON.parse(readFileSync(path, 'utf8'));
27
+ const { hash, ...view } = receipt;
28
+ return receipt.state === 'running' && !running.has(path) ? { ...view, state: 'attention', error: 'The server stopped observing this launch. Inspect the existing agent before any recovery.' } : view;
29
+ }
30
+ export async function requestMemberAddition(input) {
31
+ const { request: r, taskId } = input;
32
+ if (!r || typeof r.slot !== 'string' || !/^[A-Za-z][A-Za-z0-9_-]{0,31}$/.test(r.slot)
33
+ || ![r.role, r.brain, r.agentTemplate].every(v => typeof v === 'string' && v.length > 0 && v.length <= 128))
34
+ // No receipt lookup has happened yet: this request ID may already be accepted.
35
+ throw new TaskStateError('Slot, Role, Brain and Agent Template are required');
36
+ const path = pathFor(taskId, r.requestId);
37
+ const hash = createHash('sha256').update(canonicalJson(r)).digest('hex');
38
+ mkdirSync(join(stateRoot(), 'member-additions', taskId), { recursive: true, mode: 0o700 });
39
+ return withFileLock(path + '.lock', async () => {
40
+ if (existsSync(path)) {
41
+ const old = JSON.parse(readFileSync(path, 'utf8'));
42
+ if (old.hash !== hash)
43
+ throw new TaskStateError('Request ID was already used with different settings');
44
+ return memberAddition(taskId, r.requestId);
45
+ }
46
+ const task = getTask(taskId);
47
+ const room = task.room_id && getRoomRecord(task.room_id);
48
+ if (!room || !['active', 'review'].includes(task.state) || task.terminal_intent || task.blocked || room.state !== 'active'
49
+ || room.task_id !== taskId || room.room_identity_cid !== task.room_identity_cid)
50
+ throw new MemberAdditionRejected('Adding an agent requires an active, unblocked task room');
51
+ const roleId = `${taskId.slice(0, 8)}-${r.slot}-1`;
52
+ if (room.member_seats.some(s => s.role_name === roleId))
53
+ throw new MemberAdditionRejected('This member slot already exists');
54
+ const plan = (() => {
55
+ try {
56
+ return prepareExecutionPlan({ name: 'additional-member', version: 1, description: 'Additional task participant',
57
+ contract: room.template_snapshot?.contract, members: [{ slot: r.slot, role: r.role, count: 1, agent_template: r.agentTemplate }] }, input.cfg, { [r.slot]: { role: r.role, brain: r.brain } });
58
+ }
59
+ catch (error) {
60
+ throw new MemberAdditionRejected(error instanceof Error ? error.message : 'Invalid member configuration');
61
+ }
62
+ })();
63
+ const template = sealTemplateSnapshot(plan.snapshot, input.cfg.agentTemplates ?? {}, plan.launchDefinitions);
64
+ const receipt = { taskId, requestId: r.requestId, roleId, hash, state: 'running' };
65
+ const save = () => replaceFileAtomically(path, JSON.stringify(receipt) + '\n', 0o600);
66
+ save();
67
+ running.add(path);
68
+ void (input.provision ?? provisionMembers)({ cfg: input.cfg, cowork: input.cowork, configPath: input.configPath, binPath: input.binPath,
69
+ taskId, roomId: room.room_id, template, goal: task.title, brief: task.brief, append: true }).then(result => {
70
+ const seat = result.member_seats.find(s => s.role_name === roleId);
71
+ receipt.state = seat?.seat_state === 'active' && getTask(taskId).member_roles.some(m => m.name === roleId) ? 'succeeded' : 'attention';
72
+ if (receipt.state === 'attention')
73
+ receipt.error = 'Admission is not confirmed. Inspect the existing launch; no automatic retry was made.';
74
+ }).catch(() => { receipt.state = 'failed'; receipt.error = 'Member launch failed. Inspect the task and agent logs before recovery.'; })
75
+ .finally(() => { try {
76
+ save();
77
+ }
78
+ finally {
79
+ running.delete(path);
80
+ } }).catch(() => { running.delete(path); });
81
+ return memberAddition(taskId, r.requestId);
82
+ });
83
+ }
@@ -0,0 +1,8 @@
1
+ import type { ArchivedMemberAbsence, RoomMemberSeat } from './types.js';
2
+ /** Revalidate live facts; a persisted timestamp is never cleanup authority. */
3
+ export declare function verifyArchivedAbsence(proof: ArchivedMemberAbsence): Promise<void>;
4
+ /** After the verified archive has been consumed by explicit workspace deletion,
5
+ * still fence replacement live state and a recreated daemon identity on every retry.
6
+ */
7
+ export declare function verifyArchivedMemberStillAbsent(proof: ArchivedMemberAbsence): Promise<void>;
8
+ export declare function proveArchivedAbsence(seat: RoomMemberSeat): Promise<ArchivedMemberAbsence>;
@@ -0,0 +1,48 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { agentDir } from '../paths.js';
4
+ import { tempArchiveForLaunch, tempArchiveForCreationAction, tempSupervisorLiveness } from '../temp-lifecycle.js';
5
+ import { assertMemberIdentityAbsent } from './close.js';
6
+ /** Revalidate live facts; a persisted timestamp is never cleanup authority. */
7
+ export async function verifyArchivedAbsence(proof) {
8
+ const absent = () => {
9
+ if (existsSync(agentDir(proof.name, true)))
10
+ throw new Error('Archived member has replacement live state');
11
+ };
12
+ absent();
13
+ const archive = tempArchiveForLaunch(proof.name, proof.launch_id);
14
+ const action = tempArchiveForCreationAction(proof.name, proof.action_id);
15
+ if (!archive || archive !== proof.archive_path || action?.path !== archive
16
+ || action.launchId !== proof.launch_id
17
+ || readFileSync(join(archive, '.identity'), 'utf8').trim() !== proof.name)
18
+ throw new Error('Archived member absence ownership proof mismatch');
19
+ if (await tempSupervisorLiveness(archive) !== 'stopped')
20
+ throw new Error('Archived member supervisor absence is not proven');
21
+ await verifyArchivedMemberStillAbsent(proof);
22
+ }
23
+ /** After the verified archive has been consumed by explicit workspace deletion,
24
+ * still fence replacement live state and a recreated daemon identity on every retry.
25
+ */
26
+ export async function verifyArchivedMemberStillAbsent(proof) {
27
+ const absent = () => {
28
+ if (existsSync(agentDir(proof.name, true)))
29
+ throw new Error('Archived member has replacement live state');
30
+ };
31
+ absent();
32
+ await assertMemberIdentityAbsent({
33
+ role_name: proof.name, slot: 'archived', cowork_role: 'archived', seat_state: 'removed',
34
+ });
35
+ absent();
36
+ }
37
+ export async function proveArchivedAbsence(seat) {
38
+ if (seat.identity_cid || seat.retirement?.phase !== 'identity_absent'
39
+ || !seat.launch?.launch_id || !seat.launch.action_id
40
+ || seat.launch.launch_id !== seat.retirement.launch_id || !seat.retirement.archive_path)
41
+ throw new Error('Missing exact archived member absence evidence');
42
+ const proof = {
43
+ name: seat.role_name, launch_id: seat.launch.launch_id, action_id: seat.launch.action_id,
44
+ archive_path: seat.retirement.archive_path, checked_at: new Date().toISOString(),
45
+ };
46
+ await verifyArchivedAbsence(proof);
47
+ return proof;
48
+ }
@@ -75,6 +75,11 @@ async function presentDetachedProvisioningOutcome(outcome) {
75
75
  function taskRoomPublicFailure(error) {
76
76
  const f = error.fields;
77
77
  switch (error.code) {
78
+ case 'task_not_ready': return {
79
+ legacy: `task readiness ${f.readiness}: ${f.reason}`, kind: 'state',
80
+ detail: `Task ${f.task} readiness is ${f.readiness}: ${f.reason}${f.member ? ` (${f.member})` : ''}.`,
81
+ action: 'Ask Fleet Coordinator to inspect room and member status and choose supported recovery. Do not blindly relaunch agents or reuse invites.',
82
+ };
78
83
  case 'task_confirmation_mismatch': return {
79
84
  legacy: 'confirmation ID must match task ID', kind: 'usage',
80
85
  detail: 'The two task IDs must match.', action: 'Repeat the same task ID twice.',
@@ -515,10 +520,10 @@ function taskRoomService(configuration) {
515
520
  function allTemplates(cfg) {
516
521
  return cfg.roomTemplates ?? {};
517
522
  }
518
- function coworkFor(cfg) {
523
+ function coworkFor(cfg, options) {
519
524
  if (!cfg.rooms)
520
525
  throw new ConfigError('rooms: configuration is required before creating or querying rooms');
521
- return createCoworkAdapter({ configPath: cfg.rooms.cowork?.config });
526
+ return createCoworkAdapter({ configPath: cfg.rooms.cowork?.config, ...options });
522
527
  }
523
528
  function resolveRoomTemplate(cfg, name) {
524
529
  if (!name)
@@ -827,16 +832,18 @@ export function registerTaskCommands(parent, cOpt) {
827
832
  dieTaskRoom(e);
828
833
  }
829
834
  });
830
- taskCmd.command('show <id>')
835
+ cOpt(taskCmd.command('show <id>'))
831
836
  .description('show task details')
832
837
  .option('--json', 'JSON output')
833
838
  .action(async (id, opts) => {
834
839
  try {
835
- const service = taskRoomService();
840
+ const service = taskRoomService(opts.configuration);
836
841
  const { task: t, orchestration: room } = service.getTask(id);
842
+ const readiness = t.state === 'active' ? await service.observeTaskReadiness(id) : undefined;
837
843
  if (opts.json) {
838
844
  console.log(JSON.stringify({
839
845
  schema_version: 1, task: t, orchestration: room ?? null,
846
+ ...(readiness ? { readiness } : {}),
840
847
  }, null, 2));
841
848
  return;
842
849
  }
@@ -846,6 +853,8 @@ export function registerTaskCommands(parent, cOpt) {
846
853
  { label: 'ID', value: t.task_id, kind: 'code' },
847
854
  { label: 'Title', value: t.title },
848
855
  { label: 'Status', value: taskStatus(t.state), kind: 'markdown' },
856
+ ...(readiness ? [{ label: 'Readiness', value: readiness.state },
857
+ ...('reason' in readiness ? [{ label: 'Reason', value: readiness.reason }] : [])] : []),
849
858
  ...(t.blocked ? [{ label: 'Blocked', value: t.blocked.reason }] : []),
850
859
  ...(t.template ? [{ label: 'Template', value: `${t.template.name}@${t.template.version}`, kind: 'code' }] : []),
851
860
  ...(t.room_id ? [{ label: 'Room', value: t.room_id, kind: 'code' }] : []),
@@ -1152,7 +1161,7 @@ export function registerTaskCommands(parent, cOpt) {
1152
1161
  const app = taskRoomService(opts.configuration);
1153
1162
  for (;;) {
1154
1163
  const before = app.taskProvisioningOutcome(id);
1155
- if (before.kind !== 'in_progress') {
1164
+ if (before.kind !== 'in_progress' || before.next_action) {
1156
1165
  await presentDetachedProvisioningOutcome(before);
1157
1166
  return;
1158
1167
  }
@@ -1176,6 +1185,26 @@ export function registerTaskCommands(parent, cOpt) {
1176
1185
  dieTaskRoom(e);
1177
1186
  }
1178
1187
  });
1188
+ cOpt(taskCmd.command('_layout <id> <operation> [room]', { hidden: true }))
1189
+ .description('internal: run an accepted layout room operation (open, close-room, close)')
1190
+ .option('--json', 'JSON output')
1191
+ .option('--operation-id <id>', 'accepted operation ID; status updates apply only while it is current')
1192
+ .action(async (id, operation, room, opts) => {
1193
+ try {
1194
+ if (!['open', 'close-room', 'close'].includes(operation))
1195
+ throw new Error(`unknown layout operation: ${operation}`);
1196
+ const view = await taskRoomService(opts.configuration).runTaskLayoutOperation({
1197
+ actor: { kind: 'internal_worker', surface: 'cli' }, taskId: id,
1198
+ operation: operation, room, operationId: opts.operationId,
1199
+ });
1200
+ console.log(JSON.stringify({ schema_version: 1, layout: view }, null, 2));
1201
+ }
1202
+ catch (e) {
1203
+ if (opts.json)
1204
+ die(e);
1205
+ dieTaskRoom(e);
1206
+ }
1207
+ });
1179
1208
  cOpt(taskCmd.command('_settle_delete <id>', { hidden: true }))
1180
1209
  .description('internal: settle a previously accepted task deletion')
1181
1210
  .option('--json', 'JSON output')