@ours.network/fleet 1.2.0-nightly.5 → 1.2.0-nightly.51

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 (330) hide show
  1. package/README.md +263 -53
  2. package/dist/account-origin.d.ts +2 -0
  3. package/dist/account-origin.js +6 -0
  4. package/dist/agent-ours/bridge.js +9 -0
  5. package/dist/agent-ours/correspondence.d.ts +10 -0
  6. package/dist/agent-ours/correspondence.js +1 -0
  7. package/dist/agent-ours/harness.js +8 -0
  8. package/dist/agent-ours/runtime.d.ts +6 -0
  9. package/dist/agent-ours/runtime.js +36 -0
  10. package/dist/agent-ours/service.js +33 -13
  11. package/dist/application/codex-models.d.ts +15 -0
  12. package/dist/application/codex-models.js +56 -0
  13. package/dist/application/conversation-history.d.ts +25 -0
  14. package/dist/application/conversation-history.js +189 -0
  15. package/dist/application/fleet-query-service.d.ts +1 -1
  16. package/dist/application/fleet-query-service.js +2 -2
  17. package/dist/application/legacy-supervisor-identity.d.ts +7 -0
  18. package/dist/application/legacy-supervisor-identity.js +43 -0
  19. package/dist/application/model-catalog.d.ts +1 -1
  20. package/dist/application/model-catalog.js +5 -2
  21. package/dist/application/preset-provenance.d.ts +19 -0
  22. package/dist/application/preset-provenance.js +59 -0
  23. package/dist/application/role-creation-service.js +1 -1
  24. package/dist/application/role-removal-service.js +2 -0
  25. package/dist/application/role-repository.js +2 -2
  26. package/dist/application/room-layout-definitions.d.ts +45 -0
  27. package/dist/application/room-layout-definitions.js +130 -0
  28. package/dist/application/session-control.d.ts +30 -0
  29. package/dist/application/session-control.js +72 -3
  30. package/dist/application/supervisor-ours-tools.d.ts +159 -0
  31. package/dist/application/supervisor-ours-tools.js +113 -0
  32. package/dist/application/task-layouts.d.ts +91 -0
  33. package/dist/application/task-layouts.js +249 -0
  34. package/dist/application/task-room-service.d.ts +99 -3
  35. package/dist/application/task-room-service.js +296 -31
  36. package/dist/atomic-file.d.ts +5 -0
  37. package/dist/atomic-file.js +62 -1
  38. package/dist/briefing.d.ts +2 -0
  39. package/dist/briefing.js +8 -1
  40. package/dist/build-info.json +7 -4
  41. package/dist/capabilities.d.ts +6 -1
  42. package/dist/capabilities.js +8 -0
  43. package/dist/cli.js +376 -34
  44. package/dist/client-profile.d.ts +5 -17
  45. package/dist/client-profile.js +4 -127
  46. package/dist/config.d.ts +28 -0
  47. package/dist/config.js +41 -6
  48. package/dist/creation.js +2 -2
  49. package/dist/daemon-recovery.d.ts +1 -8
  50. package/dist/daemon-recovery.js +8 -113
  51. package/dist/docs.d.ts +3 -3
  52. package/dist/docs.js +126 -22
  53. package/dist/doctor.d.ts +1 -1
  54. package/dist/doctor.js +55 -60
  55. package/dist/erased-resources.d.ts +9 -0
  56. package/dist/erased-resources.js +87 -0
  57. package/dist/fleet-command-audit.d.ts +7 -0
  58. package/dist/fleet-command-audit.js +26 -9
  59. package/dist/harness/claude-code.js +9 -1
  60. package/dist/harness/claude-runtime.d.ts +12 -0
  61. package/dist/harness/claude-runtime.js +43 -0
  62. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  63. package/dist/harness/codex-app-server-proxy.js +41 -5
  64. package/dist/harness/codex-reasoning.d.ts +5 -0
  65. package/dist/harness/codex-reasoning.js +12 -0
  66. package/dist/harness/codex-runtime.d.ts +11 -1
  67. package/dist/harness/codex-runtime.js +31 -4
  68. package/dist/harness/codex.d.ts +3 -2
  69. package/dist/harness/codex.js +20 -11
  70. package/dist/init-wizard.d.ts +2 -0
  71. package/dist/init-wizard.js +38 -19
  72. package/dist/isolation/policy.js +2 -0
  73. package/dist/isolation/types.d.ts +5 -0
  74. package/dist/managed-cli.d.ts +253 -0
  75. package/dist/managed-cli.js +923 -0
  76. package/dist/minimal-setup.d.ts +2 -0
  77. package/dist/minimal-setup.js +44 -0
  78. package/dist/monitor.d.ts +1 -34
  79. package/dist/monitor.js +24 -151
  80. package/dist/notifications/fleet-producer.d.ts +19 -0
  81. package/dist/notifications/fleet-producer.js +208 -0
  82. package/dist/notifications/outbox.d.ts +46 -0
  83. package/dist/notifications/outbox.js +158 -0
  84. package/dist/notifications/target-cleanup.d.ts +8 -0
  85. package/dist/notifications/target-cleanup.js +41 -0
  86. package/dist/ops.js +5 -1
  87. package/dist/owner-channel/channel.d.ts +3 -0
  88. package/dist/owner-channel/channel.js +34 -6
  89. package/dist/owner-channel/commands.d.ts +4 -0
  90. package/dist/owner-channel/commands.js +8 -0
  91. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  92. package/dist/owner-channel/ours-client.js +2 -17
  93. package/dist/paths.d.ts +2 -0
  94. package/dist/paths.js +2 -0
  95. package/dist/preset-migration.js +25 -0
  96. package/dist/resolved-plan.js +1 -0
  97. package/dist/rooms-tasks/add-member.d.ts +48 -0
  98. package/dist/rooms-tasks/add-member.js +83 -0
  99. package/dist/rooms-tasks/archived-absence.d.ts +8 -0
  100. package/dist/rooms-tasks/archived-absence.js +48 -0
  101. package/dist/rooms-tasks/cli.js +34 -5
  102. package/dist/rooms-tasks/close.d.ts +5 -2
  103. package/dist/rooms-tasks/close.js +208 -28
  104. package/dist/rooms-tasks/config.d.ts +1 -1
  105. package/dist/rooms-tasks/config.js +11 -4
  106. package/dist/rooms-tasks/cowork-adapter.d.ts +6 -4
  107. package/dist/rooms-tasks/cowork-adapter.js +8 -121
  108. package/dist/rooms-tasks/deletion.d.ts +1 -1
  109. package/dist/rooms-tasks/deletion.js +74 -5
  110. package/dist/rooms-tasks/erasure.d.ts +6 -0
  111. package/dist/rooms-tasks/erasure.js +169 -0
  112. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  113. package/dist/rooms-tasks/external-worker.js +3 -4
  114. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  115. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  116. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  117. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  118. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  119. package/dist/rooms-tasks/layout-cli.js +107 -0
  120. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  121. package/dist/rooms-tasks/layout-config.js +89 -0
  122. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  123. package/dist/rooms-tasks/layout-control.js +52 -0
  124. package/dist/rooms-tasks/layout-service.d.ts +42 -0
  125. package/dist/rooms-tasks/layout-service.js +185 -0
  126. package/dist/rooms-tasks/layout.d.ts +114 -0
  127. package/dist/rooms-tasks/layout.js +250 -0
  128. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  129. package/dist/rooms-tasks/live-readiness.js +85 -0
  130. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  131. package/dist/rooms-tasks/member-startup.js +2 -0
  132. package/dist/rooms-tasks/provision.d.ts +14 -0
  133. package/dist/rooms-tasks/provision.js +173 -46
  134. package/dist/rooms-tasks/room-state.d.ts +4 -2
  135. package/dist/rooms-tasks/room-state.js +53 -8
  136. package/dist/rooms-tasks/task-state.d.ts +42 -7
  137. package/dist/rooms-tasks/task-state.js +153 -23
  138. package/dist/rooms-tasks/types.d.ts +28 -0
  139. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  140. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  141. package/dist/rooms-tasks/workspace.d.ts +26 -0
  142. package/dist/rooms-tasks/workspace.js +195 -0
  143. package/dist/runner.d.ts +19 -3
  144. package/dist/runner.js +128 -45
  145. package/dist/session/acp.d.ts +9 -1
  146. package/dist/session/acp.js +31 -6
  147. package/dist/session/arbiter.d.ts +5 -0
  148. package/dist/session/arbiter.js +28 -2
  149. package/dist/session/codex-app-server.d.ts +5 -0
  150. package/dist/session/codex-app-server.js +36 -3
  151. package/dist/session/control.d.ts +12 -1
  152. package/dist/session/control.js +68 -3
  153. package/dist/session/conversation-normalizer.d.ts +2 -1
  154. package/dist/session/conversation-normalizer.js +1 -1
  155. package/dist/session/conversation-store.d.ts +1 -1
  156. package/dist/session/conversation-store.js +7 -11
  157. package/dist/session/conversation-types.d.ts +7 -3
  158. package/dist/session/task-notice.d.ts +14 -0
  159. package/dist/session/task-notice.js +13 -0
  160. package/dist/session/types.d.ts +6 -0
  161. package/dist/setup-tunnel-preflight.d.ts +34 -0
  162. package/dist/setup-tunnel-preflight.js +62 -0
  163. package/dist/socket-path.d.ts +2 -0
  164. package/dist/socket-path.js +22 -0
  165. package/dist/spawn.js +8 -1
  166. package/dist/startup-readiness.d.ts +13 -0
  167. package/dist/startup-readiness.js +38 -0
  168. package/dist/subscriptions/cli.d.ts +91 -0
  169. package/dist/subscriptions/cli.js +223 -0
  170. package/dist/subscriptions/launch.d.ts +37 -0
  171. package/dist/subscriptions/launch.js +93 -0
  172. package/dist/subscriptions/login.d.ts +75 -0
  173. package/dist/subscriptions/login.js +182 -0
  174. package/dist/subscriptions/observed.d.ts +7 -0
  175. package/dist/subscriptions/observed.js +44 -0
  176. package/dist/subscriptions/probe.d.ts +10 -0
  177. package/dist/subscriptions/probe.js +73 -0
  178. package/dist/subscriptions/service.d.ts +102 -0
  179. package/dist/subscriptions/service.js +364 -0
  180. package/dist/subscriptions/store.d.ts +71 -0
  181. package/dist/subscriptions/store.js +140 -0
  182. package/dist/supervisor/launchd.js +2 -1
  183. package/dist/supervisor/systemd.js +9 -23
  184. package/dist/temp-idle.d.ts +17 -0
  185. package/dist/temp-idle.js +42 -0
  186. package/dist/temp-lifecycle.d.ts +6 -1
  187. package/dist/temp-lifecycle.js +29 -13
  188. package/dist/tunnel-setup-completion.d.ts +7 -0
  189. package/dist/tunnel-setup-completion.js +13 -0
  190. package/dist/tunnel-setup-input.d.ts +19 -0
  191. package/dist/tunnel-setup-input.js +124 -0
  192. package/dist/web/agent-attachments.d.ts +29 -0
  193. package/dist/web/agent-attachments.js +162 -0
  194. package/dist/web/auth.d.ts +29 -1
  195. package/dist/web/auth.js +82 -7
  196. package/dist/web/available-port.d.ts +2 -0
  197. package/dist/web/available-port.js +23 -0
  198. package/dist/web/control.d.ts +3 -3
  199. package/dist/web/control.js +10 -8
  200. package/dist/web/fleet-config-service.d.ts +4 -1
  201. package/dist/web/fleet-config-service.js +46 -15
  202. package/dist/web/prefix-gateway.d.ts +32 -0
  203. package/dist/web/prefix-gateway.js +234 -0
  204. package/dist/web/runtime.d.ts +3 -1
  205. package/dist/web/runtime.js +116 -31
  206. package/dist/web/server.d.ts +16 -0
  207. package/dist/web/server.js +592 -53
  208. package/dist/web/service.d.ts +11 -2
  209. package/dist/web/service.js +30 -4
  210. package/dist/web/workspace-devices.d.ts +36 -0
  211. package/dist/web/workspace-devices.js +101 -0
  212. package/dist/web/workspace-tunnel.d.ts +1 -0
  213. package/dist/web/workspace-tunnel.js +34 -0
  214. package/dist/workspace-enrollment.d.ts +82 -0
  215. package/dist/workspace-enrollment.js +566 -0
  216. package/dist/workspace-replacement.d.ts +66 -0
  217. package/dist/workspace-replacement.js +220 -0
  218. package/docs/live-voice.md +13 -0
  219. package/docs/room-layouts.md +227 -0
  220. package/docs/task-workspaces.md +130 -0
  221. package/docs/validation/managed-cli-permissions.md +421 -0
  222. package/examples/room-layouts/fresh.yaml +27 -0
  223. package/examples/room-layouts/scoped.yaml +21 -0
  224. package/examples/room-layouts/shared.yaml +19 -0
  225. package/package.json +15 -18
  226. package/presets/README.md +78 -0
  227. package/presets/brain-catalog.json +8 -2
  228. package/presets/fleet/agent_templates/Critic.yaml +1 -1
  229. package/presets/fleet/agent_templates/Developer.yaml +1 -1
  230. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  231. package/presets/fleet/agent_templates/LocalCoordinator.yaml +1 -1
  232. package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
  233. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  234. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  235. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  236. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  237. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  238. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  239. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  240. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  241. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  242. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  243. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  244. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  245. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  246. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  247. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  248. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  249. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  250. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  251. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  252. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  253. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  254. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  255. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  256. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  257. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  258. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  259. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  260. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  261. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  262. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  263. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  264. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  265. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  266. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  267. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  268. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  269. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  270. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  271. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  272. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  273. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  274. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  275. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  276. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  277. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  278. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  279. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  280. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  281. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  282. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  283. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  284. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  285. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  286. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  287. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  288. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  289. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  290. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  291. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  292. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  293. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  294. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  295. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  296. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  297. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  298. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  299. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  300. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  301. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  302. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  303. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  304. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  305. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  306. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  307. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  308. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  309. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  310. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  311. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  312. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  313. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  314. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  315. package/presets/fleet/roles/Coordinator.yaml +34 -11
  316. package/presets/fleet/roles/Engineer.yaml +40 -0
  317. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  318. package/presets/fleet/room_layouts/pair.yaml +24 -0
  319. package/presets/fleet/room_layouts/single.yaml +17 -0
  320. package/presets/fleet/room_layouts/team.yaml +30 -0
  321. package/presets/fleet/room_templates/engineering.yaml +19 -0
  322. package/presets/manifest.json +2 -2
  323. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  324. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  325. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  326. package/dist/web-app/icons/ours-fleet.svg +0 -4
  327. package/dist/web-app/index.html +0 -17
  328. package/dist/web-app/manifest.webmanifest +0 -15
  329. package/dist/web-app/offline.html +0 -18
  330. package/dist/web-app/sw.js +0 -51
package/README.md CHANGED
@@ -79,7 +79,7 @@ The state dir contract:
79
79
  |---|---|---|
80
80
  | Node ≥ 22 | runs `ours-fleet` and its maintained adapters | nodejs.org, `apt`, or `brew` |
81
81
  | 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` |
82
+ | `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
83
 
84
84
  Linux only: `ours-fleet init` enables *linger* so roles run without a login session
85
85
  and survive reboots. macOS: launchd agents start **at login** (no linger
@@ -139,72 +139,55 @@ the caller's owner channel with the caller and spawned-role details. This is an
139
139
  honest-actor convenience and attribution path, not a security boundary; host
140
140
  shells and deliberately bypassed absolute binaries retain direct behavior.
141
141
 
142
- ## Local web console
142
+ ## Local HTTP service
143
143
 
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:
144
+ Fleet is an HTTP backend. It serves no pages, bundles no frontend and opens no
145
+ browser: every screen belongs to the App, which calls this API with a device
146
+ credential. Any address outside `/api/` answers JSON `404`.
146
147
 
147
148
  ```sh
148
- npm run build
149
- ours-fleet web
149
+ ours-fleet setup-tunnel <encoded-v2-grant> # App command; prints QR and connection code
150
+ ours-fleet link-device # connect another browser or device
150
151
  # 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
152
+ ours-fleet web serve --port 0
153
+ # nginx/TLS terminates at the declared origin; fleet remains loopback-bound
153
154
  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
155
  ```
157
156
 
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
157
+ `ours-fleet web` installs or updates an owner-level native service and starts
158
+ it on stable `127.0.0.1:49271`. Linux uses a systemd user unit and macOS uses a
159
+ LaunchAgent; both restart after process failures and send logs to the native
160
+ supervisor. Service management is explicit through
161
+ `ours-fleet web install|start|stop|restart|status|uninstall`. Use
162
+ `ours-fleet web serve` for a foreground development process. `--no-open` is
163
+ still accepted because installed service units pass it; it has no effect. Linux
164
+ login persistence requires linger; the installer reports when it is missing but
165
165
  never enables it or requests root privileges.
166
166
 
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.
167
+ Use `ours-fleet web revoke-all` to revoke every linked device and active
168
+ session. Only a domain-separated SHA-256 device-secret hash and bounded
169
+ timestamps are stored in the owner-private fleet state directory (`0700`
170
+ directory, `0600` atomic file). The link and revoke controls use an
171
+ owner-private Unix socket; local processes running as the same OS user are
172
+ therefore inside the trust boundary.
181
173
 
182
174
  On first setup, the CLI requires an explicit access choice: `--password-file`
183
175
  or `--pairing` for protected access, or `--no-password` for intentional
184
176
  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.
177
+ the owner-private web state; the source file remains operator-managed.
178
+ `--no-password` is deliberately named and prints a warning: anyone who can
179
+ reach that origin can control the fleet.
189
180
 
190
181
  For nginx on a VPS, keep the default loopback bind and set the exact external
191
182
  `--public-origin` (scheme, hostname, optional port). nginx should proxy HTTP and
192
183
  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
184
+ Host is not required because the declared Origin remains authoritative. To listen beyond
194
185
  loopback, add an explicit `--bind`; fleet refuses a non-loopback bind without a
195
186
  public origin. Host and Origin validation use that declaration rather than
196
187
  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.
188
+ local mode; an unconfigured hostname is refused with a JSON error.
206
189
 
207
- The console provides evidence-separated inventory and status, ACP activity and
190
+ The API provides evidence-separated inventory and status, ACP activity and
208
191
  permission controls, redacted logs, typed text send, confirmed lifecycle
209
192
  actions, and transactional permanent/temporary creation. Identity is fixed to
210
193
  the role name. Creation uses the authenticated
@@ -303,10 +286,33 @@ ours-fleet loops reload <Role>
303
286
  ours-fleet loops run-now|disable|enable <Role> <Loop>
304
287
  ours-fleet rm <Name>
305
288
  ours-fleet doctor [--harness H]
289
+ ours-fleet managed-cli setup [--enable <Agent>]... | status [--json] native harness policy for the task workflow
306
290
  ours-fleet version [--json] build identity, capabilities, installs on PATH
307
291
  ours-fleet init
308
292
  ```
309
293
 
294
+ ### Fleet task commands from a harness command sandbox
295
+
296
+ A Codex or Claude command sandbox refuses the supervisor socket, so a managed
297
+ `ours-fleet` call fails with `connect EPERM` before it parses anything. Fleet
298
+ prepares the native harness policy for the packaged Coordinator task workflow;
299
+ you do not write Codex rules or Claude sandbox settings by hand:
300
+
301
+ ```sh
302
+ ours-fleet managed-cli setup --enable FleetCoordinator # adds managed_cli: [task-workflow] to that Agent
303
+ ours-fleet managed-cli status # static setup, session policy, observed commands
304
+ ```
305
+
306
+ The opt-in is an explicit Agent key and changes no permission. Setup starts no
307
+ session or model, is repeated at every agent start, and `ours-install` runs it
308
+ for you. It prepares `task create|start|finish|block|unblock|review|list|show`,
309
+ `room show|members` and template/plan/help inspection for one pinned
310
+ configuration, and nothing else; `task start`/`task finish` are real authority.
311
+ Qualified end to end on Linux with Codex (native and ACP) and Claude ACP; macOS
312
+ is prepared the same way but not yet qualified. Scope, boundaries, unsupported
313
+ combinations and the evidence are in
314
+ [docs/validation/managed-cli-permissions.md](docs/validation/managed-cli-permissions.md).
315
+
310
316
  ### Which build am I running?
311
317
 
312
318
  `--version` prints a semver, and a semver does not identify an artifact: version
@@ -376,9 +382,9 @@ preserve at most one recent late occurrence. The trusted authoring file and
376
382
  private sealed role snapshot retain exact prompt text; resolved launch, task,
377
383
  room, provenance, and audit presentation surfaces show only bytes and SHA-256.
378
384
 
379
- Every packaged `Developer`, `Critic`, and `LocalCoordinator` Agent Template uses
385
+ Every packaged `Developer`, `Engineer`, `Critic`, and `LocalCoordinator` Agent Template uses
380
386
  `monitor.mode: fleet` with `monitor.interrupt: after_tool`. Consequently every
381
- member of the standard `single`, `pair`, and `team` Room Templates resolves to
387
+ member of the standard `single`, `pair`, `team`, and `engineering` Room Templates resolves to
382
388
  that policy. A custom Agent Template or explicit per-member override remains
383
389
  authoritative and is merged key by key without rewriting unrelated values.
384
390
 
@@ -524,7 +530,7 @@ ours-fleet up
524
530
 
525
531
  ### Rooms and tasks
526
532
 
527
- Init installs editable `single`, `pair`, and `team` definitions under
533
+ Init installs editable `single`, `pair`, `team`, and `engineering` definitions under
528
534
  `~/fleet/room_templates/`, plus every exact-cased Agent, Role, and Brain they
529
535
  reference. Inspect them with `ours-fleet template list` and
530
536
  `ours-fleet template show team`. After configuring the authenticated owner below:
@@ -533,8 +539,25 @@ reference. Inspect them with `ours-fleet template list` and
533
539
  ours-fleet task create --title "Solo task" --template single
534
540
  ours-fleet task create --title "Reviewed change" --template pair
535
541
  ours-fleet task create --title "Phased delivery" --template team
542
+ ours-fleet task create --title "Gated feature build" --template engineering
536
543
  ```
537
544
 
545
+ `engineering` pairs a gate-pipeline `Engineer` with the standard `Critic`. The
546
+ Engineer works every non-trivial task through ordered gates — scope and a numbered
547
+ Definition of Done before code, an over-engineering check, spec before
548
+ implementation, test-first, review, a sized security pass, docs, and evidence-backed
549
+ DoD verification — invoking an installed gate-pipeline skill when one is present and
550
+ walking the same gates by hand otherwise. The seat is labelled `Engineer`, so a
551
+ gated seat is never mistaken for a plain `Developer`. To make it the default for
552
+ development tasks, set `tasks: { default_room_template: engineering }` in
553
+ `fleet.yaml`.
554
+
555
+ The `engineering` starter expresses a prompt-level workflow mandate; Fleet does not enforce
556
+ the gates at runtime or install pipeline skills. The Engineer label identifies that mandate,
557
+ not a completed review. When migrating an existing install, a newly added Engineer uses
558
+ the existing Developer template's brain selection and keeps the packaged restrictive permissions.
559
+ Existing customized Engineer files are preserved.
560
+
538
561
  The default `team` gives only its LocalCoordinator Agent Template a 15-minute
539
562
  continuity loop. Each idle-only pass uses authenticated assigned-room evidence,
540
563
  posts at most one missing interval update or status request, and reports `STALLED`
@@ -588,8 +611,9 @@ non-owner-controlled parent fail closed before host setup and are rechecked unde
588
611
  per-setup init lock before publication.
589
612
 
590
613
  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
614
+ uses `Developer`; `pair` uses `Developer` with an independent `Critic`; `team` uses
615
+ task-local `LocalCoordinator`, `Developer`, and `Critic`; and `engineering` uses the
616
+ gate-pipeline `Engineer` with an independent `Critic`. The persistent
593
617
  `FleetCoordinator` uses the separate packaged `Coordinator` contract and coordination
594
618
  model.
595
619
 
@@ -666,6 +690,29 @@ continuation is serialized per Task and remains alive until convergence or an
666
690
  Owner-action blocker. Re-running `task start <id>` safely resumes the same durable
667
691
  provisioning operation after the blocker is corrected or a process restarts.
668
692
 
693
+ Live health is distinct from durable lifecycle. `task show TASK --json` adds a
694
+ `readiness` observation for active tasks (`ready`, `degraded`, or `unknown`); human
695
+ and authenticated Owner task-show output display the same observation. Task start/work
696
+ continue to reject unavailable health with `task_not_ready`. A same-role untracked
697
+ seat or a changed recorded launch cannot satisfy an original slot. Each control,
698
+ liveness, and production Cowork probe is bounded; members are checked sequentially,
699
+ so total latency grows with room size. These are point-in-time observations, not
700
+ proof that a timed-out session is dead or permission to respawn it.
701
+
702
+ Before deliberate recovery, Fleet Coordinator must inspect existing room seats and
703
+ the exact old launch's termination record and worklog under `recovery/temporary`.
704
+ Keep original slot records and archives intact; record verified old/new identity
705
+ and launch provenance privately. Never restore archived identity state or reuse
706
+ consumed invites. A same-role seat is only a possible replacement, not proven ownership.
707
+
708
+ A replacement's empty inbox does not establish that no work is pending. Paginate
709
+ scoped room/operator history to the end, retain the cursor privately, authenticate
710
+ historical Owner instructions from identity metadata, and compare replies, worklogs,
711
+ and already-completed actions before resuming. Ask the Owner when authority or
712
+ completion is uncertain. Transfer only necessary non-secret context; never replay
713
+ instructions blindly. Observation does not adopt seats, launch replacements, change
714
+ lifecycle, or modify retained recovery evidence.
715
+
669
716
  Set `room.anonymous: true` on a room template, or pass `--anonymous` to
670
717
  `task create`, `task start`, `task work`, or `room create`, to create an
671
718
  anonymous Cowork room. `--no-anonymous` explicitly overrides an anonymous
@@ -1348,8 +1395,9 @@ The command override is exact: Fleet does not append `--profile`, `--search`, or
1348
1395
 
1349
1396
  One-off/permanent spawn selects a Brain that owns model, reasoning, native permission,
1350
1397
  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`.
1398
+ All roles use the shared gateway profile `~/.ours-client/profile.json`.
1399
+ `OURS_CONFIG` selects an alternate whole profile. Legacy port/token/state-dir
1400
+ overrides are rejected. See the [gateway setup guide](https://github.com/adapt-toolkit/ours-network/blob/prerelease/packages/installer/GATEWAY_SETUP.md).
1353
1401
 
1354
1402
  ## Agent isolation
1355
1403
 
@@ -1710,3 +1758,165 @@ Explicit Cowork socket, config or state-directory overrides continue to select
1710
1758
  local Unix management. Profiles without `serverUrl` retain legacy behavior. The
1711
1759
  HTTP API grants operator room authority; use the installer's supported private
1712
1760
  or authenticated external gateway entry, and keep its backend ports private.
1761
+
1762
+ ### Agent ours tools through the supervisor
1763
+
1764
+ Operators can invoke the running agent's ordinary ours MCP tools without sending
1765
+ an LLM prompt or binding another session to its identity:
1766
+
1767
+ ```sh
1768
+ ours-fleet ours tools Critic1
1769
+ ours-fleet ours call Critic1 current_identity
1770
+ ours-fleet ours call Critic1 list_contacts
1771
+ ours-fleet ours call Critic1 generate_invite --args-file /private/invite-options.json
1772
+ ours-fleet ours call Critic1 add_contact --args-file /private/contact.json
1773
+ ```
1774
+
1775
+ `tools` returns the managed MCP tool names and argument schemas, plus the selected
1776
+ agent's identity name, CID, and supervisor generation. `call` returns the same
1777
+ identity metadata and the MCP result. The private JSON file contains the tool's
1778
+ arguments (for example `{"invite":"…"}` for `add_contact`); omitted arguments mean
1779
+ `{}`. Protect files containing invites and protect command output containing a
1780
+ new invite. Tool errors set a nonzero CLI exit status.
1781
+
1782
+ The authenticated REST equivalents are `GET /api/v1/roles/:id/ours/tools` and
1783
+ `POST /api/v1/roles/:id/ours/call`, with the normal Fleet session and CSRF token.
1784
+ The POST body is `{"tool":"list_contacts","arguments":{}}`. MCP tool errors
1785
+ remain in `result.isError`; transport failures use the normal Fleet error envelope.
1786
+ Request arguments and results are excluded from the Fleet audit log.
1787
+
1788
+ Both interfaces use the supervisor's existing fixed-identity MCP server and tool
1789
+ policy. Identity creation, removal, switching, and binding are not exposed. The
1790
+ supervisor must be running. Older descriptors are supported only when a unique
1791
+ existing runtime journal, instance record, and identity pin prove the selected
1792
+ agent and generation, and the same MCP connection confirms its identity and
1793
+ lifetime before the operation. This reads existing state without rewriting the
1794
+ descriptor or restarting the agent. Missing, ambiguous, stale, or mismatched
1795
+ proofs fail closed. Unknown identity descriptions also fail closed. Closing an operator call
1796
+ retains the supervisor's identity. An interrupted mutation can have an unknown
1797
+ outcome: inspect state before retrying, because there is no automatic retry or
1798
+ exactly-once guarantee. Contact acceptance alone does not prove peer verification
1799
+ or message delivery. File tools resolve paths in the invoking CLI process or
1800
+ Fleet web server's filesystem context, with that process's access permissions.
1801
+
1802
+ Task workspace ownership, retention, safe deletion and legacy migration are documented in [Task workspaces](docs/task-workspaces.md).
1803
+
1804
+ ### Active task readiness after interruption
1805
+
1806
+ Task and room list states, and `taskProvisioningOutcome`, describe durable lifecycle
1807
+ and provisioning progress; they are not live health checks. Retrying `task start`
1808
+ or `task work` on an active task checks the current Cowork room identity and seats,
1809
+ member launch ownership, supervisor liveness, and authenticated session status
1810
+ before reporting success. Waiting for provisioning completion also checks live
1811
+ readiness. This is a point-in-time observation, not proof of an agent-authored reply.
1812
+
1813
+ A `task_not_ready` result distinguishes confirmed degradation from unknown health
1814
+ (for example, an unavailable control socket). Ask Fleet Coordinator to inspect room
1815
+ and member status and choose supported recovery. These checks do not restart agents,
1816
+ recreate identities, redeem invites, or rewrite lifecycle state. Temporary room agents
1817
+ remain transient across host reboot; retained launch records do not restore them.
1818
+
1819
+ See [predefined Brain models and runtime requirements](presets/README.md) for the verified model/effort matrix and regeneration instructions.
1820
+
1821
+ ### YAML room layouts
1822
+
1823
+ Room layouts describe room composition with shared or fresh participant sessions and independent room closure.
1824
+ See [Room layouts](docs/room-layouts.md) for YAML examples and CLI commands.
1825
+
1826
+
1827
+ ### Dedicated notification service
1828
+
1829
+ 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.
1830
+
1831
+ 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.
1832
+
1833
+ ### Connect an installed host to the App
1834
+
1835
+ Install Ours network first. In the App's tunnel step, copy the single command and
1836
+ paste it on the intended host, including in an SSH session on a VPS:
1837
+
1838
+ ```sh
1839
+ ours-fleet setup-tunnel <encoded-v2-grant>
1840
+ ```
1841
+
1842
+ The base64url argument contains only the existing v2 grant: `version: 2`, allowed
1843
+ `appOrigin`, one-use `code`, and `expiresAt`. It names the workspace indirectly
1844
+ through a server-held grant; it includes no broad Cloudflare credential or
1845
+ installer script. The grant can appear in shell history and process listings:
1846
+ keep the command private and remove it from history after use. Base64 is encoding,
1847
+ not encryption. The server enforces its short expiry and one-time redemption.
1848
+ Fleet never prints the grant; it checks host prerequisites before redeeming it
1849
+ over HTTPS POST, with the code in the body rather than a URL. The response supplies
1850
+ only the existing scoped connector and signed-root enrollment data; authorization,
1851
+ account-origin checks and private connector token-file storage remain enforced.
1852
+
1853
+ Optional private transports remain available: `setup-tunnel --file /private/grant`
1854
+ requires an owned regular file with mode 600; `setup-tunnel --stdin` reads a secure
1855
+ pipe with a 32KiB limit and refuses a terminal. Legacy v1 payloads, which contain
1856
+ long-lived scoped credentials, are accepted only through file/stdin, never as
1857
+ command arguments. Use only one payload transport.
1858
+
1859
+ When this host already has a registration, Fleet inspects the one-use grant without
1860
+ consuming it. The same workspace reruns without a deletion prompt or retirement.
1861
+ An account-origin change for that workspace requires `--migrate-app-origin`; a
1862
+ changed server identity is refused. An older App without inspection support falls
1863
+ back to asking before redemption. An unavailable inspection service preserves the
1864
+ grant and setup. Fleet verifies the redeemed destination against the inspection.
1865
+
1866
+ For another workspace, setup describes the existing workspace, tunnel hostname and
1867
+ account origin and asks `[y/N]`. No answer or `no` preserves the setup and grant; a
1868
+ noninteractive caller must pass `--replace-registration`, otherwise it exits with
1869
+ an error. A legacy binding without a server identity must rerun its own workspace
1870
+ first. The original Human root signs retirement. Fleet waits for the account's
1871
+ durable cleanup receipt before stopping the old service and revoking its linked
1872
+ devices. If a migrated database has no old registration, the signed command confirms
1873
+ absence; the service has no old provider resources to delete. Installation identities,
1874
+ profile, agents, history, stable host ID and local pairing are preserved.
1875
+
1876
+ Replacement recovery is saved in an owned private `workspace/replacement.json`
1877
+ after root, host, service and server-contact preconditions pass. The App must
1878
+ explicitly support deadline-enforced retirement; an older App without that
1879
+ capability preserves the existing setup. `setup-tunnel --resume` retries its nonce
1880
+ and saved operation deadline (24 hours less a five-minute clock margin).
1881
+ If the enrollment challenge expires, obtain a fresh App command for the same target
1882
+ and pass `--replace-registration`; completed retirement is retained. The old server
1883
+ identity is pinned: only its own invitation can reconnect it.
1884
+
1885
+ `setup-tunnel --abandon-replacement` removes the private recovery payload only when
1886
+ a fresh private receipt confirms no deletion and the operation was never dispatched
1887
+ or was terminally rejected. A lost transport response remains uncertain. Expired
1888
+ operations require a fresh receipt proving the old binding still exists after the
1889
+ deadline plus five minutes and an explicit server guarantee that the deadline is enforced;
1890
+ older recovery records without that guarantee must be resumed. Abandoning preserves
1891
+ the existing binding, connector and installation data. A terminally rejected operation
1892
+ requires abandonment and a new App command, rather than reusing its nonce.
1893
+ After that deadline, a fresh command for the same target can also resume with a
1894
+ new operation nonce after checking the enforced expiry. This confirms signed
1895
+ absence if an old successful receipt was lost and later pruned.
1896
+
1897
+ If the App accepted the successor proof before Fleet wrote its local binding,
1898
+ a fresh command for that target retains the original private connector from the
1899
+ recovery record. If that successor cannot be recovered, remove it in the App,
1900
+ then use `setup-tunnel --discard-retired-replacement` and a fresh App command.
1901
+ Discard is allowed only after retirement and local cleanup, while the old local
1902
+ binding remains. It removes only the recovery record. This host has no working
1903
+ registration until the new setup completes; the old service was stopped and its
1904
+ linked devices revoked.
1905
+
1906
+ Renewal commands contain no existing live connector credential. Fleet keeps the
1907
+ current private connector byte for byte, and accepts renewal only for its recorded
1908
+ workspace, server, origin and tunnel hostname. Restore a missing or unsafe connector,
1909
+ or remove and re-create that workspace in the App before setting it up again.
1910
+
1911
+ After service and signed tunnel-target confirmation, setup prints both a QR and
1912
+ ordinary private single-use connection code. The App checks readiness automatically
1913
+ and immediately opens the code field. If setup or code output fails after binding,
1914
+ fix the reported problem and run `ours-fleet setup-tunnel --resume`; its private
1915
+ pending record remains until the code is printed, including confirmed nondefault
1916
+ ports. `ours-fleet link-device` still generates another code for additional browsers
1917
+ or expired codes. `--check` checks prerequisites without consuming a grant.
1918
+
1919
+ Prerelease rollout requires this Fleet capability to be published first, then the
1920
+ installer's normal generated version/integrity lock updated, then installer and
1921
+ App released. The currently pinned Fleet nightly.41 does not support v2 grants.
1922
+ These source changes do not publish, merge, or deploy any component.
@@ -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,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto';
2
3
  import { connect } from 'node:net';
3
4
  import { access, mkdir, open, readFile } from 'node:fs/promises';
4
5
  import { constants } from 'node:fs';
@@ -12,6 +13,14 @@ export async function runBridge(descriptorPath) {
12
13
  typeof descriptor.capability !== 'string' ||
13
14
  !Number.isInteger(descriptor.generation))
14
15
  throw Error('INVALID_BRIDGE_DESCRIPTOR');
16
+ if (process.env.FLEET_OURS_BRIDGE_EXPECTED) {
17
+ const expected = JSON.parse(process.env.FLEET_OURS_BRIDGE_EXPECTED);
18
+ const digest = createHash('sha256').update(JSON.stringify([descriptor.socket, descriptor.capability, descriptor.generation])).digest('hex');
19
+ if (expected.transportDigest !== digest)
20
+ throw Error('SUPERVISOR_TRANSPORT_CHANGED');
21
+ if (['role', 'identity', 'cid', 'generation'].some(key => descriptor[key] !== expected[key]))
22
+ throw Error('SUPERVISOR_SELECTION_CHANGED');
23
+ }
15
24
  const wire = new Wire(connect(descriptor.socket));
16
25
  const handles = new Map();
17
26
  const cleanup = async () => {
@@ -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 {};
@@ -20,12 +20,19 @@ export function prepareManagedHarness(role, stateDir, cwd, descriptor, env) {
20
20
  args: [bridge],
21
21
  env: [{ name: 'FLEET_OURS_BRIDGE_DESCRIPTOR', value: descriptor }],
22
22
  };
23
+ // Portable allow covers bound identity messaging, not all tools on the server.
24
+ const tools = role.harness === 'codex' && role.permissions?.approval === 'allow'
25
+ ? Object.fromEntries([
26
+ 'current_identity', 'get_messages', 'list_history', 'list_contacts', 'send_message',
27
+ ].map(name => [name, { approval_mode: 'approve' }]))
28
+ : undefined;
23
29
  const native = {
24
30
  mcp_servers: {
25
31
  ours: {
26
32
  command: process.execPath,
27
33
  args: [bridge],
28
34
  env: { FLEET_OURS_BRIDGE_DESCRIPTOR: descriptor },
35
+ ...(tools ? { tools } : {}),
29
36
  },
30
37
  },
31
38
  plugins: { 'ours@ours-codex-marketplace': { enabled: false } },
@@ -35,6 +42,7 @@ export function prepareManagedHarness(role, stateDir, cwd, descriptor, env) {
35
42
  const config = child.CODEX_CONFIG ? JSON.parse(child.CODEX_CONFIG) : {};
36
43
  child.CODEX_CONFIG = JSON.stringify({
37
44
  ...config,
45
+ mcp_servers: { ...config.mcp_servers, ...native.mcp_servers },
38
46
  plugins: { ...config.plugins, ...native.plugins },
39
47
  });
40
48
  // codex-acp otherwise prefers a same-name connector from the user's config.
@@ -1,3 +1,4 @@
1
+ import type { AgentHistoryQuery } from './correspondence.js';
1
2
  import type { OursClient } from '@ours.network/sdk/client';
2
3
  import { RuntimeJournal, type RuntimeState } from './state.js';
3
4
  export interface AssignedIdentity {
@@ -47,6 +48,11 @@ export declare class AgentOursRuntime {
47
48
  prepare(room?: RoomAdmission, timeoutMs?: number): Promise<void>;
48
49
  /** Admission covers SDK calls, response rendering and agent filesystem callbacks. */
49
50
  admit(): Promise<() => void>;
51
+ /** Trusted supervisor-only admission for a later room; keeps the live harness
52
+ * and original startup assignment. Not exposed as an agent lifecycle tool. */
53
+ joinAdditionalRoom(invite: string, expectedRoomCid: string): Promise<void>;
54
+ readContacts(): Promise<unknown>;
55
+ readHistory(request: AgentHistoryQuery): Promise<unknown>;
50
56
  startHarness<T>(start: () => Promise<T>): Promise<T>;
51
57
  suspend(): Promise<void>;
52
58
  terminal(): Promise<void>;
@@ -201,6 +201,42 @@ export class AgentOursRuntime {
201
201
  throw error;
202
202
  }
203
203
  }
204
+ /** Trusted supervisor-only admission for a later room; keeps the live harness
205
+ * and original startup assignment. Not exposed as an agent lifecycle tool. */
206
+ async joinAdditionalRoom(invite, expectedRoomCid) {
207
+ const release = await this.admit();
208
+ try {
209
+ const contact = await this.deps.client.addContact({ invite });
210
+ if (contact.cid !== expectedRoomCid)
211
+ throw Error('ADDITIONAL_ROOM_CID_MISMATCH');
212
+ await this.verify();
213
+ }
214
+ finally {
215
+ release();
216
+ }
217
+ }
218
+ async readContacts() {
219
+ const release = await this.admit();
220
+ try {
221
+ const data = await this.deps.client.listContacts();
222
+ await this.verify();
223
+ return { identity: { name: this.state.name, cid: this.state.cid, generation: this.state.generation }, ...data };
224
+ }
225
+ finally {
226
+ release();
227
+ }
228
+ }
229
+ async readHistory(request) {
230
+ const release = await this.admit();
231
+ try {
232
+ const data = await this.deps.client.listHistory(request);
233
+ await this.verify();
234
+ return { identity: { name: this.state.name, cid: this.state.cid, generation: this.state.generation }, ...data };
235
+ }
236
+ finally {
237
+ release();
238
+ }
239
+ }
204
240
  async startHarness(start) {
205
241
  if (!this.accepting || this.state.phase !== 'READY')
206
242
  throw Error('RUNTIME_NOT_READY');