@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
@@ -0,0 +1,13 @@
1
+ /** Body-free recovery cursor. Dispatching is uncertain after a crash, never
2
+ * permission to replay an initial task which may already have caused effects. */
3
+ export interface ManagedRecovery {
4
+ version: 1;
5
+ session: 'pending' | 'established';
6
+ readiness: boolean;
7
+ initial: 'pending' | 'dispatching' | 'completed';
8
+ active: boolean;
9
+ }
10
+ export declare const managedRecoveryPath: (dir: string) => string;
11
+ export declare function readManagedRecovery(dir: string): ManagedRecovery | undefined;
12
+ export declare function writeManagedRecovery(dir: string, value: ManagedRecovery): void;
13
+ export declare function firstManagedSessionMayStart(dir: string): boolean;
@@ -0,0 +1,31 @@
1
+ import { lstatSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { replaceFileAtomically } from './atomic-file.js';
4
+ export const managedRecoveryPath = (dir) => join(dir, '.managed-recovery.json');
5
+ export function readManagedRecovery(dir) {
6
+ const path = managedRecoveryPath(dir);
7
+ let stat;
8
+ try {
9
+ stat = lstatSync(path);
10
+ }
11
+ catch (error) {
12
+ if (error.code === 'ENOENT')
13
+ return;
14
+ throw error;
15
+ }
16
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 4096)
17
+ throw Error('MANAGED_RECOVERY_UNSAFE_PROOF');
18
+ const value = JSON.parse(readFileSync(path, 'utf8'));
19
+ if (value.version !== 1 || !['pending', 'established'].includes(value.session)
20
+ || !['pending', 'dispatching', 'completed'].includes(value.initial)
21
+ || typeof value.readiness !== 'boolean' || typeof value.active !== 'boolean')
22
+ throw Error('MANAGED_RECOVERY_INVALID_PROOF');
23
+ return value;
24
+ }
25
+ export function writeManagedRecovery(dir, value) {
26
+ replaceFileAtomically(managedRecoveryPath(dir), JSON.stringify(value) + '\n');
27
+ }
28
+ export function firstManagedSessionMayStart(dir) {
29
+ const proof = readManagedRecovery(dir);
30
+ return Boolean(proof?.session === 'pending' && proof.initial === 'pending' && !proof.readiness && !proof.active);
31
+ }
@@ -0,0 +1,2 @@
1
+ /** Prepare only the web configuration; App onboarding chooses agents and brains later. */
2
+ export declare function ensureMinimalSetup(configuration: string): Promise<void>;
@@ -0,0 +1,44 @@
1
+ import { existsSync, linkSync, mkdirSync, mkdtempSync, renameSync, rmSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { basename, join } from 'node:path';
3
+ import { withFileLock } from './atomic-file.js';
4
+ import { loadConfig, splitRootFor } from './config.js';
5
+ import { preflightInitPaths } from './init-wizard.js';
6
+ import { workspaceOwnerInvite } from './paths.js';
7
+ /** Prepare only the web configuration; App onboarding chooses agents and brains later. */
8
+ export async function ensureMinimalSetup(configuration) {
9
+ const initial = preflightInitPaths(configuration);
10
+ await withFileLock(join(initial.parent, `.${basename(initial.splitRoot)}.init.lock`), async () => {
11
+ const selected = preflightInitPaths(configuration);
12
+ if (selected.manifestExisted) {
13
+ loadConfig(selected.configPath, { yamlMode: 'strict', deferredOwnerInviteFile: workspaceOwnerInvite() });
14
+ return;
15
+ }
16
+ if (selected.rootExisted)
17
+ throw new Error('Fleet split configuration exists without its manifest; retain it and recover the existing setup before setting up a tunnel');
18
+ const stage = mkdtempSync(join(selected.parent, '.fleet-web-setup-'));
19
+ const manifest = join(stage, 'fleet.yaml');
20
+ const root = splitRootFor(manifest);
21
+ let publishedRoot = false;
22
+ try {
23
+ mkdirSync(join(root, 'agents'), { recursive: true, mode: 0o700 });
24
+ writeFileSync(manifest, 'api_version: ours.network/fleet/v2\n', { mode: 0o600, flag: 'wx' });
25
+ loadConfig(manifest, { yamlMode: 'strict' });
26
+ if (existsSync(selected.splitRoot) || existsSync(selected.configPath))
27
+ throw new Error('Fleet setup targets changed; refusing replacement');
28
+ renameSync(root, selected.splitRoot);
29
+ publishedRoot = true;
30
+ // Same-filesystem link publishes without replacing an unexpected manifest.
31
+ linkSync(manifest, selected.configPath);
32
+ unlinkSync(manifest);
33
+ loadConfig(selected.configPath, { yamlMode: 'strict' });
34
+ }
35
+ catch (cause) {
36
+ if (publishedRoot)
37
+ throw new Error('Minimal Fleet setup stopped after publishing its empty split directory; existing files were retained for recovery', { cause });
38
+ throw cause;
39
+ }
40
+ finally {
41
+ rmSync(stage, { recursive: true, force: true });
42
+ }
43
+ });
44
+ }
package/dist/monitor.d.ts CHANGED
@@ -28,6 +28,10 @@ export type FetchLike = (url: string, init?: {
28
28
  signal?: AbortSignal;
29
29
  }) => Promise<FetchResponse>;
30
30
  export interface MonitorPageClient {
31
+ /** Body-free snapshot; never consumes messages or changes read status. */
32
+ unread(): Promise<{
33
+ identities: Array<Record<string, unknown>>;
34
+ }>;
31
35
  readNotificationPage(identity: string, options?: {
32
36
  since?: number | 'tip';
33
37
  signal?: AbortSignal;
@@ -88,33 +92,6 @@ export interface MonitorDeps {
88
92
  * turns they trigger keep dying.
89
93
  */
90
94
  export type StatusCause = 'connectivity' | 'delivery' | 'modal' | 'offline' | 'turns-failing' | 'safe-boundary' | 'auth';
91
- /** Best-effort daemon config (issue #17): the fields the MCP client reads. */
92
- interface DaemonConfig {
93
- apiToken?: string;
94
- port?: number;
95
- stateDir?: string;
96
- }
97
- /**
98
- * Read the daemon config the way the MCP client does — best-effort. Any missing,
99
- * malformed, or unreadable config yields `{}` so token resolution falls through
100
- * (issue #17). Only the well-typed fields we consume are surfaced.
101
- */
102
- export declare function readDaemonConfig(env: NodeJS.ProcessEnv): DaemonConfig;
103
- /**
104
- * Resolve the daemon API token exactly like the MCP client (issue #17), a 3-step
105
- * chain: `OURS_API_TOKEN` (trimmed) → config `apiToken` (trimmed) → the 0600 owner
106
- * token at `<stateDir>/daemon-token`. Never generates a token; a failed read of
107
- * any source (missing/unreadable) silently falls through to the next.
108
- */
109
- export declare function resolveApiToken(env: NodeJS.ProcessEnv, file?: DaemonConfig): string | undefined;
110
- export interface DaemonEndpoint {
111
- origin: string;
112
- port: number;
113
- configPath: string;
114
- stateDir: string;
115
- url(name: string): string;
116
- headers: Record<string, string>;
117
- }
118
95
  export type IdentityPresence = {
119
96
  state: 'present';
120
97
  temporary: boolean;
@@ -125,16 +102,12 @@ export type IdentityPresence = {
125
102
  state: 'unknown';
126
103
  detail: string;
127
104
  };
128
- /** Resolve the daemon endpoint + auth header from env → config → defaults. */
129
- export declare function resolveEndpoint(env: NodeJS.ProcessEnv, includeToken?: boolean): DaemonEndpoint;
130
105
  /**
131
106
  * Ask the daemon's authoritative identity index. The notifications endpoint is
132
107
  * intentionally unsuitable for lifecycle: it serves an empty 200 page for a
133
108
  * valid but missing identity, which made a closed temp identity look healthy.
134
109
  */
135
110
  export declare function probeIdentityPresence(name: string, fetch: FetchLike, env: NodeJS.ProcessEnv, deps?: IdentityProbeDeps): Promise<IdentityPresence>;
136
- /** Actionable, secret-free description of every token source for this profile. */
137
- export declare function authResolutionHint(ep: DaemonEndpoint): string;
138
111
  /** Keep only the events whose type the role asked to wake on. */
139
112
  export declare function filterEvents(events: NotifyEvent[], wakeSources: string[]): NotifyEvent[];
140
113
  /**
@@ -196,8 +169,7 @@ export declare class Monitor {
196
169
  private readonly identity;
197
170
  private readonly cfg;
198
171
  private readonly deps;
199
- private readonly ep?;
200
- private readonly profile?;
172
+ private readonly profile;
201
173
  private readonly profileKey;
202
174
  private readonly monitorLeaseToken;
203
175
  private profileClientPromise?;
@@ -211,6 +183,7 @@ export declare class Monitor {
211
183
  private stopped;
212
184
  private bootDeadline;
213
185
  private currentAbort;
186
+ private initialBacklogPending;
214
187
  private apiErrorStreak;
215
188
  private readonly turnFailThreshold;
216
189
  /** Active degradations, keyed by cause. Empty means armed. */
@@ -230,6 +203,7 @@ export declare class Monitor {
230
203
  /** Gather stragglers arriving within batch_ms so a burst lands as one line. */
231
204
  private coalesce;
232
205
  private deliver;
206
+ private deliverLine;
233
207
  /** Update the consecutive-API-error streak and derive `.monitor-status` from it. */
234
208
  private recordTurn;
235
209
  /**
@@ -242,6 +216,7 @@ export declare class Monitor {
242
216
  */
243
217
  private doFetch;
244
218
  private profileClient;
219
+ private readInitialUnread;
245
220
  private disposeProfileClient;
246
221
  private advance;
247
222
  private persistCursor;
@@ -263,4 +238,3 @@ export declare class Monitor {
263
238
  private writeStatus;
264
239
  }
265
240
  export declare function createMonitor(o: MonitorOpts): Monitor;
266
- export {};
package/dist/monitor.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
2
  import { randomUUID } from 'node:crypto';
3
- import { homedir } from 'node:os';
4
3
  import { join } from 'node:path';
5
4
  import { attachOursClient } from '@ours.network/sdk/client';
6
5
  import { clientProfileKey, readClientProfile, } from './client-profile.js';
@@ -42,124 +41,28 @@ const TURN_OBSERVE_INTERVAL_MS = 1_500;
42
41
  const DEFAULT_TURN_FAIL_THRESHOLD = 3; // fallback when the resolved config omits it
43
42
  class AuthError extends Error {
44
43
  }
45
- /** Path to the daemon config the MCP client uses: OURS_CONFIG ?? real ~/.ours/config.json. */
46
- const daemonConfigPath = (env) => env.OURS_CONFIG ?? join(homedir(), '.ours', 'config.json');
47
- /** Preserve the daemon's legacy env integer semantics: parseInt, invalid → absent. */
48
- function envInt(env, name) {
49
- const raw = env[name];
50
- if (raw === undefined)
51
- return undefined;
52
- const n = parseInt(raw, 10);
53
- return Number.isNaN(n) ? undefined : n;
54
- }
55
- /**
56
- * Read the daemon config the way the MCP client does — best-effort. Any missing,
57
- * malformed, or unreadable config yields `{}` so token resolution falls through
58
- * (issue #17). Only the well-typed fields we consume are surfaced.
59
- */
60
- export function readDaemonConfig(env) {
61
- try {
62
- const p = JSON.parse(readFileSync(daemonConfigPath(env), 'utf8'));
63
- const o = {};
64
- if (typeof p.apiToken === 'string' && p.apiToken.trim())
65
- o.apiToken = p.apiToken.trim();
66
- if (typeof p.port === 'number' && Number.isFinite(p.port))
67
- o.port = p.port;
68
- if (typeof p.stateDir === 'string')
69
- o.stateDir = p.stateDir;
70
- return o;
71
- }
72
- catch {
73
- return {};
74
- }
75
- }
76
- /**
77
- * Resolve the daemon API token exactly like the MCP client (issue #17), a 3-step
78
- * chain: `OURS_API_TOKEN` (trimmed) → config `apiToken` (trimmed) → the 0600 owner
79
- * token at `<stateDir>/daemon-token`. Never generates a token; a failed read of
80
- * any source (missing/unreadable) silently falls through to the next.
81
- */
82
- export function resolveApiToken(env, file = readDaemonConfig(env)) {
83
- const e = env.OURS_API_TOKEN?.trim();
84
- if (e)
85
- return e;
86
- if (file.apiToken)
87
- return file.apiToken;
88
- const sd = env.OURS_STATE_DIR ?? file.stateDir ?? join(homedir(), '.ours');
89
- try {
90
- const t = readFileSync(join(sd, 'daemon-token'), 'utf8').trim();
91
- if (t)
92
- return t;
93
- }
94
- catch { /* missing/unreadable (e.g. cross-user 0600) → fall through */ }
95
- return undefined;
96
- }
97
- /** Resolve the daemon endpoint + auth header from env → config → defaults. */
98
- export function resolveEndpoint(env, includeToken = true) {
99
- const file = readDaemonConfig(env);
100
- const port = envInt(env, 'OURS_PORT') ?? file.port ?? DEFAULT_PORT;
101
- const configPath = daemonConfigPath(env);
102
- const stateDir = env.OURS_STATE_DIR ?? file.stateDir ?? join(homedir(), '.ours');
103
- const token = includeToken ? resolveApiToken(env, file) : undefined;
104
- const origin = `http://127.0.0.1:${port}`;
105
- return {
106
- origin,
107
- port,
108
- configPath,
109
- stateDir,
110
- url: (name) => `${origin}/identities/${encodeURIComponent(name)}/notifications`,
111
- headers: token ? { 'x-ours-api-token': token } : {},
112
- };
113
- }
114
44
  /**
115
45
  * Ask the daemon's authoritative identity index. The notifications endpoint is
116
46
  * intentionally unsuitable for lifecycle: it serves an empty 200 page for a
117
47
  * valid but missing identity, which made a closed temp identity look healthy.
118
48
  */
119
49
  export async function probeIdentityPresence(name, fetch, env, deps = {}) {
120
- const profile = readClientProfile(env);
121
- if (profile) {
122
- let client;
123
- try {
124
- client = await (deps.attachClient?.({
125
- endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
126
- credentialPath: profile.credentialPath,
127
- sessionMode: 'external', leaseToken: randomUUID(), env: {},
128
- }) ?? attachOursClient({
129
- endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
130
- credentialPath: profile.credentialPath,
131
- sessionMode: 'external', leaseToken: randomUUID(), env: {},
132
- }));
133
- return classifyIdentityPresence(name, await client.identities());
134
- }
135
- catch {
136
- return { state: 'unknown', detail: 'selected identity index is unavailable' };
137
- }
138
- finally {
139
- await client?.close().catch(() => undefined);
140
- }
141
- }
142
- const ep = resolveEndpoint(env);
143
- let response;
50
+ let client;
144
51
  try {
145
- response = await fetch(`${ep.origin}/identities`, { headers: ep.headers });
146
- }
147
- catch (error) {
148
- return { state: 'unknown', detail: `identity index unreachable (${msg(error)})` };
149
- }
150
- if (!response.ok)
151
- return {
152
- state: 'unknown',
153
- detail: response.status === 401
154
- ? `daemon rejected the API token (401) — ${authResolutionHint(ep)}`
155
- : `identity index returned HTTP ${response.status}`,
52
+ const profile = readClientProfile(env);
53
+ const options = {
54
+ endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
55
+ credentialPath: profile.credentialPath,
56
+ sessionMode: 'external', leaseToken: randomUUID(), env: {},
156
57
  };
157
- try {
158
- const body = await response.json();
159
- return classifyIdentityPresence(name, body.identities);
58
+ client = await (deps.attachClient?.(options) ?? attachOursClient(options));
59
+ return classifyIdentityPresence(name, await client.identities());
160
60
  }
161
- catch (error) {
162
- return { state: 'unknown', detail: `identity index response is unreadable (${msg(error)})` };
61
+ catch {
62
+ return { state: 'unknown', detail: 'gateway identity index unavailable; check the shared client profile and issued credential' };
63
+ }
64
+ finally {
65
+ await client?.close().catch(() => undefined);
163
66
  }
164
67
  }
165
68
  function classifyIdentityPresence(name, identities) {
@@ -186,12 +89,6 @@ function classifyIdentityPresence(name, identities) {
186
89
  stale: found.stale === true,
187
90
  };
188
91
  }
189
- /** Actionable, secret-free description of every token source for this profile. */
190
- export function authResolutionHint(ep) {
191
- const tokenPath = join(ep.stateDir, 'daemon-token');
192
- return `set OURS_API_TOKEN, set apiToken in ${JSON.stringify(ep.configPath)}, or ensure ` +
193
- `${JSON.stringify(tokenPath)} is readable by the fleet supervisor`;
194
- }
195
92
  /** Keep only the events whose type the role asked to wake on. */
196
93
  export function filterEvents(events, wakeSources) {
197
94
  const set = new Set(wakeSources);
@@ -414,7 +311,6 @@ export class Monitor {
414
311
  identity;
415
312
  cfg;
416
313
  deps;
417
- ep;
418
314
  profile;
419
315
  profileKey;
420
316
  monitorLeaseToken = `ours-fleet-monitor-${process.pid}-${randomUUID()}`;
@@ -429,6 +325,7 @@ export class Monitor {
429
325
  stopped = false;
430
326
  bootDeadline = 0;
431
327
  currentAbort = null;
328
+ initialBacklogPending = true;
432
329
  // Refusal-wedge detector (issue #19): consecutive delivered wakes whose turn
433
330
  // ended in an API error with no completed turn in between.
434
331
  apiErrorStreak = 0;
@@ -441,8 +338,7 @@ export class Monitor {
441
338
  this.cfg = o.cfg;
442
339
  this.deps = o.deps;
443
340
  this.profile = readClientProfile(o.deps.env);
444
- this.ep = this.profile ? undefined : resolveEndpoint(o.deps.env);
445
- this.profileKey = this.profile ? clientProfileKey(this.profile) : this.ep.origin;
341
+ this.profileKey = clientProfileKey(this.profile);
446
342
  this.statusPath = join(o.agentDir, '.monitor-status');
447
343
  this.cursorPath = join(o.agentDir, '.notify-cursor');
448
344
  this.statePath = join(o.agentDir, '.monitor-state.json');
@@ -470,14 +366,8 @@ export class Monitor {
470
366
  }
471
367
  catch (e) {
472
368
  if (e instanceof AuthError) {
473
- if (this.profile) {
474
- this.cursor = null;
475
- this.degrade('auth', e.message);
476
- }
477
- else {
478
- this.fatal = true;
479
- this.degrade('auth', e.message, 'failed');
480
- }
369
+ this.cursor = null;
370
+ this.degrade('auth', e.message);
481
371
  }
482
372
  else {
483
373
  this.cursor = null;
@@ -500,6 +390,41 @@ export class Monitor {
500
390
  this.degrade('offline', 'session offline');
501
391
  return;
502
392
  }
393
+ // The native SessionStart hook is disabled for managed sessions. Check
394
+ // existing unread work AFTER the ready turn, without a model inbox ritual
395
+ // or touching read status. Keep retrying a failed probe/delivery before
396
+ // committing stream cursors, including on supervisor restarts.
397
+ if (this.initialBacklogPending) {
398
+ try {
399
+ const body = await this.readInitialUnread();
400
+ if (!Array.isArray(body.identities))
401
+ throw new Error('unread summary is malformed');
402
+ const row = body.identities.find(row => row.name === this.identity);
403
+ if (row && (!Number.isSafeInteger(row.count) || Number(row.count) < 0
404
+ || !Number.isSafeInteger(row.files) || Number(row.files) < 0))
405
+ throw new Error('unread identity summary is malformed');
406
+ const messages = this.cfg.wake_sources.includes('message_received') ? Number(row?.count ?? 0) : 0;
407
+ const files = this.cfg.wake_sources.includes('file_received') ? Number(row?.files ?? 0) : 0;
408
+ if ((messages || files) && !await this.deliverLine(`${PREFIX} unread backlog: ${messages} messages, ${files} files — run get_messages; drain remaining unread batches and authorize files before retrieving them`)) {
409
+ await this.deps.sleep(BACKOFF_MAX_MS);
410
+ continue;
411
+ }
412
+ this.initialBacklogPending = false;
413
+ this.recover('connectivity', 'auth');
414
+ }
415
+ catch (e) {
416
+ if (this.stopped)
417
+ return;
418
+ if (e instanceof AuthError)
419
+ this.degrade('auth', e.message);
420
+ else
421
+ this.degrade('connectivity', 'initial unread check unavailable; retrying');
422
+ await this.deps.sleep(BACKOFF_MAX_MS);
423
+ continue;
424
+ }
425
+ }
426
+ if (this.stopped)
427
+ return;
503
428
  let body;
504
429
  try {
505
430
  body = await this.doFetch(String(this.cursor ?? 0), LONGPOLL_STALL_MS, 'stall');
@@ -510,11 +435,6 @@ export class Monitor {
510
435
  catch (e) {
511
436
  if (this.stopped)
512
437
  return;
513
- if (e instanceof AuthError && !this.profile) {
514
- this.fatal = true;
515
- this.degrade('auth', e.message, 'failed');
516
- return;
517
- }
518
438
  backoff = Math.min(backoff + BACKOFF_STEP_MS, BACKOFF_MAX_MS);
519
439
  if (e instanceof AuthError)
520
440
  this.degrade('auth', e.message);
@@ -579,7 +499,9 @@ export class Monitor {
579
499
  catch { /* no stragglers / abort — deliver what we have */ }
580
500
  }
581
501
  async deliver(pid, batch) {
582
- const line = formatNotificationLine(batch);
502
+ return this.deliverLine(formatNotificationLine(batch));
503
+ }
504
+ async deliverLine(line) {
583
505
  if (!this.deps.delivery) {
584
506
  this.degrade('delivery', 'structured agent-session delivery is unavailable');
585
507
  return false;
@@ -630,23 +552,19 @@ export class Monitor {
630
552
  this.currentAbort = ctrl;
631
553
  let timedOut = false;
632
554
  const timer = this.deps.timers.set(() => { timedOut = true; ctrl.abort(); }, timeoutMs);
633
- let resp;
634
555
  try {
635
- if (this.profile) {
636
- const client = await this.profileClient();
637
- const page = await client.readNotificationPage(this.identity, {
638
- since: since === 'tip' ? 'tip' : Number.parseInt(since, 10),
639
- signal: ctrl.signal,
640
- requestTimeoutMs: timeoutMs,
641
- });
642
- return { cursor: page.cursor, events: page.events };
643
- }
644
- resp = await this.deps.fetch(`${this.ep.url(this.identity)}?since=${since}`, { headers: this.ep.headers, signal: ctrl.signal });
556
+ const client = await this.profileClient();
557
+ const page = await client.readNotificationPage(this.identity, {
558
+ since: since === 'tip' ? 'tip' : Number.parseInt(since, 10),
559
+ signal: ctrl.signal,
560
+ requestTimeoutMs: timeoutMs,
561
+ });
562
+ return { cursor: page.cursor, events: page.events };
645
563
  }
646
564
  catch (error) {
647
565
  if (timedOut && timeoutKind === 'stall')
648
566
  throw new Error(`notification stream stalled for ${Math.round(timeoutMs / 1000)}s`);
649
- if (this.profile && /(?:HTTP\s*401|unauthori[sz]ed|API token)/i.test(msg(error)))
567
+ if (/(?:HTTP\s*401|unauthori[sz]ed|API token)/i.test(msg(error)))
650
568
  throw new AuthError(`daemon rejected the API token (401) — verify the credential file `
651
569
  + `${JSON.stringify(this.profile.credentialPath)} selected by `
652
570
  + `${JSON.stringify(this.profile.configPath)}`);
@@ -656,15 +574,8 @@ export class Monitor {
656
574
  this.deps.timers.clear(timer);
657
575
  this.currentAbort = null;
658
576
  }
659
- if (resp.status === 401)
660
- throw new AuthError(`daemon rejected the API token (401) — ${authResolutionHint(this.ep)}`);
661
- if (!resp.ok)
662
- throw new Error(`daemon returned HTTP ${resp.status}`);
663
- return resp.json();
664
577
  }
665
578
  profileClient() {
666
- if (!this.profile)
667
- throw new Error('explicit client profile is not selected');
668
579
  if (!this.profileClientPromise) {
669
580
  const { endpoint, expectedInstanceId, credentialPath } = this.profile;
670
581
  const options = {
@@ -678,6 +589,32 @@ export class Monitor {
678
589
  }
679
590
  return this.profileClientPromise;
680
591
  }
592
+ async readInitialUnread() {
593
+ const ctrl = new AbortController();
594
+ this.currentAbort = ctrl;
595
+ const timer = this.deps.timers.set(() => ctrl.abort(), 5_000);
596
+ let client;
597
+ try {
598
+ const { endpoint, expectedInstanceId, credentialPath } = this.profile;
599
+ const options = {
600
+ endpoint, expectedInstanceId, credentialPath,
601
+ sessionMode: 'external', leaseToken: this.monitorLeaseToken, env: {},
602
+ requestSignal: ctrl.signal,
603
+ };
604
+ client = await (this.deps.attachClient?.(options) ?? attachOursClient(options));
605
+ return await client.unread();
606
+ }
607
+ catch (error) {
608
+ if (/(?:HTTP\s*401|unauthori[sz]ed|API token)/i.test(msg(error)))
609
+ throw new AuthError('daemon rejected the API token (401); initial unread check unavailable; retrying');
610
+ throw error;
611
+ }
612
+ finally {
613
+ this.deps.timers.clear(timer);
614
+ this.currentAbort = null;
615
+ await client?.close().catch(() => undefined);
616
+ }
617
+ }
681
618
  async disposeProfileClient() {
682
619
  const pending = this.profileClientPromise;
683
620
  this.profileClientPromise = undefined;
@@ -0,0 +1,19 @@
1
+ import { type ProducerConfig } from './outbox.js';
2
+ /** Read durable supervisor ledgers without restarting agents or attaching a
3
+ * conversation controller. Each tick reads at most 256 KiB per role, from its
4
+ * checkpoint; it never loads a complete transcript or requests model history. */
5
+ export declare class FleetNotificationProducer {
6
+ private readonly roots;
7
+ private readonly stateDir;
8
+ private readonly config;
9
+ private readonly warn;
10
+ private readonly queues;
11
+ private readonly timer;
12
+ private readonly existing;
13
+ private cleanup?;
14
+ constructor(roots: string[], stateDir: string, config: ProducerConfig, warn?: (line: string) => void);
15
+ private names;
16
+ poll(): void;
17
+ drain(): Promise<void>;
18
+ close(): Promise<void>;
19
+ }