@ours.network/fleet 1.2.0-nightly.6 → 1.2.0-nightly.61

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 (389) hide show
  1. package/README.md +287 -65
  2. package/dist/account-origin.d.ts +2 -0
  3. package/dist/account-origin.js +6 -0
  4. package/dist/agent-ours/bridge.js +35 -9
  5. package/dist/agent-ours/correspondence.d.ts +10 -0
  6. package/dist/agent-ours/correspondence.js +1 -0
  7. package/dist/agent-ours/file-rpc.d.ts +12 -0
  8. package/dist/agent-ours/file-rpc.js +18 -4
  9. package/dist/agent-ours/harness.js +9 -1
  10. package/dist/agent-ours/mcp-endpoint.d.ts +4 -0
  11. package/dist/agent-ours/mcp-endpoint.js +5 -0
  12. package/dist/agent-ours/runtime.d.ts +9 -1
  13. package/dist/agent-ours/runtime.js +50 -2
  14. package/dist/agent-ours/service.d.ts +21 -1
  15. package/dist/agent-ours/service.js +94 -14
  16. package/dist/application/codex-models.d.ts +15 -0
  17. package/dist/application/codex-models.js +56 -0
  18. package/dist/application/conversation-history.d.ts +27 -0
  19. package/dist/application/conversation-history.js +212 -0
  20. package/dist/application/fleet-query-service.d.ts +1 -1
  21. package/dist/application/fleet-query-service.js +2 -2
  22. package/dist/application/legacy-supervisor-identity.d.ts +7 -0
  23. package/dist/application/legacy-supervisor-identity.js +43 -0
  24. package/dist/application/log-service.js +8 -8
  25. package/dist/application/model-catalog.d.ts +1 -1
  26. package/dist/application/model-catalog.js +5 -2
  27. package/dist/application/preset-provenance.d.ts +19 -0
  28. package/dist/application/preset-provenance.js +59 -0
  29. package/dist/application/role-creation-service.js +3 -2
  30. package/dist/application/role-removal-service.js +9 -1
  31. package/dist/application/role-repository.js +19 -2
  32. package/dist/application/room-layout-definitions.d.ts +45 -0
  33. package/dist/application/room-layout-definitions.js +130 -0
  34. package/dist/application/session-control.d.ts +30 -0
  35. package/dist/application/session-control.js +72 -3
  36. package/dist/application/supervisor-ours-tools.d.ts +159 -0
  37. package/dist/application/supervisor-ours-tools.js +115 -0
  38. package/dist/application/task-layouts.d.ts +91 -0
  39. package/dist/application/task-layouts.js +259 -0
  40. package/dist/application/task-room-service.d.ts +99 -3
  41. package/dist/application/task-room-service.js +285 -32
  42. package/dist/application/types.d.ts +2 -0
  43. package/dist/atomic-file.d.ts +5 -0
  44. package/dist/atomic-file.js +62 -1
  45. package/dist/briefing.d.ts +3 -1
  46. package/dist/briefing.js +70 -30
  47. package/dist/build-info.json +7 -4
  48. package/dist/capabilities.d.ts +6 -1
  49. package/dist/capabilities.js +8 -0
  50. package/dist/cli.js +407 -37
  51. package/dist/client-profile.d.ts +5 -17
  52. package/dist/client-profile.js +4 -127
  53. package/dist/config.d.ts +45 -0
  54. package/dist/config.js +57 -6
  55. package/dist/creation.d.ts +1 -1
  56. package/dist/creation.js +4 -4
  57. package/dist/daemon-recovery.d.ts +1 -8
  58. package/dist/daemon-recovery.js +8 -113
  59. package/dist/docs.d.ts +1 -1
  60. package/dist/docs.js +123 -19
  61. package/dist/doctor.d.ts +1 -1
  62. package/dist/doctor.js +55 -60
  63. package/dist/erased-resources.d.ts +9 -0
  64. package/dist/erased-resources.js +87 -0
  65. package/dist/file-delivery/reader.d.ts +15 -0
  66. package/dist/file-delivery/reader.js +63 -0
  67. package/dist/file-delivery/store.d.ts +15 -0
  68. package/dist/file-delivery/store.js +124 -0
  69. package/dist/file-delivery/types.d.ts +19 -0
  70. package/dist/file-delivery/types.js +1 -0
  71. package/dist/fleet-command-audit.d.ts +7 -0
  72. package/dist/fleet-command-audit.js +26 -9
  73. package/dist/harness/agent-session.d.ts +2 -0
  74. package/dist/harness/claude-code-session.js +1 -1
  75. package/dist/harness/claude-code.js +20 -11
  76. package/dist/harness/claude-runtime.d.ts +12 -0
  77. package/dist/harness/claude-runtime.js +43 -0
  78. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  79. package/dist/harness/codex-app-server-proxy.js +41 -5
  80. package/dist/harness/codex-reasoning.d.ts +5 -0
  81. package/dist/harness/codex-reasoning.js +12 -0
  82. package/dist/harness/codex-runtime.d.ts +11 -1
  83. package/dist/harness/codex-runtime.js +31 -4
  84. package/dist/harness/codex-session.js +2 -2
  85. package/dist/harness/codex.js +23 -12
  86. package/dist/init-wizard.d.ts +2 -0
  87. package/dist/init-wizard.js +38 -19
  88. package/dist/isolation/policy.js +6 -1
  89. package/dist/isolation/types.d.ts +5 -0
  90. package/dist/managed-cli.d.ts +253 -0
  91. package/dist/managed-cli.js +923 -0
  92. package/dist/managed-recovery.d.ts +13 -0
  93. package/dist/managed-recovery.js +31 -0
  94. package/dist/minimal-setup.d.ts +2 -0
  95. package/dist/minimal-setup.js +44 -0
  96. package/dist/monitor.d.ts +8 -34
  97. package/dist/monitor.js +89 -152
  98. package/dist/notifications/fleet-producer.d.ts +19 -0
  99. package/dist/notifications/fleet-producer.js +208 -0
  100. package/dist/notifications/outbox.d.ts +46 -0
  101. package/dist/notifications/outbox.js +158 -0
  102. package/dist/notifications/target-cleanup.d.ts +8 -0
  103. package/dist/notifications/target-cleanup.js +41 -0
  104. package/dist/notifications/task-producer.d.ts +18 -0
  105. package/dist/notifications/task-producer.js +67 -0
  106. package/dist/ops.d.ts +2 -0
  107. package/dist/ops.js +20 -3
  108. package/dist/owner-channel/channel.js +17 -6
  109. package/dist/owner-channel/commands.d.ts +4 -0
  110. package/dist/owner-channel/commands.js +8 -0
  111. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  112. package/dist/owner-channel/ours-client.js +2 -17
  113. package/dist/paths.d.ts +2 -0
  114. package/dist/paths.js +2 -0
  115. package/dist/preset-migration.js +25 -0
  116. package/dist/resolved-plan.js +1 -0
  117. package/dist/rooms-tasks/add-member.d.ts +48 -0
  118. package/dist/rooms-tasks/add-member.js +83 -0
  119. package/dist/rooms-tasks/archived-absence.d.ts +8 -0
  120. package/dist/rooms-tasks/archived-absence.js +48 -0
  121. package/dist/rooms-tasks/cli.js +65 -5
  122. package/dist/rooms-tasks/close.d.ts +6 -2
  123. package/dist/rooms-tasks/close.js +246 -37
  124. package/dist/rooms-tasks/config.d.ts +1 -1
  125. package/dist/rooms-tasks/config.js +11 -4
  126. package/dist/rooms-tasks/cowork-adapter.d.ts +2 -4
  127. package/dist/rooms-tasks/cowork-adapter.js +7 -121
  128. package/dist/rooms-tasks/cowork-http.js +29 -1
  129. package/dist/rooms-tasks/deletion.d.ts +1 -1
  130. package/dist/rooms-tasks/deletion.js +84 -5
  131. package/dist/rooms-tasks/erasure.d.ts +6 -0
  132. package/dist/rooms-tasks/erasure.js +173 -0
  133. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  134. package/dist/rooms-tasks/external-worker.js +3 -4
  135. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  136. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  137. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  138. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  139. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  140. package/dist/rooms-tasks/layout-cli.js +107 -0
  141. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  142. package/dist/rooms-tasks/layout-config.js +89 -0
  143. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  144. package/dist/rooms-tasks/layout-control.js +52 -0
  145. package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
  146. package/dist/rooms-tasks/layout-member-retirement.js +90 -0
  147. package/dist/rooms-tasks/layout-service.d.ts +43 -0
  148. package/dist/rooms-tasks/layout-service.js +203 -0
  149. package/dist/rooms-tasks/layout.d.ts +121 -0
  150. package/dist/rooms-tasks/layout.js +285 -0
  151. package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
  152. package/dist/rooms-tasks/legacy-task-member.js +116 -0
  153. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  154. package/dist/rooms-tasks/live-readiness.js +85 -0
  155. package/dist/rooms-tasks/member-ownership.d.ts +5 -0
  156. package/dist/rooms-tasks/member-ownership.js +40 -0
  157. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  158. package/dist/rooms-tasks/member-startup.js +2 -0
  159. package/dist/rooms-tasks/provision.d.ts +3 -0
  160. package/dist/rooms-tasks/provision.js +101 -49
  161. package/dist/rooms-tasks/recovery.d.ts +19 -0
  162. package/dist/rooms-tasks/recovery.js +110 -0
  163. package/dist/rooms-tasks/room-state.d.ts +4 -2
  164. package/dist/rooms-tasks/room-state.js +47 -8
  165. package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
  166. package/dist/rooms-tasks/task-service-retirement.js +21 -0
  167. package/dist/rooms-tasks/task-state.d.ts +51 -8
  168. package/dist/rooms-tasks/task-state.js +245 -25
  169. package/dist/rooms-tasks/types.d.ts +40 -0
  170. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  171. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  172. package/dist/rooms-tasks/workspace.d.ts +35 -0
  173. package/dist/rooms-tasks/workspace.js +325 -0
  174. package/dist/runner.d.ts +25 -3
  175. package/dist/runner.js +291 -49
  176. package/dist/session/acp.d.ts +53 -1
  177. package/dist/session/acp.js +216 -40
  178. package/dist/session/arbiter.d.ts +11 -0
  179. package/dist/session/arbiter.js +43 -2
  180. package/dist/session/codex-app-server.d.ts +32 -0
  181. package/dist/session/codex-app-server.js +137 -23
  182. package/dist/session/control.d.ts +12 -1
  183. package/dist/session/control.js +68 -3
  184. package/dist/session/conversation-normalizer.d.ts +2 -1
  185. package/dist/session/conversation-normalizer.js +1 -1
  186. package/dist/session/conversation-store.d.ts +1 -1
  187. package/dist/session/conversation-store.js +7 -11
  188. package/dist/session/conversation-types.d.ts +28 -3
  189. package/dist/session/prompt-batch.d.ts +63 -0
  190. package/dist/session/prompt-batch.js +86 -0
  191. package/dist/session/task-notice.d.ts +14 -0
  192. package/dist/session/task-notice.js +13 -0
  193. package/dist/session/types.d.ts +14 -0
  194. package/dist/setup-tunnel-preflight.d.ts +34 -0
  195. package/dist/setup-tunnel-preflight.js +62 -0
  196. package/dist/socket-path.d.ts +2 -0
  197. package/dist/socket-path.js +22 -0
  198. package/dist/spawn.d.ts +5 -1
  199. package/dist/spawn.js +40 -4
  200. package/dist/startup-prompt.d.ts +4 -0
  201. package/dist/startup-prompt.js +36 -0
  202. package/dist/startup-readiness.d.ts +13 -0
  203. package/dist/startup-readiness.js +38 -0
  204. package/dist/startup-telemetry.d.ts +16 -0
  205. package/dist/startup-telemetry.js +46 -0
  206. package/dist/subscriptions/cli.d.ts +91 -0
  207. package/dist/subscriptions/cli.js +223 -0
  208. package/dist/subscriptions/launch.d.ts +37 -0
  209. package/dist/subscriptions/launch.js +93 -0
  210. package/dist/subscriptions/login.d.ts +75 -0
  211. package/dist/subscriptions/login.js +182 -0
  212. package/dist/subscriptions/observed.d.ts +7 -0
  213. package/dist/subscriptions/observed.js +44 -0
  214. package/dist/subscriptions/probe.d.ts +10 -0
  215. package/dist/subscriptions/probe.js +73 -0
  216. package/dist/subscriptions/service.d.ts +102 -0
  217. package/dist/subscriptions/service.js +364 -0
  218. package/dist/subscriptions/store.d.ts +71 -0
  219. package/dist/subscriptions/store.js +140 -0
  220. package/dist/supervisor/adoption.d.ts +8 -0
  221. package/dist/supervisor/adoption.js +78 -0
  222. package/dist/supervisor/catalog.d.ts +62 -0
  223. package/dist/supervisor/catalog.js +254 -0
  224. package/dist/supervisor/fleet.d.ts +8 -0
  225. package/dist/supervisor/fleet.js +89 -0
  226. package/dist/supervisor/index.js +3 -6
  227. package/dist/supervisor/launchd.d.ts +1 -1
  228. package/dist/supervisor/launchd.js +26 -13
  229. package/dist/supervisor/legacy.d.ts +35 -0
  230. package/dist/supervisor/legacy.js +524 -0
  231. package/dist/supervisor/manager.d.ts +15 -0
  232. package/dist/supervisor/manager.js +270 -0
  233. package/dist/supervisor/scope.d.ts +4 -0
  234. package/dist/supervisor/scope.js +10 -0
  235. package/dist/supervisor/systemd.d.ts +2 -2
  236. package/dist/supervisor/systemd.js +19 -33
  237. package/dist/task-supervision.d.ts +9 -0
  238. package/dist/task-supervision.js +145 -0
  239. package/dist/temp-idle.d.ts +17 -0
  240. package/dist/temp-idle.js +42 -0
  241. package/dist/temp-lifecycle.d.ts +23 -8
  242. package/dist/temp-lifecycle.js +113 -65
  243. package/dist/temp-supervisor-recovery.d.ts +1 -1
  244. package/dist/temp-supervisor-recovery.js +2 -2
  245. package/dist/tunnel-setup-completion.d.ts +7 -0
  246. package/dist/tunnel-setup-completion.js +13 -0
  247. package/dist/tunnel-setup-input.d.ts +19 -0
  248. package/dist/tunnel-setup-input.js +124 -0
  249. package/dist/web/agent-attachments.d.ts +29 -0
  250. package/dist/web/agent-attachments.js +162 -0
  251. package/dist/web/auth.d.ts +63 -2
  252. package/dist/web/auth.js +191 -10
  253. package/dist/web/available-port.d.ts +2 -0
  254. package/dist/web/available-port.js +23 -0
  255. package/dist/web/control.d.ts +3 -3
  256. package/dist/web/control.js +10 -8
  257. package/dist/web/fleet-config-service.d.ts +4 -1
  258. package/dist/web/fleet-config-service.js +46 -15
  259. package/dist/web/prefix-gateway.d.ts +32 -0
  260. package/dist/web/prefix-gateway.js +238 -0
  261. package/dist/web/runtime.d.ts +3 -1
  262. package/dist/web/runtime.js +116 -31
  263. package/dist/web/server.d.ts +16 -0
  264. package/dist/web/server.js +654 -55
  265. package/dist/web/service.d.ts +11 -2
  266. package/dist/web/service.js +30 -4
  267. package/dist/web/workspace-devices.d.ts +107 -0
  268. package/dist/web/workspace-devices.js +277 -0
  269. package/dist/web/workspace-tunnel.d.ts +1 -0
  270. package/dist/web/workspace-tunnel.js +34 -0
  271. package/dist/workspace-enrollment.d.ts +82 -0
  272. package/dist/workspace-enrollment.js +566 -0
  273. package/dist/workspace-replacement.d.ts +66 -0
  274. package/dist/workspace-replacement.js +220 -0
  275. package/docs/acp-files.md +146 -0
  276. package/docs/fleet-migration.md +54 -0
  277. package/docs/live-voice.md +13 -0
  278. package/docs/room-layouts.md +227 -0
  279. package/docs/task-workspaces.md +225 -0
  280. package/docs/validation/managed-cli-permissions.md +421 -0
  281. package/examples/room-layouts/fresh.yaml +27 -0
  282. package/examples/room-layouts/scoped.yaml +21 -0
  283. package/examples/room-layouts/shared.yaml +19 -0
  284. package/package.json +20 -19
  285. package/presets/README.md +78 -0
  286. package/presets/brain-catalog.json +8 -2
  287. package/presets/fleet/agent_templates/Critic.yaml +1 -1
  288. package/presets/fleet/agent_templates/Developer.yaml +1 -1
  289. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  290. package/presets/fleet/agent_templates/LocalCoordinator.yaml +1 -1
  291. package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
  292. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  293. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  294. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  295. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  296. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  297. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  298. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  299. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  300. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  301. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  302. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  303. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  304. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  305. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  306. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  307. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  308. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  309. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  310. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  311. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  312. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  313. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  314. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  315. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  316. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  317. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  318. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  319. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  320. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  321. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  322. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  323. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  324. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  325. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  326. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  327. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  328. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  329. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  330. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  331. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  332. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  333. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  334. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  335. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  336. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  337. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  338. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  339. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  340. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  341. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  342. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  343. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  344. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  345. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  346. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  347. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  348. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  349. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  350. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  351. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  352. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  353. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  354. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  355. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  356. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  357. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  358. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  359. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  360. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  361. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  362. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  363. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  364. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  365. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  366. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  367. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  368. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  369. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  370. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  371. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  372. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  373. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  374. package/presets/fleet/roles/Coordinator.yaml +34 -11
  375. package/presets/fleet/roles/Engineer.yaml +40 -0
  376. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  377. package/presets/fleet/room_layouts/pair.yaml +24 -0
  378. package/presets/fleet/room_layouts/single.yaml +17 -0
  379. package/presets/fleet/room_layouts/team.yaml +30 -0
  380. package/presets/fleet/room_templates/engineering.yaml +19 -0
  381. package/presets/manifest.json +2 -2
  382. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  383. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  384. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  385. package/dist/web-app/icons/ours-fleet.svg +0 -4
  386. package/dist/web-app/index.html +0 -17
  387. package/dist/web-app/manifest.webmanifest +0 -15
  388. package/dist/web-app/offline.html +0 -18
  389. package/dist/web-app/sw.js +0 -51
package/README.md CHANGED
@@ -10,8 +10,9 @@ turns such sessions into **roles**: long-lived agents that
10
10
 
11
11
  - **run through structured managed sessions** behind one provider-neutral
12
12
  agent-session interface, which you can inspect or prompt,
13
- - are **supervised** — systemd (Linux) or launchd (macOS) restarts them on crash
14
- and brings them back after a reboot,
13
+ - are **supervised** — one Fleet systemd service (Linux) or LaunchAgent (macOS)
14
+ runs their existing agent runners, restarts them on crash, and restores the
15
+ desired running roster at boot or login,
15
16
  - **resume their context** across restarts (when the harness supports it),
16
17
  - **bind an ours.network identity**, so you — and every other agent — can message
17
18
  them by name over an end-to-end-encrypted channel
@@ -44,11 +45,11 @@ brain: { inline: { harness: codex, session: codex-app-server } }
44
45
 
45
46
  ```
46
47
  ~/fleet.yaml + ~/fleet/{agents,agent_templates,roles,brains,room_templates}/*.yaml your declaration
47
- │ ours-fleet up
48
+ │ ours-fleet init, then up
48
49
  ▼
49
- briefing.md per role ──► agent session adapter ──► native app-server or ACP transport
50
- ▲ │
51
- systemd --user / launchd ───────┘ restart on crash, start at boot/login
50
+ one Fleet OS service ──► private member catalog + existing agent runners
51
+ │
52
+ briefing.md per member ──► session adapter ──► native app-server or ACP transport
52
53
  ```
53
54
 
54
55
  Each role gets a state dir (`~/.ours-fleet/agents/<Name>/`) holding its briefing,
@@ -79,11 +80,12 @@ The state dir contract:
79
80
  |---|---|---|
80
81
  | Node ≥ 22 | runs `ours-fleet` and its maintained adapters | nodejs.org, `apt`, or `brew` |
81
82
  | a harness CLI, logged in | the agent itself | e.g. Claude Code (`claude`) or Codex CLI (`codex`) |
82
- | `ours` CLI + shared daemon | identity + agent-to-agent messaging | `npm i -g @ours.network/cli@2.8.1-nightly.7 @ours.network/daemon@3.8.1-nightly.1 && ours-daemon start` |
83
+ | `ours` CLI + shared daemon | identity + agent-to-agent messaging | `ours-install client --config /absolute/private/profile.json --integrations fleet --fleet-settings /absolute/fleet-settings.json` |
83
84
 
84
- Linux only: `ours-fleet init` enables *linger* so roles run without a login session
85
- and survive reboots. macOS: launchd agents start **at login** (no linger
86
- equivalent); logs land in `~/.ours-fleet/logs/`.
85
+ Linux only: `ours-fleet init` enables *linger* so Fleet runs without a login session
86
+ and restores running members after reboot. On macOS the Fleet LaunchAgent starts
87
+ **at login** (no linger equivalent). Member logs live in each member's state
88
+ directory; use `ours-fleet logs <Name>` to read them.
87
89
 
88
90
  ## Install
89
91
 
@@ -103,6 +105,12 @@ maintained adapters require Node 22 or newer.
103
105
  Each OS user manages their own fleet — to host roles under a sandboxed account,
104
106
  become that account and repeat.
105
107
 
108
+ When upgrading from per-agent services, coordinate package installation with
109
+ explicit `ours-fleet init`. Preserve operator readiness hooks on the common
110
+ parent before migration; new task/temporary creation requires that parent.
111
+ See the [migration and rollback runbook](docs/fleet-migration.md)
112
+ for changed stop/restart behaviour and legacy task transfer limits.
113
+
106
114
  ## Quickstart
107
115
 
108
116
  ```sh
@@ -139,72 +147,57 @@ the caller's owner channel with the caller and spawned-role details. This is an
139
147
  honest-actor convenience and attribution path, not a security boundary; host
140
148
  shells and deliberately bypassed absolute binaries retain direct behavior.
141
149
 
142
- ## Local web console
150
+ ## Local HTTP service
143
151
 
144
- The interactive console is packaged with `@ours.network/fleet` and binds to
145
- IPv4 loopback by default. Remote or proxy exposure is always explicit:
152
+ Fleet is an HTTP backend. It serves no pages, bundles no frontend and opens no
153
+ browser: every screen belongs to the App, which calls this API with a device
154
+ credential. Any address outside `/api/` answers JSON `404`.
146
155
 
147
156
  ```sh
148
- npm run build
149
- ours-fleet web
157
+ ours-fleet setup-tunnel <encoded-v2-grant> # App command; prints QR and connection code
158
+ ours-fleet link-device # connect another browser or device
150
159
  # choose a free port for an isolated test:
151
- ours-fleet web serve --port 0 --no-open
152
- # nginx/TLS terminates at the declared browser origin; fleet remains loopback-bound
160
+ ours-fleet web serve --port 0
161
+ # nginx/TLS terminates at the declared origin; fleet remains loopback-bound
153
162
  ours-fleet web install --public-origin https://fleet.example.com --password-file /secure/fleet-password
154
- # Intentional no-password mode, for example when nginx already authenticates:
155
- ours-fleet web install --public-origin https://fleet.example.com --no-password
156
163
  ```
157
164
 
158
- The normal `ours-fleet web` command installs or updates an owner-level native
159
- service, starts it on stable `127.0.0.1:49271`, and opens/re-pairs the browser.
160
- Linux uses a systemd user unit and macOS uses a LaunchAgent; both restart after
161
- process failures and send logs to the native supervisor. Service management is
162
- explicit through `ours-fleet web install|start|stop|restart|status|uninstall`.
163
- Use `ours-fleet web serve` for a foreground development process. Linux login
164
- persistence requires linger; the installer reports when it is missing but
165
+ `ours-fleet web` installs or updates an owner-level native service and starts
166
+ it on stable `127.0.0.1:49271`. Linux uses a systemd user unit and macOS uses a
167
+ LaunchAgent; both restart after process failures and send logs to the native
168
+ supervisor. Service management is explicit through
169
+ `ours-fleet web install|start|stop|restart|status|uninstall`. Use
170
+ `ours-fleet web serve` for a foreground development process. `--no-open` is
171
+ still accepted because installed service units pass it; it has no effect. Linux
172
+ login persistence requires linger; the installer reports when it is missing but
165
173
  never enables it or requests root privileges.
166
174
 
167
- The normal command opens a one-time five-minute fragment directly in the local
168
- browser; it does not print a reusable secret. If the browser needs pairing
169
- again while the server is running, use `ours-fleet web open`. The fragment is
170
- exchanged once and removed from history. A paired browser receives a rotating,
171
- 30-day `HttpOnly; SameSite=Strict` device credential and can return after a
172
- session idle timeout or server restart. Use **Sign out** to revoke the current
173
- browser, or `ours-fleet web revoke-all` to revoke every trusted browser and
174
- active web session.
175
-
176
- Only a domain-separated SHA-256 device-secret hash and bounded timestamps are
177
- stored in the owner-private fleet state directory (`0700` directory, `0600`
178
- atomic file). The re-pair and revoke controls use an owner-private Unix socket;
179
- local processes running as the same OS user are therefore inside the trust
180
- boundary.
175
+ Use `ours-fleet web revoke-all` to revoke every linked device and active
176
+ session. Only a domain-separated SHA-256 device-secret hash and bounded
177
+ timestamps are stored in the owner-private fleet state directory (`0700`
178
+ directory, `0600` atomic file). App browser links use 5-minute access
179
+ credentials and rotating refresh credentials; see
180
+ [workspace onboarding](docs/workspace-onboarding.md#browser-link-credentials). The link and revoke controls use an
181
+ owner-private Unix socket; local processes running as the same OS user are
182
+ therefore inside the trust boundary.
181
183
 
182
184
  On first setup, the CLI requires an explicit access choice: `--password-file`
183
185
  or `--pairing` for protected access, or `--no-password` for intentional
184
186
  unprotected access. `--password-file` stores only a salted scrypt verifier in
185
- the owner-private web state; the source file remains operator-managed. New
186
- browsers sign in and then receive the same rotating HttpOnly trusted-device
187
- credential. `--no-password` is deliberately named and prints a warning: anyone
188
- who can reach that origin can control the fleet.
187
+ the owner-private web state; the source file remains operator-managed.
188
+ `--no-password` is deliberately named and prints a warning: anyone who can
189
+ reach that origin can control the fleet.
189
190
 
190
191
  For nginx on a VPS, keep the default loopback bind and set the exact external
191
192
  `--public-origin` (scheme, hostname, optional port). nginx should proxy HTTP and
192
193
  WebSocket upgrades to `127.0.0.1:49271` and provide TLS; rewriting the upstream
193
- Host is not required because the declared browser Origin remains authoritative. To listen beyond
194
+ Host is not required because the declared Origin remains authoritative. To listen beyond
194
195
  loopback, add an explicit `--bind`; fleet refuses a non-loopback bind without a
195
196
  public origin. Host and Origin validation use that declaration rather than
196
197
  trusting forwarded headers. `localhost` and `127.0.0.1` both work in normal
197
- local mode; an unconfigured hostname gets a self-describing HTML page instead
198
- of raw internal Host-header JSON.
199
-
200
- The console is installable as a standalone PWA. Its service worker caches only
201
- the data-free offline page and successful content-hashed JavaScript/CSS assets.
202
- HTML stays network-first and no API, authentication, bootstrap, device,
203
- WebSocket, terminal, event, audit, log, session, query-bearing, or error response
204
- is cached. When the local daemon is unavailable, the PWA shows an explicit
205
- offline shell and no stale fleet state.
198
+ local mode; an unconfigured hostname is refused with a JSON error.
206
199
 
207
- The console provides evidence-separated inventory and status, ACP activity and
200
+ The API provides evidence-separated inventory and status, ACP activity and
208
201
  permission controls, redacted logs, typed text send, confirmed lifecycle
209
202
  actions, and transactional permanent/temporary creation. Identity is fixed to
210
203
  the role name. Creation uses the authenticated
@@ -303,10 +296,33 @@ ours-fleet loops reload <Role>
303
296
  ours-fleet loops run-now|disable|enable <Role> <Loop>
304
297
  ours-fleet rm <Name>
305
298
  ours-fleet doctor [--harness H]
299
+ ours-fleet managed-cli setup [--enable <Agent>]... | status [--json] native harness policy for the task workflow
306
300
  ours-fleet version [--json] build identity, capabilities, installs on PATH
307
301
  ours-fleet init
308
302
  ```
309
303
 
304
+ ### Fleet task commands from a harness command sandbox
305
+
306
+ A Codex or Claude command sandbox refuses the supervisor socket, so a managed
307
+ `ours-fleet` call fails with `connect EPERM` before it parses anything. Fleet
308
+ prepares the native harness policy for the packaged Coordinator task workflow;
309
+ you do not write Codex rules or Claude sandbox settings by hand:
310
+
311
+ ```sh
312
+ ours-fleet managed-cli setup --enable FleetCoordinator # adds managed_cli: [task-workflow] to that Agent
313
+ ours-fleet managed-cli status # static setup, session policy, observed commands
314
+ ```
315
+
316
+ The opt-in is an explicit Agent key and changes no permission. Setup starts no
317
+ session or model, is repeated at every agent start, and `ours-install` runs it
318
+ for you. It prepares `task create|start|finish|block|unblock|review|list|show`,
319
+ `room show|members` and template/plan/help inspection for one pinned
320
+ configuration, and nothing else; `task start`/`task finish` are real authority.
321
+ Qualified end to end on Linux with Codex (native and ACP) and Claude ACP; macOS
322
+ is prepared the same way but not yet qualified. Scope, boundaries, unsupported
323
+ combinations and the evidence are in
324
+ [docs/validation/managed-cli-permissions.md](docs/validation/managed-cli-permissions.md).
325
+
310
326
  ### Which build am I running?
311
327
 
312
328
  `--version` prints a semver, and a semver does not identify an artifact: version
@@ -325,9 +341,9 @@ Installs predating the stamp are compared by hashing their `dist/`, so two of
325
341
  those are still told apart.
326
342
 
327
343
  A permanent role brought up via `-c custom.yaml` remembers that file (`.config-path`
328
- in its state dir) across supervisor-triggered restarts — systemd/launchd re-invoke the
329
- agent process with no arguments, so without this the role would silently fall back to
330
- the default `~/fleet.yaml` on its very first crash-restart and fail to resolve.
344
+ in its state dir and its private member registration) across supervisor-triggered
345
+ restarts. Its runner resolves that original configuration instead of falling back
346
+ to the default `~/fleet.yaml`.
331
347
 
332
348
  ## split configuration field reference
333
349
 
@@ -376,9 +392,9 @@ preserve at most one recent late occurrence. The trusted authoring file and
376
392
  private sealed role snapshot retain exact prompt text; resolved launch, task,
377
393
  room, provenance, and audit presentation surfaces show only bytes and SHA-256.
378
394
 
379
- Every packaged `Developer`, `Critic`, and `LocalCoordinator` Agent Template uses
395
+ Every packaged `Developer`, `Engineer`, `Critic`, and `LocalCoordinator` Agent Template uses
380
396
  `monitor.mode: fleet` with `monitor.interrupt: after_tool`. Consequently every
381
- member of the standard `single`, `pair`, and `team` Room Templates resolves to
397
+ member of the standard `single`, `pair`, `team`, and `engineering` Room Templates resolves to
382
398
  that policy. A custom Agent Template or explicit per-member override remains
383
399
  authoritative and is merged key by key without rewriting unrelated values.
384
400
 
@@ -524,7 +540,7 @@ ours-fleet up
524
540
 
525
541
  ### Rooms and tasks
526
542
 
527
- Init installs editable `single`, `pair`, and `team` definitions under
543
+ Init installs editable `single`, `pair`, `team`, and `engineering` definitions under
528
544
  `~/fleet/room_templates/`, plus every exact-cased Agent, Role, and Brain they
529
545
  reference. Inspect them with `ours-fleet template list` and
530
546
  `ours-fleet template show team`. After configuring the authenticated owner below:
@@ -533,8 +549,25 @@ reference. Inspect them with `ours-fleet template list` and
533
549
  ours-fleet task create --title "Solo task" --template single
534
550
  ours-fleet task create --title "Reviewed change" --template pair
535
551
  ours-fleet task create --title "Phased delivery" --template team
552
+ ours-fleet task create --title "Gated feature build" --template engineering
536
553
  ```
537
554
 
555
+ `engineering` pairs a gate-pipeline `Engineer` with the standard `Critic`. The
556
+ Engineer works every non-trivial task through ordered gates — scope and a numbered
557
+ Definition of Done before code, an over-engineering check, spec before
558
+ implementation, test-first, review, a sized security pass, docs, and evidence-backed
559
+ DoD verification — invoking an installed gate-pipeline skill when one is present and
560
+ walking the same gates by hand otherwise. The seat is labelled `Engineer`, so a
561
+ gated seat is never mistaken for a plain `Developer`. To make it the default for
562
+ development tasks, set `tasks: { default_room_template: engineering }` in
563
+ `fleet.yaml`.
564
+
565
+ The `engineering` starter expresses a prompt-level workflow mandate; Fleet does not enforce
566
+ the gates at runtime or install pipeline skills. The Engineer label identifies that mandate,
567
+ not a completed review. When migrating an existing install, a newly added Engineer uses
568
+ the existing Developer template's brain selection and keeps the packaged restrictive permissions.
569
+ Existing customized Engineer files are preserved.
570
+
538
571
  The default `team` gives only its LocalCoordinator Agent Template a 15-minute
539
572
  continuity loop. Each idle-only pass uses authenticated assigned-room evidence,
540
573
  posts at most one missing interval update or status request, and reports `STALLED`
@@ -588,8 +621,9 @@ non-owner-controlled parent fail closed before host setup and are rechecked unde
588
621
  per-setup init lock before publication.
589
622
 
590
623
  The generated task experiences are fixed consequences, not extra questions: `single`
591
- uses `Developer`; `pair` uses `Developer` with an independent `Critic`; and `team` uses
592
- task-local `LocalCoordinator`, `Developer`, and `Critic`. The persistent
624
+ uses `Developer`; `pair` uses `Developer` with an independent `Critic`; `team` uses
625
+ task-local `LocalCoordinator`, `Developer`, and `Critic`; and `engineering` uses the
626
+ gate-pipeline `Engineer` with an independent `Critic`. The persistent
593
627
  `FleetCoordinator` uses the separate packaged `Coordinator` contract and coordination
594
628
  model.
595
629
 
@@ -666,6 +700,29 @@ continuation is serialized per Task and remains alive until convergence or an
666
700
  Owner-action blocker. Re-running `task start <id>` safely resumes the same durable
667
701
  provisioning operation after the blocker is corrected or a process restarts.
668
702
 
703
+ Live health is distinct from durable lifecycle. `task show TASK --json` adds a
704
+ `readiness` observation for active tasks (`ready`, `degraded`, or `unknown`); human
705
+ and authenticated Owner task-show output display the same observation. Task start/work
706
+ continue to reject unavailable health with `task_not_ready`. A same-role untracked
707
+ seat or a changed recorded launch cannot satisfy an original slot. Each control,
708
+ liveness, and production Cowork probe is bounded; members are checked sequentially,
709
+ so total latency grows with room size. These are point-in-time observations, not
710
+ proof that a timed-out session is dead or permission to respawn it.
711
+
712
+ Before deliberate recovery, Fleet Coordinator must inspect existing room seats and
713
+ the exact old launch's termination record and worklog under `recovery/temporary`.
714
+ Keep original slot records and archives intact; record verified old/new identity
715
+ and launch provenance privately. Never restore archived identity state or reuse
716
+ consumed invites. A same-role seat is only a possible replacement, not proven ownership.
717
+
718
+ A replacement's empty inbox does not establish that no work is pending. Paginate
719
+ scoped room/operator history to the end, retain the cursor privately, authenticate
720
+ historical Owner instructions from identity metadata, and compare replies, worklogs,
721
+ and already-completed actions before resuming. Ask the Owner when authority or
722
+ completion is uncertain. Transfer only necessary non-secret context; never replay
723
+ instructions blindly. Observation does not adopt seats, launch replacements, change
724
+ lifecycle, or modify retained recovery evidence.
725
+
669
726
  Set `room.anonymous: true` on a room template, or pass `--anonymous` to
670
727
  `task create`, `task start`, `task work`, or `room create`, to create an
671
728
  anonymous Cowork room. `--no-anonymous` explicitly overrides an anonymous
@@ -1348,8 +1405,9 @@ The command override is exact: Fleet does not append `--profile`, `--search`, or
1348
1405
 
1349
1406
  One-off/permanent spawn selects a Brain that owns model, reasoning, native permission,
1350
1407
  sandbox, profile, launcher, search, monitor consent, native config, and additional roots.
1351
- Use `env.OURS_PORT`/`env.OURS_CONFIG` for a
1352
- role-specific ours daemon, or configure the host default in `~/.ours/config.json`.
1408
+ All roles use the shared gateway profile `~/.ours-client/profile.json`.
1409
+ `OURS_CONFIG` selects an alternate whole profile. Legacy port/token/state-dir
1410
+ overrides are rejected. See the [gateway setup guide](https://github.com/adapt-toolkit/ours-network/blob/prerelease/packages/installer/GATEWAY_SETUP.md).
1353
1411
 
1354
1412
  ## Agent isolation
1355
1413
 
@@ -1710,3 +1768,167 @@ Explicit Cowork socket, config or state-directory overrides continue to select
1710
1768
  local Unix management. Profiles without `serverUrl` retain legacy behavior. The
1711
1769
  HTTP API grants operator room authority; use the installer's supported private
1712
1770
  or authenticated external gateway entry, and keep its backend ports private.
1771
+
1772
+ ### Agent ours tools through the supervisor
1773
+
1774
+ Operators can invoke the running agent's ordinary ours MCP tools without sending
1775
+ an LLM prompt or binding another session to its identity:
1776
+
1777
+ ```sh
1778
+ ours-fleet ours tools Critic1
1779
+ ours-fleet ours call Critic1 current_identity
1780
+ ours-fleet ours call Critic1 list_contacts
1781
+ ours-fleet ours call Critic1 generate_invite --args-file /private/invite-options.json
1782
+ ours-fleet ours call Critic1 add_contact --args-file /private/contact.json
1783
+ ```
1784
+
1785
+ `tools` returns the managed MCP tool names and argument schemas, plus the selected
1786
+ agent's identity name, CID, and supervisor generation. `call` returns the same
1787
+ identity metadata and the MCP result. The private JSON file contains the tool's
1788
+ arguments (for example `{"invite":"…"}` for `add_contact`); omitted arguments mean
1789
+ `{}`. Protect files containing invites and protect command output containing a
1790
+ new invite. Tool errors set a nonzero CLI exit status.
1791
+
1792
+ The authenticated REST equivalents are `GET /api/v1/roles/:id/ours/tools` and
1793
+ `POST /api/v1/roles/:id/ours/call`, with the normal Fleet session and CSRF token.
1794
+ The POST body is `{"tool":"list_contacts","arguments":{}}`. MCP tool errors
1795
+ remain in `result.isError`; transport failures use the normal Fleet error envelope.
1796
+ Request arguments and results are excluded from the Fleet audit log.
1797
+
1798
+ Both interfaces use the supervisor's existing fixed-identity MCP server and tool
1799
+ policy. Identity creation, removal, switching, and binding are not exposed. The
1800
+ supervisor must be running. Older descriptors are supported only when a unique
1801
+ existing runtime journal, instance record, and identity pin prove the selected
1802
+ agent and generation, and the same MCP connection confirms its identity and
1803
+ lifetime before the operation. This reads existing state without rewriting the
1804
+ descriptor or restarting the agent. Missing, ambiguous, stale, or mismatched
1805
+ proofs fail closed. Unknown identity descriptions also fail closed. Closing an operator call
1806
+ retains the supervisor's identity. An interrupted mutation can have an unknown
1807
+ outcome: inspect state before retrying, because there is no automatic retry or
1808
+ exactly-once guarantee. Contact acceptance alone does not prove peer verification
1809
+ or message delivery. File tools resolve paths in the invoking CLI process or
1810
+ Fleet web server's filesystem context, with that process's access permissions.
1811
+
1812
+ Task workspace ownership, retention, safe deletion and legacy migration are documented in [Task workspaces](docs/task-workspaces.md).
1813
+
1814
+ ### Active task readiness after interruption
1815
+
1816
+ Task and room list states, and `taskProvisioningOutcome`, describe durable lifecycle
1817
+ and provisioning progress; they are not live health checks. Retrying `task start`
1818
+ or `task work` on an active task checks the current Cowork room identity and seats,
1819
+ member launch ownership, supervisor liveness, and authenticated session status
1820
+ before reporting success. Waiting for provisioning completion also checks live
1821
+ readiness. This is a point-in-time observation, not proof of an agent-authored reply.
1822
+
1823
+ A `task_not_ready` result distinguishes confirmed degradation from unknown health
1824
+ (for example, an unavailable control socket). Ask Fleet Coordinator to inspect room
1825
+ and member status and choose supported recovery. These checks do not restart agents,
1826
+ recreate identities, redeem invites, or rewrite lifecycle state. Temporary room agents
1827
+ remain transient across host reboot; retained launch records do not restore them.
1828
+
1829
+ See [predefined Brain models and runtime requirements](presets/README.md) for the verified model/effort matrix and regeneration instructions.
1830
+
1831
+ ### YAML room layouts
1832
+
1833
+ Room layouts describe room composition with shared or fresh participant sessions and independent room closure.
1834
+ See [Room layouts](docs/room-layouts.md) for YAML examples and CLI commands.
1835
+
1836
+
1837
+ ### Dedicated notification service
1838
+
1839
+ Configure the web backend with `OURS_NOTIFICATIONS_ORIGIN` and a Fleet-scoped `OURS_NOTIFICATIONS_PRODUCER_TOKEN`. It reads each local supervisor ledger incrementally with persistent checkpoints under web state, correlating owner browser/channel prompts with terminal completion. Monitor/startup turns do not notify. First installation skips existing history; no agent restart or conversation controller is needed. Persist web state across deployment/restarts. Reads are bounded to 256 KiB per role per tick, and oversized model/media records are skipped across chunks. Expose `/notifications` through the generic authenticated prefix gateway with a server-side user token and `stripBrowserContext: true`; producer tokens stay server-side. All browser sessions of this single-owner console map to one stable notification account. See [ours-notifications](https://github.com/adapt-toolkit/ours-notifications) for configuration/API/release details.
1840
+
1841
+ Existing-host enrollment: `ours-fleet workspace-enroll --file <private-file> --preserve-profile` requires Messenger to advertise preservation support before any enrollment POST. It omits Name/Surname and leaves existing/absent profile untouched. Existing Fleet models and agents are retained; the installer must skip init when its configuration exists. Signed root proof, tunnel setup and device QR issuance remain the normal enrollment flow. Older Messenger fails closed and requires its preservation-capable release.
1842
+
1843
+ ### Connect an installed host to the App
1844
+
1845
+ Install Ours network first. In the App's tunnel step, copy the single command and
1846
+ paste it on the intended host, including in an SSH session on a VPS:
1847
+
1848
+ ```sh
1849
+ ours-fleet setup-tunnel <encoded-v2-grant>
1850
+ ```
1851
+
1852
+ The base64url argument contains only the existing v2 grant: `version: 2`, allowed
1853
+ `appOrigin`, one-use `code`, and `expiresAt`. It names the workspace indirectly
1854
+ through a server-held grant; it includes no broad Cloudflare credential or
1855
+ installer script. The grant can appear in shell history and process listings:
1856
+ keep the command private and remove it from history after use. Base64 is encoding,
1857
+ not encryption. The server enforces its short expiry and one-time redemption.
1858
+ Fleet never prints the grant; it checks host prerequisites before redeeming it
1859
+ over HTTPS POST, with the code in the body rather than a URL. The response supplies
1860
+ only the existing scoped connector and signed-root enrollment data; authorization,
1861
+ account-origin checks and private connector token-file storage remain enforced.
1862
+
1863
+ Optional private transports remain available: `setup-tunnel --file /private/grant`
1864
+ requires an owned regular file with mode 600; `setup-tunnel --stdin` reads a secure
1865
+ pipe with a 32KiB limit and refuses a terminal. Legacy v1 payloads, which contain
1866
+ long-lived scoped credentials, are accepted only through file/stdin, never as
1867
+ command arguments. Use only one payload transport.
1868
+
1869
+ When this host already has a registration, Fleet inspects the one-use grant without
1870
+ consuming it. The same workspace reruns without a deletion prompt or retirement.
1871
+ An account-origin change for that workspace requires `--migrate-app-origin`; a
1872
+ changed server identity is refused. An older App without inspection support falls
1873
+ back to asking before redemption. An unavailable inspection service preserves the
1874
+ grant and setup. Fleet verifies the redeemed destination against the inspection.
1875
+
1876
+ For another workspace, setup describes the existing workspace, tunnel hostname and
1877
+ account origin and asks `[y/N]`. No answer or `no` preserves the setup and grant; a
1878
+ noninteractive caller must pass `--replace-registration`, otherwise it exits with
1879
+ an error. A legacy binding without a server identity must rerun its own workspace
1880
+ first. The original Human root signs retirement. Fleet waits for the account's
1881
+ durable cleanup receipt before stopping the old service and revoking its linked
1882
+ devices. If a migrated database has no old registration, the signed command confirms
1883
+ absence; the service has no old provider resources to delete. Installation identities,
1884
+ profile, agents, history, stable host ID and local pairing are preserved.
1885
+
1886
+ Replacement recovery is saved in an owned private `workspace/replacement.json`
1887
+ after root, host, service and server-contact preconditions pass. The App must
1888
+ explicitly support deadline-enforced retirement; an older App without that
1889
+ capability preserves the existing setup. `setup-tunnel --resume` retries its nonce
1890
+ and saved operation deadline (24 hours less a five-minute clock margin).
1891
+ If the enrollment challenge expires, obtain a fresh App command for the same target
1892
+ and pass `--replace-registration`; completed retirement is retained. The old server
1893
+ identity is pinned: only its own invitation can reconnect it.
1894
+
1895
+ `setup-tunnel --abandon-replacement` removes the private recovery payload only when
1896
+ a fresh private receipt confirms no deletion and the operation was never dispatched
1897
+ or was terminally rejected. A lost transport response remains uncertain. Expired
1898
+ operations require a fresh receipt proving the old binding still exists after the
1899
+ deadline plus five minutes and an explicit server guarantee that the deadline is enforced;
1900
+ older recovery records without that guarantee must be resumed. Abandoning preserves
1901
+ the existing binding, connector and installation data. A terminally rejected operation
1902
+ requires abandonment and a new App command, rather than reusing its nonce.
1903
+ After that deadline, a fresh command for the same target can also resume with a
1904
+ new operation nonce after checking the enforced expiry. This confirms signed
1905
+ absence if an old successful receipt was lost and later pruned.
1906
+
1907
+ If the App accepted the successor proof before Fleet wrote its local binding,
1908
+ a fresh command for that target retains the original private connector from the
1909
+ recovery record. If that successor cannot be recovered, remove it in the App,
1910
+ then use `setup-tunnel --discard-retired-replacement` and a fresh App command.
1911
+ Discard is allowed only after retirement and local cleanup, while the old local
1912
+ binding remains. It removes only the recovery record. This host has no working
1913
+ registration until the new setup completes; the old service was stopped and its
1914
+ linked devices revoked.
1915
+
1916
+ Renewal commands contain no existing live connector credential. Fleet keeps the
1917
+ current private connector byte for byte, and accepts renewal only for its recorded
1918
+ workspace, server, origin and tunnel hostname. Restore a missing or unsafe connector,
1919
+ or remove and re-create that workspace in the App before setting it up again.
1920
+
1921
+ After service and signed tunnel-target confirmation, setup prints both a QR and
1922
+ ordinary private single-use connection code. The App checks readiness automatically
1923
+ and immediately opens the code field. If setup or code output fails after binding,
1924
+ fix the reported problem and run `ours-fleet setup-tunnel --resume`; its private
1925
+ pending record remains until the code is printed, including confirmed nondefault
1926
+ ports. `ours-fleet link-device` still generates another code for additional browsers
1927
+ or expired codes. `--check` checks prerequisites without consuming a grant.
1928
+
1929
+ Prerelease rollout requires this Fleet capability to be published first, then the
1930
+ installer's normal generated version/integrity lock updated, then installer and
1931
+ App released. The currently pinned Fleet nightly.41 does not support v2 grants.
1932
+ These source changes do not publish, merge, or deploy any component.
1933
+
1934
+ See [ACP file sending](docs/acp-files.md) for the same-chat `send_file` flow, available to every Agent by default, and its supported sessions.
@@ -0,0 +1,2 @@
1
+ export declare const accountOrigins: readonly ["https://app.ours.network", "https://app.ours-tunnel.com"];
2
+ export declare function validateAccountOrigin(value: unknown): string;
@@ -0,0 +1,6 @@
1
+ export const accountOrigins = ['https://app.ours.network', 'https://app.ours-tunnel.com'];
2
+ export function validateAccountOrigin(value) {
3
+ if (typeof value !== 'string' || !accountOrigins.some(origin => origin === value))
4
+ throw Error('Unsupported account origin');
5
+ return value;
6
+ }
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/env node
2
+ import { openChatFile } from '../file-delivery/reader.js';
3
+ import { createHash } from 'node:crypto';
2
4
  import { connect } from 'node:net';
3
5
  import { access, mkdir, open, readFile } from 'node:fs/promises';
4
6
  import { constants } from 'node:fs';
5
7
  import { basename, dirname, resolve } from 'node:path';
6
8
  import { fileURLToPath } from 'node:url';
7
9
  import { MAX_CHUNK_BYTES, MAX_FRAME_BYTES, Wire } from './wire.js';
10
+ /** A current-chat refusal the agent may see; it names a reason, never a path or content. */
11
+ class ChatFileError extends Error {
12
+ }
8
13
  /** Runs inside exactly the harness OS sandbox. Only this process opens agent paths. */
9
14
  export async function runBridge(descriptorPath) {
10
15
  const descriptor = JSON.parse(await readFile(descriptorPath, 'utf8'));
@@ -12,6 +17,14 @@ export async function runBridge(descriptorPath) {
12
17
  typeof descriptor.capability !== 'string' ||
13
18
  !Number.isInteger(descriptor.generation))
14
19
  throw Error('INVALID_BRIDGE_DESCRIPTOR');
20
+ if (process.env.FLEET_OURS_BRIDGE_EXPECTED) {
21
+ const expected = JSON.parse(process.env.FLEET_OURS_BRIDGE_EXPECTED);
22
+ const digest = createHash('sha256').update(JSON.stringify([descriptor.socket, descriptor.capability, descriptor.generation])).digest('hex');
23
+ if (expected.transportDigest !== digest)
24
+ throw Error('SUPERVISOR_TRANSPORT_CHANGED');
25
+ if (['role', 'identity', 'cid', 'generation'].some(key => descriptor[key] !== expected[key]))
26
+ throw Error('SUPERVISOR_SELECTION_CHANGED');
27
+ }
15
28
  const wire = new Wire(connect(descriptor.socket));
16
29
  const handles = new Map();
17
30
  const cleanup = async () => {
@@ -62,7 +75,7 @@ export async function runBridge(descriptorPath) {
62
75
  value = false;
63
76
  }
64
77
  }
65
- else if (op === 'read-open' || op === 'write-open') {
78
+ else if (op === 'read-open' || op === 'write-open' || op === 'export-open') {
66
79
  if (handles.size >= 32 ||
67
80
  typeof args.handle !== 'string' ||
68
81
  handles.has(args.handle) ||
@@ -71,12 +84,20 @@ export async function runBridge(descriptorPath) {
71
84
  const path = resolve(args.path);
72
85
  if (op === 'write-open')
73
86
  await mkdir(dirname(path), { recursive: true });
74
- const file = await open(path, op === 'write-open' ? 'w' : 'r');
75
- handles.set(args.handle, { file, call, write: op === 'write-open' });
76
- value =
77
- op === 'write-open'
78
- ? path
79
- : { filename: basename(path), size: (await file.stat()).size };
87
+ if (op === 'export-open') {
88
+ const opened = await openChatFile(process.cwd(), args.path).catch((error) => { throw new ChatFileError(error.message); });
89
+ const stat = await opened.file.stat();
90
+ handles.set(args.handle, { file: opened.file, call, write: false, original: { size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs } });
91
+ value = { filename: basename(opened.path), size: stat.size, path: opened.path };
92
+ }
93
+ else {
94
+ const file = await open(path, op === 'write-open' ? 'w' : 'r');
95
+ handles.set(args.handle, { file, call, write: op === 'write-open' });
96
+ value =
97
+ op === 'write-open'
98
+ ? path
99
+ : { filename: basename(path), size: (await file.stat()).size };
100
+ }
80
101
  }
81
102
  else {
82
103
  const row = handles.get(args.handle);
@@ -96,6 +117,11 @@ export async function runBridge(descriptorPath) {
96
117
  value = null;
97
118
  }
98
119
  else if (op === 'read' && !row.write) {
120
+ if (row.original) {
121
+ const stat = await row.file.stat();
122
+ if (!stat.isFile() || stat.nlink !== 1 || stat.size !== row.original.size || stat.mtimeMs !== row.original.mtimeMs || stat.ctimeMs !== row.original.ctimeMs)
123
+ throw new ChatFileError('CHAT_FILE_CHANGED');
124
+ }
99
125
  const buffer = Buffer.alloc(MAX_CHUNK_BYTES);
100
126
  const { bytesRead } = await row.file.read(buffer);
101
127
  value = bytesRead ? buffer.subarray(0, bytesRead).toString('base64') : null;
@@ -120,8 +146,8 @@ export async function runBridge(descriptorPath) {
120
146
  }
121
147
  await wire.send({ kind: 'fs-result', id: raw.id, value });
122
148
  }
123
- catch {
124
- await wire.send({ kind: 'fs-result', id: raw.id, error: 'FILE_OPERATION_FAILED' });
149
+ catch (error) {
150
+ await wire.send({ kind: 'fs-result', id: raw.id, error: error instanceof ChatFileError ? error.message : 'FILE_OPERATION_FAILED' });
125
151
  }
126
152
  })
127
153
  .catch(fail);
@@ -0,0 +1,10 @@
1
+ /** Read-only operations exposed by the identity-owning supervisor. */
2
+ export interface AgentHistoryQuery {
3
+ peer_cid: string;
4
+ limit?: number;
5
+ before_seq?: number;
6
+ }
7
+ export interface SupervisorCorrespondence {
8
+ contacts(): Promise<unknown>;
9
+ history(request: AgentHistoryQuery): Promise<unknown>;
10
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -11,11 +11,23 @@ export declare class FileCallbacks implements FileExecutionContext {
11
11
  private rpc;
12
12
  canRead(path: string, extra: ToolRequestExtra): Promise<boolean>;
13
13
  read(path: string, extra: ToolRequestExtra): Promise<{
14
+ path?: string | undefined;
14
15
  filename: any;
15
16
  size: any;
16
17
  body: ReadableStream<Uint8Array<ArrayBufferLike>>;
17
18
  close: () => Promise<void>;
18
19
  }>;
20
+ /** Current-chat source: integrity-checked by the bridge, with its real path. */
21
+ readChatFile(path: string, extra: ToolRequestExtra): Promise<{
22
+ path?: string | undefined;
23
+ filename: any;
24
+ size: any;
25
+ body: ReadableStream<Uint8Array<ArrayBufferLike>>;
26
+ close: () => Promise<void>;
27
+ } & {
28
+ path: string;
29
+ }>;
30
+ private openRead;
19
31
  write(path: string, body: ReadableStream<Uint8Array>, extra: ToolRequestExtra): Promise<{
20
32
  path: string;
21
33
  size: number;