@ours.network/fleet 1.2.0-nightly.7 → 1.2.0-nightly.71

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 (423) hide show
  1. package/README.md +279 -68
  2. package/dist/account-origin.d.ts +2 -0
  3. package/dist/account-origin.js +6 -0
  4. package/dist/agent-ours/bridge.js +26 -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 +19 -0
  11. package/dist/agent-ours/mcp-endpoint.js +98 -25
  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 +24 -1
  15. package/dist/agent-ours/service.js +97 -13
  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 +34 -0
  19. package/dist/application/conversation-history.js +280 -0
  20. package/dist/application/conversation-role-observer.d.ts +62 -0
  21. package/dist/application/conversation-role-observer.js +206 -0
  22. package/dist/application/fleet-query-service.d.ts +1 -1
  23. package/dist/application/fleet-query-service.js +3 -3
  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/resource-observer.d.ts +40 -0
  30. package/dist/application/resource-observer.js +278 -0
  31. package/dist/application/role-creation-service.js +3 -2
  32. package/dist/application/role-removal-service.js +17 -3
  33. package/dist/application/role-repository.d.ts +1 -1
  34. package/dist/application/role-repository.js +30 -7
  35. package/dist/application/room-layout-definitions.d.ts +45 -0
  36. package/dist/application/room-layout-definitions.js +130 -0
  37. package/dist/application/session-control.d.ts +61 -17
  38. package/dist/application/session-control.js +207 -23
  39. package/dist/application/supervisor-ours-tools.js +5 -11
  40. package/dist/application/task-layouts.d.ts +91 -0
  41. package/dist/application/task-layouts.js +261 -0
  42. package/dist/application/task-room-service.d.ts +101 -3
  43. package/dist/application/task-room-service.js +286 -33
  44. package/dist/application/types.d.ts +2 -0
  45. package/dist/atomic-file.d.ts +34 -1
  46. package/dist/atomic-file.js +161 -18
  47. package/dist/briefing.d.ts +3 -1
  48. package/dist/briefing.js +97 -31
  49. package/dist/build-info.json +9 -4
  50. package/dist/capabilities.d.ts +9 -1
  51. package/dist/capabilities.js +13 -0
  52. package/dist/cli.js +400 -37
  53. package/dist/client-profile.d.ts +5 -17
  54. package/dist/client-profile.js +4 -127
  55. package/dist/config.d.ts +45 -0
  56. package/dist/config.js +57 -6
  57. package/dist/creation.d.ts +1 -1
  58. package/dist/creation.js +4 -4
  59. package/dist/daemon-recovery.d.ts +14 -9
  60. package/dist/daemon-recovery.js +124 -115
  61. package/dist/docs.d.ts +1 -1
  62. package/dist/docs.js +207 -19
  63. package/dist/doctor.d.ts +4 -1
  64. package/dist/doctor.js +75 -60
  65. package/dist/erased-resources.d.ts +9 -0
  66. package/dist/erased-resources.js +87 -0
  67. package/dist/file-delivery/reader.d.ts +15 -0
  68. package/dist/file-delivery/reader.js +63 -0
  69. package/dist/file-delivery/store.d.ts +15 -0
  70. package/dist/file-delivery/store.js +124 -0
  71. package/dist/file-delivery/types.d.ts +19 -0
  72. package/dist/file-delivery/types.js +1 -0
  73. package/dist/fleet-command-audit.d.ts +7 -0
  74. package/dist/fleet-command-audit.js +24 -8
  75. package/dist/harness/agent-session.d.ts +4 -0
  76. package/dist/harness/claude-code-session.js +1 -1
  77. package/dist/harness/claude-code.js +21 -11
  78. package/dist/harness/claude-runtime.d.ts +12 -0
  79. package/dist/harness/claude-runtime.js +43 -0
  80. package/dist/harness/codex-app-server-proxy.d.ts +4 -1
  81. package/dist/harness/codex-app-server-proxy.js +41 -5
  82. package/dist/harness/codex-reasoning.d.ts +5 -0
  83. package/dist/harness/codex-reasoning.js +12 -0
  84. package/dist/harness/codex-runtime.d.ts +11 -1
  85. package/dist/harness/codex-runtime.js +31 -4
  86. package/dist/harness/codex-session.js +2 -2
  87. package/dist/harness/codex.js +24 -12
  88. package/dist/init-wizard.d.ts +2 -0
  89. package/dist/init-wizard.js +38 -19
  90. package/dist/isolation/policy.js +6 -1
  91. package/dist/isolation/types.d.ts +5 -0
  92. package/dist/managed-cli.d.ts +253 -0
  93. package/dist/managed-cli.js +923 -0
  94. package/dist/managed-recovery.d.ts +13 -0
  95. package/dist/managed-recovery.js +31 -0
  96. package/dist/minimal-setup.d.ts +2 -0
  97. package/dist/minimal-setup.js +44 -0
  98. package/dist/monitor.d.ts +9 -34
  99. package/dist/monitor.js +90 -153
  100. package/dist/notifications/fleet-producer.d.ts +22 -0
  101. package/dist/notifications/fleet-producer.js +237 -0
  102. package/dist/notifications/outbox.d.ts +46 -0
  103. package/dist/notifications/outbox.js +158 -0
  104. package/dist/notifications/target-cleanup.d.ts +11 -0
  105. package/dist/notifications/target-cleanup.js +63 -0
  106. package/dist/notifications/task-producer.d.ts +20 -0
  107. package/dist/notifications/task-producer.js +100 -0
  108. package/dist/ops.d.ts +2 -0
  109. package/dist/ops.js +20 -3
  110. package/dist/owner-channel/channel.js +17 -6
  111. package/dist/owner-channel/commands.d.ts +4 -0
  112. package/dist/owner-channel/commands.js +8 -0
  113. package/dist/owner-channel/lifecycle-outbox.js +4 -3
  114. package/dist/owner-channel/ours-client.js +2 -17
  115. package/dist/paths.d.ts +2 -0
  116. package/dist/paths.js +2 -0
  117. package/dist/preset-migration.js +43 -0
  118. package/dist/process-incarnation.d.ts +23 -0
  119. package/dist/process-incarnation.js +42 -0
  120. package/dist/reminders/manager.d.ts +75 -0
  121. package/dist/reminders/manager.js +278 -0
  122. package/dist/reminders/runtime.d.ts +27 -0
  123. package/dist/reminders/runtime.js +32 -0
  124. package/dist/reminders/schedule.d.ts +37 -0
  125. package/dist/reminders/schedule.js +104 -0
  126. package/dist/reminders/store.d.ts +341 -0
  127. package/dist/reminders/store.js +762 -0
  128. package/dist/reminders/tools.d.ts +20 -0
  129. package/dist/reminders/tools.js +114 -0
  130. package/dist/resolved-plan.js +1 -0
  131. package/dist/rooms-tasks/add-member.d.ts +48 -0
  132. package/dist/rooms-tasks/add-member.js +84 -0
  133. package/dist/rooms-tasks/archived-absence.d.ts +8 -0
  134. package/dist/rooms-tasks/archived-absence.js +48 -0
  135. package/dist/rooms-tasks/cli.js +65 -5
  136. package/dist/rooms-tasks/close.d.ts +6 -2
  137. package/dist/rooms-tasks/close.js +246 -37
  138. package/dist/rooms-tasks/config.d.ts +1 -1
  139. package/dist/rooms-tasks/config.js +11 -4
  140. package/dist/rooms-tasks/cowork-adapter.d.ts +12 -5
  141. package/dist/rooms-tasks/cowork-adapter.js +15 -121
  142. package/dist/rooms-tasks/cowork-http.js +56 -6
  143. package/dist/rooms-tasks/deletion.d.ts +1 -1
  144. package/dist/rooms-tasks/deletion.js +84 -5
  145. package/dist/rooms-tasks/erasure.d.ts +6 -0
  146. package/dist/rooms-tasks/erasure.js +173 -0
  147. package/dist/rooms-tasks/external-worker.d.ts +1 -1
  148. package/dist/rooms-tasks/external-worker.js +3 -4
  149. package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
  150. package/dist/rooms-tasks/layout-binding-client.js +56 -0
  151. package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
  152. package/dist/rooms-tasks/layout-binding-grants.js +128 -0
  153. package/dist/rooms-tasks/layout-cli.d.ts +4 -0
  154. package/dist/rooms-tasks/layout-cli.js +107 -0
  155. package/dist/rooms-tasks/layout-config.d.ts +11 -0
  156. package/dist/rooms-tasks/layout-config.js +89 -0
  157. package/dist/rooms-tasks/layout-control.d.ts +21 -0
  158. package/dist/rooms-tasks/layout-control.js +52 -0
  159. package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
  160. package/dist/rooms-tasks/layout-member-retirement.js +90 -0
  161. package/dist/rooms-tasks/layout-service.d.ts +43 -0
  162. package/dist/rooms-tasks/layout-service.js +203 -0
  163. package/dist/rooms-tasks/layout.d.ts +121 -0
  164. package/dist/rooms-tasks/layout.js +286 -0
  165. package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
  166. package/dist/rooms-tasks/legacy-task-member.js +116 -0
  167. package/dist/rooms-tasks/live-readiness.d.ts +18 -0
  168. package/dist/rooms-tasks/live-readiness.js +85 -0
  169. package/dist/rooms-tasks/member-ownership.d.ts +5 -0
  170. package/dist/rooms-tasks/member-ownership.js +40 -0
  171. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  172. package/dist/rooms-tasks/member-startup.js +2 -0
  173. package/dist/rooms-tasks/provision.d.ts +3 -0
  174. package/dist/rooms-tasks/provision.js +101 -49
  175. package/dist/rooms-tasks/recovery.d.ts +19 -0
  176. package/dist/rooms-tasks/recovery.js +110 -0
  177. package/dist/rooms-tasks/room-state.d.ts +4 -2
  178. package/dist/rooms-tasks/room-state.js +47 -8
  179. package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
  180. package/dist/rooms-tasks/task-service-retirement.js +21 -0
  181. package/dist/rooms-tasks/task-state.d.ts +52 -8
  182. package/dist/rooms-tasks/task-state.js +251 -26
  183. package/dist/rooms-tasks/types.d.ts +40 -0
  184. package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
  185. package/dist/rooms-tasks/workspace-artifacts.js +93 -0
  186. package/dist/rooms-tasks/workspace.d.ts +35 -0
  187. package/dist/rooms-tasks/workspace.js +325 -0
  188. package/dist/runner.d.ts +33 -4
  189. package/dist/runner.js +410 -62
  190. package/dist/session/acp.d.ts +75 -2
  191. package/dist/session/acp.js +345 -82
  192. package/dist/session/arbiter.d.ts +98 -0
  193. package/dist/session/arbiter.js +272 -3
  194. package/dist/session/codex-app-server.d.ts +45 -1
  195. package/dist/session/codex-app-server.js +225 -32
  196. package/dist/session/control.d.ts +17 -3
  197. package/dist/session/control.js +213 -23
  198. package/dist/session/conversation-normalizer.d.ts +2 -1
  199. package/dist/session/conversation-normalizer.js +1 -1
  200. package/dist/session/conversation-observation.d.ts +25 -0
  201. package/dist/session/conversation-observation.js +100 -0
  202. package/dist/session/conversation-replay.d.ts +50 -0
  203. package/dist/session/conversation-replay.js +203 -0
  204. package/dist/session/conversation-store.d.ts +15 -1
  205. package/dist/session/conversation-store.js +206 -26
  206. package/dist/session/conversation-types.d.ts +57 -4
  207. package/dist/session/prompt-batch.d.ts +79 -0
  208. package/dist/session/prompt-batch.js +120 -0
  209. package/dist/session/task-notice.d.ts +14 -0
  210. package/dist/session/task-notice.js +13 -0
  211. package/dist/session/types.d.ts +42 -1
  212. package/dist/setup-tunnel-preflight.d.ts +34 -0
  213. package/dist/setup-tunnel-preflight.js +62 -0
  214. package/dist/socket-path.d.ts +2 -0
  215. package/dist/socket-path.js +22 -0
  216. package/dist/spawn.d.ts +5 -1
  217. package/dist/spawn.js +40 -4
  218. package/dist/startup-prompt.d.ts +15 -0
  219. package/dist/startup-prompt.js +71 -0
  220. package/dist/startup-readiness.d.ts +32 -0
  221. package/dist/startup-readiness.js +101 -0
  222. package/dist/startup-telemetry.d.ts +16 -0
  223. package/dist/startup-telemetry.js +46 -0
  224. package/dist/subscriptions/cli.d.ts +91 -0
  225. package/dist/subscriptions/cli.js +223 -0
  226. package/dist/subscriptions/launch.d.ts +37 -0
  227. package/dist/subscriptions/launch.js +93 -0
  228. package/dist/subscriptions/login.d.ts +77 -0
  229. package/dist/subscriptions/login.js +215 -0
  230. package/dist/subscriptions/observed.d.ts +7 -0
  231. package/dist/subscriptions/observed.js +44 -0
  232. package/dist/subscriptions/probe.d.ts +10 -0
  233. package/dist/subscriptions/probe.js +73 -0
  234. package/dist/subscriptions/service.d.ts +102 -0
  235. package/dist/subscriptions/service.js +364 -0
  236. package/dist/subscriptions/store.d.ts +71 -0
  237. package/dist/subscriptions/store.js +143 -0
  238. package/dist/supervisor/adoption.d.ts +8 -0
  239. package/dist/supervisor/adoption.js +78 -0
  240. package/dist/supervisor/catalog.d.ts +62 -0
  241. package/dist/supervisor/catalog.js +254 -0
  242. package/dist/supervisor/fleet.d.ts +8 -0
  243. package/dist/supervisor/fleet.js +89 -0
  244. package/dist/supervisor/index.js +3 -6
  245. package/dist/supervisor/launchd.d.ts +1 -1
  246. package/dist/supervisor/launchd.js +26 -13
  247. package/dist/supervisor/legacy.d.ts +35 -0
  248. package/dist/supervisor/legacy.js +524 -0
  249. package/dist/supervisor/manager.d.ts +15 -0
  250. package/dist/supervisor/manager.js +270 -0
  251. package/dist/supervisor/registration-refresh.d.ts +45 -0
  252. package/dist/supervisor/registration-refresh.js +266 -0
  253. package/dist/supervisor/scope.d.ts +4 -0
  254. package/dist/supervisor/scope.js +10 -0
  255. package/dist/supervisor/systemd.d.ts +2 -2
  256. package/dist/supervisor/systemd.js +19 -33
  257. package/dist/task-supervision.d.ts +9 -0
  258. package/dist/task-supervision.js +145 -0
  259. package/dist/temp-idle.d.ts +17 -0
  260. package/dist/temp-idle.js +42 -0
  261. package/dist/temp-lifecycle.d.ts +23 -8
  262. package/dist/temp-lifecycle.js +123 -66
  263. package/dist/temp-supervisor-recovery.d.ts +1 -1
  264. package/dist/temp-supervisor-recovery.js +2 -2
  265. package/dist/tunnel-setup-completion.d.ts +7 -0
  266. package/dist/tunnel-setup-completion.js +13 -0
  267. package/dist/tunnel-setup-input.d.ts +19 -0
  268. package/dist/tunnel-setup-input.js +124 -0
  269. package/dist/watchdog/query.d.ts +3 -1
  270. package/dist/watchdog/query.js +2 -1
  271. package/dist/web/agent-attachments.d.ts +29 -0
  272. package/dist/web/agent-attachments.js +162 -0
  273. package/dist/web/auth.d.ts +65 -2
  274. package/dist/web/auth.js +201 -11
  275. package/dist/web/available-port.d.ts +2 -0
  276. package/dist/web/available-port.js +23 -0
  277. package/dist/web/control.d.ts +3 -3
  278. package/dist/web/control.js +10 -8
  279. package/dist/web/conversation-stream-codec.d.ts +23 -0
  280. package/dist/web/conversation-stream-codec.js +110 -0
  281. package/dist/web/conversation-stream.d.ts +25 -0
  282. package/dist/web/conversation-stream.js +231 -0
  283. package/dist/web/events.d.ts +2 -0
  284. package/dist/web/events.js +9 -0
  285. package/dist/web/fleet-config-service.d.ts +4 -1
  286. package/dist/web/fleet-config-service.js +46 -15
  287. package/dist/web/prefix-gateway.d.ts +32 -0
  288. package/dist/web/prefix-gateway.js +248 -0
  289. package/dist/web/resource-views.d.ts +124 -0
  290. package/dist/web/resource-views.js +424 -0
  291. package/dist/web/runtime.d.ts +3 -1
  292. package/dist/web/runtime.js +132 -34
  293. package/dist/web/server.d.ts +19 -0
  294. package/dist/web/server.js +802 -67
  295. package/dist/web/service.d.ts +11 -2
  296. package/dist/web/service.js +30 -4
  297. package/dist/web/workspace-devices.d.ts +107 -0
  298. package/dist/web/workspace-devices.js +277 -0
  299. package/dist/web/workspace-tunnel.d.ts +1 -0
  300. package/dist/web/workspace-tunnel.js +34 -0
  301. package/dist/workspace-enrollment.d.ts +83 -0
  302. package/dist/workspace-enrollment.js +580 -0
  303. package/dist/workspace-replacement.d.ts +66 -0
  304. package/dist/workspace-replacement.js +220 -0
  305. package/docs/acp-files.md +146 -0
  306. package/docs/conversation-stream.md +196 -0
  307. package/docs/fleet-migration.md +54 -0
  308. package/docs/live-voice.md +13 -0
  309. package/docs/room-layouts.md +227 -0
  310. package/docs/self-reminders.md +374 -0
  311. package/docs/task-workspaces.md +225 -0
  312. package/docs/validation/managed-cli-permissions.md +421 -0
  313. package/examples/room-layouts/fresh.yaml +27 -0
  314. package/examples/room-layouts/scoped.yaml +21 -0
  315. package/examples/room-layouts/shared.yaml +19 -0
  316. package/package.json +24 -20
  317. package/presets/README.md +78 -0
  318. package/presets/brain-catalog.json +8 -2
  319. package/presets/fleet/agent_templates/Critic.yaml +1 -1
  320. package/presets/fleet/agent_templates/Developer.yaml +1 -1
  321. package/presets/fleet/agent_templates/Engineer.yaml +5 -0
  322. package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -2
  323. package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
  324. package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
  325. package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
  326. package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
  327. package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
  328. package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
  329. package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
  330. package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
  331. package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
  332. package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
  333. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
  334. package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
  335. package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
  336. package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
  337. package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
  338. package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
  339. package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
  340. package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
  341. package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
  342. package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
  343. package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
  344. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
  345. package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
  346. package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
  347. package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
  348. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
  349. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
  350. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
  351. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
  352. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
  353. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
  354. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
  355. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
  356. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
  357. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
  358. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
  359. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
  360. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
  361. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
  362. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
  363. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
  364. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
  365. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
  366. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
  367. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
  368. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
  369. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
  370. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
  371. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
  372. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
  373. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
  374. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
  375. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
  376. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
  377. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
  378. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
  379. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
  380. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
  381. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
  382. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
  383. package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
  384. package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
  385. package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
  386. package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
  387. package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
  388. package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
  389. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
  390. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
  391. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
  392. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
  393. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
  394. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
  395. package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
  396. package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
  397. package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
  398. package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
  399. package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
  400. package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
  401. package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
  402. package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
  403. package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
  404. package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
  405. package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
  406. package/presets/fleet/roles/Coordinator.yaml +12 -11
  407. package/presets/fleet/roles/Critic.yaml +13 -0
  408. package/presets/fleet/roles/Developer.yaml +13 -0
  409. package/presets/fleet/roles/Engineer.yaml +53 -0
  410. package/presets/fleet/room_layouts/engineering.yaml +25 -0
  411. package/presets/fleet/room_layouts/pair.yaml +24 -0
  412. package/presets/fleet/room_layouts/single.yaml +17 -0
  413. package/presets/fleet/room_layouts/team.yaml +30 -0
  414. package/presets/fleet/room_templates/engineering.yaml +19 -0
  415. package/presets/manifest.json +2 -2
  416. package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
  417. package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
  418. package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
  419. package/dist/web-app/icons/ours-fleet.svg +0 -4
  420. package/dist/web-app/index.html +0 -17
  421. package/dist/web-app/manifest.webmanifest +0 -15
  422. package/dist/web-app/offline.html +0 -18
  423. package/dist/web-app/sw.js +0 -51
package/dist/ops.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { retireNotificationTarget } from './notifications/target-cleanup.js';
1
2
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync, unlinkSync, } from 'node:fs';
2
3
  import { join } from 'node:path';
3
4
  import { randomUUID, createHash } from 'node:crypto';
@@ -5,8 +6,9 @@ import { agentDir, watchdogsRoot } from './paths.js';
5
6
  import { findRole } from './config.js';
6
7
  import { getAdapter } from './harness/registry.js';
7
8
  import { generateBriefing } from './briefing.js';
8
- import { resetRestartLedger } from './runner.js';
9
- import { archiveTempState, stopTempSupervisor, tempSupervisorLiveness, } from './temp-lifecycle.js';
9
+ import { managedCliBriefing } from './managed-cli.js';
10
+ import { resetRestartLedger, loadTempRole } from './runner.js';
11
+ import { archiveTempState, stopTempSupervisor, tempSupervisorLiveness, readTempSupervisor, } from './temp-lifecycle.js';
10
12
  import { realExec } from './exec.js';
11
13
  import { daemonIdentityProvisioner, reconcilePermanentRoleIdentities, } from './creation.js';
12
14
  import { provesGeneratedAgentSource } from './generated-agent-source.js';
@@ -28,7 +30,7 @@ export function applyRole(role, opts = {}) {
28
30
  // brought up from so the supervised process can reload the SAME file instead of
29
31
  // silently falling back to the default ~/fleet.yaml. Temp roles snapshot their
30
32
  // whole resolved role into role.yaml instead and don't need this.
31
- if (!opts.temp)
33
+ if (!opts.temp || opts.configPath)
32
34
  writeFileSync(join(dir, '.config-path'), (opts.configPath ?? '') + '\n');
33
35
  writeFileSync(join(dir, '.identity'), role.identity + '\n');
34
36
  if (role.cwd)
@@ -43,6 +45,7 @@ export function applyRole(role, opts = {}) {
43
45
  routinesPath: join(dir, 'ROUTINES.md'), briefingBody,
44
46
  identityGuarantee: opts.identityGuarantee,
45
47
  temporaryIdentity: opts.temp === true,
48
+ managedCli: managedCliBriefing(role, opts.configPath, opts.temp === true),
46
49
  }));
47
50
  if (opts.fresh)
48
51
  for (const f of ['.booted', '.session-id', '.exit-status'])
@@ -220,8 +223,21 @@ export async function restartRoles(cfg, names, deps, mode, configPath) {
220
223
  : `↻ ${role.name} — restarted (resumes; briefing re-synced)`);
221
224
  }
222
225
  }
226
+ /** Read-only admission check shared by CLI removal and web preview, before any archive. */
227
+ export function assertStandaloneRoleRemoval(cfg, name) {
228
+ if (cfg.roles.some(role => role.name === name) || !/^[A-Za-z0-9_-]+$/.test(name))
229
+ return;
230
+ const dir = agentDir(name, true);
231
+ if (!existsSync(dir))
232
+ return;
233
+ const taskId = readTempSupervisor(dir)?.taskOwner?.taskId
234
+ ?? (existsSync(join(dir, 'role.yaml')) ? loadTempRole(name).roomMemberStartup?.task_id : undefined);
235
+ if (taskId)
236
+ throw Error(`TASK_MEMBER_IS_TASK_OWNED: ${name} belongs to task ${taskId}; use the owning task lifecycle; if its record is missing or corrupt, preserve evidence and restore the original records before retrying task delete`);
237
+ }
223
238
  /** Stop + forget a role: unit, state dir, and its fleet.d file when spawned. */
224
239
  export async function rmRole(cfg, name, deps) {
240
+ assertStandaloneRoleRemoval(cfg, name);
225
241
  const temporaryDir = /^[A-Za-z0-9_-]+$/.test(name) ? agentDir(name, true) : '';
226
242
  const configured = cfg.roles.find(role => role.name === name);
227
243
  if (!configured && temporaryDir && existsSync(temporaryDir)) {
@@ -255,6 +271,7 @@ export async function rmRole(cfg, name, deps) {
255
271
  rmSync(agentDir(name), { recursive: true, force: true });
256
272
  if (generatedSource && existsSync(role.sourceFile)) {
257
273
  unlinkSync(role.sourceFile);
274
+ await retireNotificationTarget(`/fleet/chats/agents/${encodeURIComponent(name)}`).catch(() => { });
258
275
  deps.log(`removed ${role.sourceFile}`);
259
276
  }
260
277
  deps.log(`removed '${name}' (its ours identity is left intact)`);
@@ -883,8 +883,15 @@ export class OwnerChannel {
883
883
  const recovered = [];
884
884
  for (const claim of this.messageRecovery.list()) {
885
885
  const item = await this.client.getHistoryItem(claim.wireId);
886
- if (!item)
887
- throw new Error(`journaled owner message ${claim.wireId} is missing from persistent history`);
886
+ if (!item) {
887
+ // The daemon has definitively lost this body. Retrying the claim would
888
+ // block every later owner message, including after a supervisor restart.
889
+ // Keep transient lookup errors retryable; only an explicit absence skips.
890
+ this.messageRecovery.pruneHandled(wireId => wireId === claim.wireId);
891
+ this.options.log(`[${this.options.role}] skipped journaled owner message ${claim.wireId} `
892
+ + `(seq=${claim.seq}): missing from persistent history`);
893
+ continue;
894
+ }
888
895
  recovered.push(this.historyMessage(item, claim));
889
896
  }
890
897
  const listed = await this.client.listIncomingMessages();
@@ -1391,6 +1398,7 @@ export class OwnerChannel {
1391
1398
  await this.fleetOps.provisionTask(task.task_id);
1392
1399
  return outcome;
1393
1400
  }),
1401
+ observeTaskReadiness: taskId => new TaskRoomApplicationService(this.options.configPath).observeTaskReadiness(taskId),
1394
1402
  taskProvisioningOutcome: taskId => new TaskRoomApplicationService(this.options.configPath).taskProvisioningOutcome(taskId),
1395
1403
  listTasks: filter => new TaskRoomApplicationService(this.options.configPath).listTasks(filter),
1396
1404
  groupedTasks: filter => new TaskRoomApplicationService(this.options.configPath).groupedTasks(filter),
@@ -1977,6 +1985,9 @@ export class OwnerChannel {
1977
1985
  const progressMs = this.options.config.progress_interval_ms;
1978
1986
  let lastSeq = activityCursor;
1979
1987
  let startedAt;
1988
+ // When one turn delivers several waiting prompts, its events carry the turn's
1989
+ // id, not this request's: follow the turn that actually carries this request.
1990
+ const inTurn = (turnId) => turnId === (this.options.session.sharedTurnId?.(queued.promptId) ?? queued.promptId);
1980
1991
  let phase = 'starting request';
1981
1992
  let timer;
1982
1993
  const flushCommentary = () => {
@@ -2033,7 +2044,7 @@ export class OwnerChannel {
2033
2044
  };
2034
2045
  const acceptCommentary = (event) => {
2035
2046
  if (!this.commentsEnabled
2036
- || active.commentaryDisabled || active.finalizing || event.turnId !== queued.promptId
2047
+ || active.commentaryDisabled || active.finalizing || !inTurn(event.turnId)
2037
2048
  || event.kind !== 'agent_text' || event.messagePhase !== 'commentary'
2038
2049
  || event.replayed || event.origin?.kind !== 'owner'
2039
2050
  || event.origin.requestId !== active.requestId
@@ -2074,7 +2085,7 @@ export class OwnerChannel {
2074
2085
  const reportProgress = () => {
2075
2086
  const events = this.options.session.eventsSince(lastSeq);
2076
2087
  lastSeq = Math.max(lastSeq, this.latestEventSeq(events));
2077
- const activity = events.filter(event => event.turnId === queued.promptId);
2088
+ const activity = events.filter(event => inTurn(event.turnId));
2078
2089
  if (!activity.length)
2079
2090
  return;
2080
2091
  startedAt ??= Date.parse(activity[0].at) || Date.now();
@@ -2099,10 +2110,10 @@ export class OwnerChannel {
2099
2110
  const startProgress = (event) => {
2100
2111
  if (timer || progressMs <= 0)
2101
2112
  return;
2102
- if (event && event.turnId !== queued.promptId)
2113
+ if (event && !inTurn(event.turnId))
2103
2114
  return;
2104
2115
  const observed = event ? [event] : this.options.session.eventsSince(activityCursor)
2105
- .filter(item => item.turnId === queued.promptId);
2116
+ .filter(item => inTurn(item.turnId));
2106
2117
  if (!observed.length)
2107
2118
  return;
2108
2119
  startedAt = Date.parse(observed[0].at) || Date.now();
@@ -1,3 +1,4 @@
1
+ import type { TaskReadinessIssue } from '../rooms-tasks/live-readiness.js';
1
2
  import type { InterruptOutcome, SessionEvent, SessionSnapshot } from '../session/types.js';
2
3
  import type { RoomOrchestrationRecord, TaskOutcome, TaskRecord, TaskTerminalIntent, TaskListRecord } from '../rooms-tasks/types.js';
3
4
  import { type OwnerCommentsState } from './notices.js';
@@ -58,6 +59,9 @@ export interface OwnerCommandContext {
58
59
  terminalTask(taskId: string, kind: TaskTerminalIntent['kind'], outcome?: TaskOutcome): Promise<void>;
59
60
  createTask(input: Omit<CreateTaskRequest, 'actor'>): Promise<TaskRecord>;
60
61
  startTask(taskId: string): Promise<TaskProvisioningOutcome | TaskRecord>;
62
+ observeTaskReadiness?(taskId: string): Promise<{
63
+ state: 'ready';
64
+ } | TaskReadinessIssue>;
61
65
  taskProvisioningOutcome?(taskId: string): TaskProvisioningOutcome;
62
66
  listTasks(filter?: {
63
67
  state?: TaskState | TaskState[];
@@ -47,6 +47,11 @@ function isKnownOwnerRoomState(message) {
47
47
  ].some(pattern => pattern.test(message));
48
48
  }
49
49
  function ownerTaskFailure(error) {
50
+ if (error instanceof TaskRoomApplicationError && error.code === 'task_not_ready')
51
+ return {
52
+ kind: 'state', detail: error.message,
53
+ action: 'Ask Fleet Coordinator to inspect room and member status and choose supported recovery.',
54
+ };
50
55
  if (error instanceof TaskListError)
51
56
  return {
52
57
  kind: error.code === 'list_not_found' ? 'not_found'
@@ -301,6 +306,7 @@ export const ownerCommands = [
301
306
  const trailingLines = argLines.slice(1).join('\n').trim() || undefined;
302
307
  const showTask = async (id) => {
303
308
  const { task: t } = ctx.getTask(id);
309
+ const readiness = t.state === 'active' ? await ctx.observeTaskReadiness?.(id) : undefined;
304
310
  await ctx.reply(renderMarkdownResult({
305
311
  icon: '📋', title: 'Task details',
306
312
  fields: [
@@ -308,6 +314,8 @@ export const ownerCommands = [
308
314
  { label: 'Title', value: t.title },
309
315
  { label: 'Status', value: taskStatus(t.state), kind: 'markdown' },
310
316
  { label: 'List', value: t.list_name ?? 'default', kind: 'code' },
317
+ ...(readiness ? [{ label: 'Readiness', value: readiness.state },
318
+ ...('reason' in readiness ? [{ label: 'Reason', value: readiness.reason }] : [])] : []),
311
319
  ...(t.blocked ? [{ label: 'Blocked', value: t.blocked.reason }] : []),
312
320
  ...(t.template ? [{ label: 'Template', value: `${t.template.name}@${t.template.version}`, kind: 'code' }] : []),
313
321
  ...(t.room_id ? [{ label: 'Room', value: t.room_id, kind: 'code' }] : []),
@@ -1,6 +1,6 @@
1
+ import { redactErasedContent, writePrivacyFilteredLedger } from '../erased-resources.js';
1
2
  import { createHash } from 'node:crypto';
2
3
  import { chmodSync, existsSync, readFileSync } from 'node:fs';
3
- import { replaceFileAtomically } from '../atomic-file.js';
4
4
  import { lifecycleEventDigestBasis, validateFleetAuditPresentations, } from '../fleet-command-audit.js';
5
5
  const DIGEST = /^[a-f0-9]{64}$/u;
6
6
  const LIMIT = 5_000;
@@ -63,7 +63,7 @@ export class FleetLifecycleOutbox {
63
63
  }
64
64
  pending() {
65
65
  this.assertHealthy();
66
- return this.entries.filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
66
+ return redactErasedContent(this.entries).filter(entry => entry.delivery === 'pending').map(entry => structuredClone(entry));
67
67
  }
68
68
  finish(digest, delivery) {
69
69
  this.assertHealthy();
@@ -82,6 +82,7 @@ export class FleetLifecycleOutbox {
82
82
  throw new Error(this.corruptReason);
83
83
  }
84
84
  persist() {
85
- replaceFileAtomically(this.path, `${JSON.stringify({ version: 1, entries: this.entries })}\n`, 0o600);
85
+ this.entries = redactErasedContent(this.entries);
86
+ writePrivacyFilteredLedger(this.path, { version: 1, entries: this.entries });
86
87
  }
87
88
  }
@@ -1,7 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { readFile } from 'node:fs/promises';
3
- import { extname, join } from 'node:path';
4
- import { readDaemonConfig, resolveEndpoint } from '../monitor.js';
3
+ import { extname } from 'node:path';
5
4
  import { readClientProfile } from '../client-profile.js';
6
5
  import { OursError, attachOursClient, } from '@ours.network/sdk/client';
7
6
  /** Any failure of a daemon operation. Never carries a message body or a token. */
@@ -131,24 +130,10 @@ export class OursSdkClient {
131
130
  return;
132
131
  const environment = { ...process.env, ...this.env };
133
132
  const profile = readClientProfile(environment);
134
- // Reuse existing connection configuration. Identity selection checks the
135
- // daemon capability before reading the client's protected token delivery file.
136
- const endpoint = !profile && environment.OURS_DAEMON_ID
137
- ? resolveEndpoint(environment, false) : undefined;
138
- const token = endpoint ? environment.OURS_API_TOKEN?.trim() || readDaemonConfig(environment).apiToken : undefined;
139
- const options = profile ? {
133
+ const options = {
140
134
  endpoint: profile.endpoint, expectedInstanceId: profile.expectedInstanceId,
141
135
  credentialPath: profile.credentialPath,
142
136
  sessionMode: 'external', leaseToken: this.leaseToken, env: {},
143
- } : endpoint ? {
144
- endpoint: endpoint.origin, expectedInstanceId: environment.OURS_DAEMON_ID,
145
- sessionMode: 'external', leaseToken: this.leaseToken,
146
- ...(token ? { token } : { credentialPath: join(endpoint.stateDir, 'daemon-token') }),
147
- } : {
148
- env: environment,
149
- leaseToken: this.leaseToken,
150
- clientPid: process.pid,
151
- fetch: notificationDeadlineFetch(this.deps.fetch ?? globalThis.fetch, this.deps.notificationRequestDeadlineMs ?? NOTIFICATION_REQUEST_DEADLINE_MS),
152
137
  };
153
138
  this.client = await (this.deps.attachClient?.(options) ?? attachOursClient(options));
154
139
  this.terminalReleasePending = true;
package/dist/paths.d.ts CHANGED
@@ -11,6 +11,8 @@ export declare const home: () => string;
11
11
  */
12
12
  export declare function deriveXdgRuntimeDir(env?: NodeJS.ProcessEnv, uid?: number | undefined, exists?: (p: string) => boolean): string | undefined;
13
13
  export declare const stateRoot: () => string;
14
+ /** The Owner invitation file that tunnel setup writes itself after enrollment. */
15
+ export declare const workspaceOwnerInvite: () => string;
14
16
  export declare const agentsRoot: () => string;
15
17
  export declare const tmpRoot: () => string;
16
18
  export declare const logsRoot: () => string;
package/dist/paths.js CHANGED
@@ -21,6 +21,8 @@ export function deriveXdgRuntimeDir(env = process.env, uid = process.getuid?.(),
21
21
  return env.XDG_RUNTIME_DIR;
22
22
  }
23
23
  export const stateRoot = () => join(home(), '.ours-fleet');
24
+ /** The Owner invitation file that tunnel setup writes itself after enrollment. */
25
+ export const workspaceOwnerInvite = () => join(stateRoot(), 'workspace', 'owner.invite');
24
26
  export const agentsRoot = () => join(stateRoot(), 'agents');
25
27
  export const tmpRoot = () => join(stateRoot(), 'tmp');
26
28
  export const logsRoot = () => join(stateRoot(), 'logs');
@@ -67,10 +67,35 @@ const V5_GENERATED_ROLE_DEFAULT_FINGERPRINTS = Object.freeze({
67
67
  'agent_templates/Developer.yaml': 'fdd953aab72d042e62780dd273598745aae59521b39edf4876d7676bb7189c83',
68
68
  'agent_templates/Critic.yaml': '3e98a28f17876061cfadf984351aa59fdbe19629e514eff52c74546545c64a91',
69
69
  });
70
+ // The packaged Coordinator role of revisions 8 and 9 addressed a named owner channel that a
71
+ // fresh installation does not have. Untouched copies adopt the current role; edited ones stay.
72
+ const OWNER_CHANNEL_COORDINATOR_FINGERPRINTS = Object.freeze({
73
+ 'roles/Coordinator.yaml': [
74
+ '8c8ad28d9bb9ddf9dba8c5c9c7859f25edd8fa10ebf833e2340124a6e49583ec',
75
+ 'f0d8b169ad0a18051b57e5280b93cf01e05faa5c12f4e12bdf89973edf2ef58a',
76
+ ],
77
+ });
78
+ // The packaged revision-10 LocalCoordinator continuity loop reread ROUTINES.md and the WORKLOG
79
+ // checkpoint on every 15-minute pass. Untouched copies adopt the current template; edited ones stay.
80
+ const REREADING_CONTINUITY_LOOP_FINGERPRINTS = Object.freeze({
81
+ 'agent_templates/LocalCoordinator.yaml': [
82
+ '53889cd3987e25ca42be64ddcfa1cf46a73ab769070db144f5b7d86085734178',
83
+ ],
84
+ });
85
+ // The packaged Developer, Critic and Engineer charters before they described one bounded
86
+ // self-reminder per peer wait. Untouched copies adopt the current text; edited ones stay.
87
+ const PEER_WAIT_REMINDER_FINGERPRINTS = Object.freeze({
88
+ 'roles/Developer.yaml': ['2884366ce02760d66d3edbaed2adc83f2959fd7906a7cd3b5a8b90cf601bc3e6'],
89
+ 'roles/Critic.yaml': ['998abdbc5159e8e1c26eb1ca09f9707b005ba1930bd5b7a4989c4d6893804c4a'],
90
+ 'roles/Engineer.yaml': ['a361453ad32cde08797cf90fff17a35bde1871ccea17389448b44398b45ccfa5'],
91
+ });
70
92
  const CURRENT_ROLE_DEFAULTS = new Set([
71
93
  'roles/Coordinator.yaml', 'roles/LocalCoordinator.yaml', 'roles/Developer.yaml', 'roles/Critic.yaml',
94
+ 'roles/Engineer.yaml',
72
95
  'agent_templates/LocalCoordinator.yaml', 'agent_templates/Developer.yaml', 'agent_templates/Critic.yaml',
96
+ 'agent_templates/Engineer.yaml',
73
97
  'room_templates/single.yaml', 'room_templates/pair.yaml', 'room_templates/team.yaml',
98
+ 'room_templates/engineering.yaml',
74
99
  'agents/FleetCoordinator.yaml',
75
100
  ]);
76
101
  export const legacyStarterMigrationManifest = Object.freeze({
@@ -193,6 +218,9 @@ export function migratePackagedRoleDefaults(configuration, options = {}, hooks =
193
218
  ...Object.keys(V3_ROLE_DEFAULT_FINGERPRINTS),
194
219
  ...Object.keys(V4_ROLE_DEFAULT_FINGERPRINTS),
195
220
  ...Object.keys(V5_ROLE_DEFAULT_FINGERPRINTS),
221
+ ...Object.keys(OWNER_CHANNEL_COORDINATOR_FINGERPRINTS),
222
+ ...Object.keys(REREADING_CONTINUITY_LOOP_FINGERPRINTS),
223
+ ...Object.keys(PEER_WAIT_REMINDER_FINGERPRINTS),
196
224
  ]);
197
225
  for (const relative of known) {
198
226
  const path = join(root, relative);
@@ -206,6 +234,9 @@ export function migratePackagedRoleDefaults(configuration, options = {}, hooks =
206
234
  V4_GENERATED_ROLE_DEFAULT_FINGERPRINTS[relative],
207
235
  V5_ROLE_DEFAULT_FINGERPRINTS[relative],
208
236
  V5_GENERATED_ROLE_DEFAULT_FINGERPRINTS[relative],
237
+ ...(OWNER_CHANNEL_COORDINATOR_FINGERPRINTS[relative] ?? []),
238
+ ...(REREADING_CONTINUITY_LOOP_FINGERPRINTS[relative] ?? []),
239
+ ...(PEER_WAIT_REMINDER_FINGERPRINTS[relative] ?? []),
209
240
  ].some(expected => expected !== undefined && actual === expected);
210
241
  if (recognized)
211
242
  (CURRENT_ROLE_DEFAULTS.has(relative) ? replacements : removals).push(path);
@@ -258,6 +289,18 @@ export function migratePackagedRoleDefaults(configuration, options = {}, hooks =
258
289
  unlinkSync(target);
259
290
  copyFileSync(join(source, relative), target, constants.COPYFILE_EXCL);
260
291
  chmodSync(target, 0o600);
292
+ // New Engineer seats use the existing Developer's selected brain. This
293
+ // preserves wizard/custom provider choices without copying permissions.
294
+ if (relative === 'agent_templates/Engineer.yaml' && classified.additions.includes(path)) {
295
+ const developer = join(root, 'agent_templates/Developer.yaml');
296
+ if (existsSync(developer)) {
297
+ const value = parseFleetDocument(developer, readFileSync(developer, 'utf8'), 'strict').value;
298
+ if (value.brain !== undefined && JSON.stringify(value.brain) !== JSON.stringify({ ref: 'claude-default' })) {
299
+ const bytes = readFileSync(target, 'utf8').replace('brain: { ref: claude-default }', () => `brain: ${JSON.stringify(value.brain)}`);
300
+ writeFileSync(target, bytes, { mode: 0o600 });
301
+ }
302
+ }
303
+ }
261
304
  fsyncPath(target);
262
305
  }
263
306
  for (const kind of ['roles', 'agent_templates', 'room_templates', 'agents'])
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Which run of a process a PID names. A PID alone is not an identity: after a
3
+ * reboot or wraparound the same number belongs to an unrelated process, and a
4
+ * lock or claim keyed on it would then look held forever. The kernel boot id
5
+ * and the process start time (in clock ticks since boot) pin one incarnation.
6
+ * Both are Linux-only; elsewhere they are absent and callers stay PID-only.
7
+ */
8
+ export interface ProcessIncarnation {
9
+ boot?: string;
10
+ start?: string;
11
+ }
12
+ export interface IncarnationProbe {
13
+ bootId(): string | undefined;
14
+ startTime(pid: number): string | undefined;
15
+ }
16
+ export declare const procIncarnationProbe: IncarnationProbe;
17
+ export declare function processIncarnation(pid: number, probe?: IncarnationProbe): ProcessIncarnation;
18
+ /**
19
+ * True only when a recorded marker positively proves the live PID is a later
20
+ * process: a different boot, or a different start time. A marker that was not
21
+ * recorded, or cannot be read now, proves nothing and keeps the PID check.
22
+ */
23
+ export declare function incarnationEnded(pid: number, recorded: ProcessIncarnation, probe?: IncarnationProbe): boolean;
@@ -0,0 +1,42 @@
1
+ import { readFileSync } from 'node:fs';
2
+ export const procIncarnationProbe = {
3
+ bootId() {
4
+ try {
5
+ return readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim() || undefined;
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ },
11
+ startTime(pid) {
12
+ try {
13
+ const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
14
+ return stat.slice(stat.lastIndexOf(')') + 2).split(/\s+/)[19] || undefined;
15
+ }
16
+ catch {
17
+ return undefined;
18
+ }
19
+ },
20
+ };
21
+ export function processIncarnation(pid, probe = procIncarnationProbe) {
22
+ const boot = probe.bootId(), start = probe.startTime(pid);
23
+ return { ...(boot ? { boot } : {}), ...(start ? { start } : {}) };
24
+ }
25
+ /**
26
+ * True only when a recorded marker positively proves the live PID is a later
27
+ * process: a different boot, or a different start time. A marker that was not
28
+ * recorded, or cannot be read now, proves nothing and keeps the PID check.
29
+ */
30
+ export function incarnationEnded(pid, recorded, probe = procIncarnationProbe) {
31
+ if (typeof recorded.boot === 'string') {
32
+ const boot = probe.bootId();
33
+ if (boot && boot !== recorded.boot)
34
+ return true;
35
+ }
36
+ if (typeof recorded.start === 'string') {
37
+ const start = probe.startTime(pid);
38
+ if (start && start !== recorded.start)
39
+ return true;
40
+ }
41
+ return false;
42
+ }
@@ -0,0 +1,75 @@
1
+ import type { ReminderAttempt, UrgentReminderHooks } from '../session/arbiter.js';
2
+ import type { PromptOrigin } from '../session/types.js';
3
+ import type { ReminderEvent, ReminderRecord, ReminderStore } from './store.js';
4
+ /** The admission seam: the role's RoleTurnArbiter in production. */
5
+ export interface ReminderAdmitter {
6
+ tryReminder(text: string, origin: Extract<PromptOrigin, {
7
+ kind: 'self-reminder';
8
+ }>, beforeQueue: () => boolean, releaseGuard: () => boolean): Promise<ReminderAttempt>;
9
+ /** Urgent admission (see `RoleTurnArbiter.tryUrgentReminder`). Absent: urgent reminders are idle-only. */
10
+ tryUrgentReminder?(origin: Extract<PromptOrigin, {
11
+ kind: 'self-reminder';
12
+ }>, hooks: UrgentReminderHooks): Promise<ReminderAttempt>;
13
+ }
14
+ export interface ReminderManagerDeps {
15
+ now(): number;
16
+ setTimer(callback: () => void, ms: number): unknown;
17
+ clearTimer(timer: unknown): void;
18
+ log(line: string): void;
19
+ }
20
+ /**
21
+ * The dispatcher never sleeps longer than this while reminders are open, so a
22
+ * wall-clock jump (host suspend, NTP step) is noticed within a minute. With
23
+ * nothing open it arms no timer at all: an idle agent costs nothing.
24
+ */
25
+ export declare const REMINDER_POLL_CEILING_MS = 60000;
26
+ export interface ReminderManagerHandle {
27
+ start(): void;
28
+ stop(): void;
29
+ /** Called after an agent tool changed the schedule so the timer reflects it. */
30
+ changed(): void;
31
+ }
32
+ /**
33
+ * Turns due self-reminders into wakes for the agent that owns them.
34
+ *
35
+ * Runs inside that agent's runner, beside the role's turn arbiter. It starts
36
+ * only after the role's startup turn has succeeded and stops before the runner
37
+ * releases its runtime binding. Admission is idle-only by default: a wake
38
+ * never interrupts or queues behind work, and the session's release guard
39
+ * makes the durable `dispatched` claim at the moment the prompt reaches the
40
+ * model. A reminder created with `interrupt: true` is considered first and may
41
+ * ask an interruptible busy turn to stop once (`tryUrgentReminder`); the
42
+ * release guard is still the only path to the model.
43
+ */
44
+ export declare class ReminderManager implements ReminderManagerHandle {
45
+ private readonly role;
46
+ private readonly store;
47
+ private readonly admitter;
48
+ private readonly deps;
49
+ private timer?;
50
+ private started;
51
+ private stopping;
52
+ private polling;
53
+ private busyStreak;
54
+ /** Consecutive re-arms with work already overdue; drives the spin backoff. */
55
+ private overdueStreak;
56
+ private readonly inFlight;
57
+ constructor(role: string, store: ReminderStore, admitter: ReminderAdmitter, deps: ReminderManagerDeps);
58
+ start(): void;
59
+ /** Synchronous: after this returns no timer is armed and every release guard refuses. */
60
+ stop(): void;
61
+ get isStopping(): boolean;
62
+ changed(): void;
63
+ /** Public fake-clock seam; the timer calls the same transition. */
64
+ poll(): Promise<void>;
65
+ private admit;
66
+ private guard;
67
+ private retryAt;
68
+ private schedule;
69
+ }
70
+ /**
71
+ * The wake text. It carries the agent's own title so the wake is legible, but
72
+ * the note is only returned by `fleet_reminder_inspect`, which also re-checks
73
+ * eligibility at the moment the agent acts.
74
+ */
75
+ export declare function wakePrompt(event: ReminderEvent, reminder: ReminderRecord, now: number, retry: boolean): string;