@ours.network/fleet 1.1.0-nightly.2 → 1.1.0-nightly.20

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 (199) hide show
  1. package/README.md +169 -54
  2. package/dist/agent-recovery-gate.d.ts +17 -0
  3. package/dist/agent-recovery-gate.js +135 -0
  4. package/dist/application/capabilities.js +18 -6
  5. package/dist/application/fleet-query-service.js +20 -5
  6. package/dist/application/role-command-service.js +9 -0
  7. package/dist/application/role-creation-service.d.ts +6 -25
  8. package/dist/application/role-creation-service.js +34 -72
  9. package/dist/application/role-repository.d.ts +4 -2
  10. package/dist/application/role-repository.js +6 -3
  11. package/dist/application/session-control.d.ts +3 -1
  12. package/dist/application/session-control.js +4 -2
  13. package/dist/application/task-room-service.d.ts +58 -6
  14. package/dist/application/task-room-service.js +426 -78
  15. package/dist/briefing.js +74 -24
  16. package/dist/build-info.json +4 -4
  17. package/dist/canonical-json.d.ts +2 -0
  18. package/dist/canonical-json.js +10 -0
  19. package/dist/cli.js +227 -73
  20. package/dist/config-yaml.d.ts +1 -1
  21. package/dist/config.d.ts +67 -2
  22. package/dist/config.js +260 -30
  23. package/dist/daemon-recovery.d.ts +93 -0
  24. package/dist/daemon-recovery.js +328 -0
  25. package/dist/docs.d.ts +1 -1
  26. package/dist/docs.js +171 -66
  27. package/dist/doctor.d.ts +2 -0
  28. package/dist/doctor.js +54 -4
  29. package/dist/fleet-command-audit.d.ts +165 -0
  30. package/dist/fleet-command-audit.js +543 -0
  31. package/dist/fleet-proxy.d.ts +7 -2
  32. package/dist/fleet-proxy.js +30 -8
  33. package/dist/harness/agent-session.d.ts +5 -0
  34. package/dist/harness/claude-code-session.d.ts +2 -0
  35. package/dist/harness/claude-code-session.js +6 -1
  36. package/dist/harness/claude-code.js +2 -0
  37. package/dist/harness/codex-app-server-proxy.d.ts +40 -0
  38. package/dist/harness/codex-app-server-proxy.js +348 -14
  39. package/dist/harness/codex-session.d.ts +11 -2
  40. package/dist/harness/codex-session.js +22 -2
  41. package/dist/harness/codex.d.ts +5 -1
  42. package/dist/harness/codex.js +110 -10
  43. package/dist/harness/types.d.ts +1 -1
  44. package/dist/index.d.ts +5 -4
  45. package/dist/index.js +4 -3
  46. package/dist/init-guidance.d.ts +1 -1
  47. package/dist/init-guidance.js +4 -3
  48. package/dist/init-wizard.d.ts +98 -0
  49. package/dist/init-wizard.js +629 -0
  50. package/dist/lifecycle-summary.d.ts +118 -0
  51. package/dist/lifecycle-summary.js +161 -0
  52. package/dist/loops/config.js +3 -2
  53. package/dist/model-env.d.ts +2 -2
  54. package/dist/model-env.js +1 -1
  55. package/dist/model-recovery.d.ts +1 -1
  56. package/dist/ops.js +2 -17
  57. package/dist/owner-channel/channel.d.ts +58 -0
  58. package/dist/owner-channel/channel.js +321 -42
  59. package/dist/owner-channel/commands.d.ts +6 -1
  60. package/dist/owner-channel/commands.js +34 -19
  61. package/dist/owner-channel/state.d.ts +2 -0
  62. package/dist/owner-channel/state.js +8 -2
  63. package/dist/permissions.js +1 -1
  64. package/dist/preset-bootstrap.d.ts +10 -0
  65. package/dist/preset-bootstrap.js +85 -0
  66. package/dist/preset-migration.d.ts +42 -0
  67. package/dist/preset-migration.js +414 -0
  68. package/dist/reports/artifact.d.ts +10 -0
  69. package/dist/reports/artifact.js +32 -0
  70. package/dist/reports/index.d.ts +5 -0
  71. package/dist/reports/index.js +5 -0
  72. package/dist/reports/render.d.ts +6 -0
  73. package/dist/reports/render.js +240 -0
  74. package/dist/reports/service.d.ts +42 -0
  75. package/dist/reports/service.js +57 -0
  76. package/dist/reports/tasks.d.ts +52 -0
  77. package/dist/reports/tasks.js +177 -0
  78. package/dist/reports/types.d.ts +315 -0
  79. package/dist/reports/types.js +6 -0
  80. package/dist/resolved-plan.js +4 -0
  81. package/dist/rooms-tasks/cli.d.ts +2 -0
  82. package/dist/rooms-tasks/cli.js +503 -75
  83. package/dist/rooms-tasks/close.d.ts +9 -1
  84. package/dist/rooms-tasks/close.js +20 -4
  85. package/dist/rooms-tasks/config.js +16 -14
  86. package/dist/rooms-tasks/cowork-adapter.d.ts +1 -0
  87. package/dist/rooms-tasks/cowork-adapter.js +6 -0
  88. package/dist/rooms-tasks/deletion.d.ts +51 -0
  89. package/dist/rooms-tasks/deletion.js +217 -0
  90. package/dist/rooms-tasks/external-worker.d.ts +1 -0
  91. package/dist/rooms-tasks/external-worker.js +14 -9
  92. package/dist/rooms-tasks/launch-snapshot.d.ts +19 -0
  93. package/dist/rooms-tasks/launch-snapshot.js +176 -0
  94. package/dist/rooms-tasks/member-overrides.d.ts +27 -0
  95. package/dist/rooms-tasks/member-overrides.js +170 -0
  96. package/dist/rooms-tasks/provision.js +179 -49
  97. package/dist/rooms-tasks/room-state.d.ts +1 -0
  98. package/dist/rooms-tasks/room-state.js +12 -1
  99. package/dist/rooms-tasks/task-state.d.ts +115 -3
  100. package/dist/rooms-tasks/task-state.js +361 -11
  101. package/dist/rooms-tasks/templates.d.ts +4 -2
  102. package/dist/rooms-tasks/templates.js +42 -78
  103. package/dist/rooms-tasks/terminal.d.ts +3 -0
  104. package/dist/rooms-tasks/terminal.js +7 -3
  105. package/dist/rooms-tasks/types.d.ts +94 -17
  106. package/dist/rooms-tasks/types.js +14 -4
  107. package/dist/runner.d.ts +9 -2
  108. package/dist/runner.js +107 -40
  109. package/dist/session/acp.d.ts +9 -1
  110. package/dist/session/acp.js +35 -9
  111. package/dist/session/arbiter.d.ts +2 -1
  112. package/dist/session/arbiter.js +2 -0
  113. package/dist/session/codex-app-server-transport.d.ts +53 -0
  114. package/dist/session/codex-app-server-transport.js +184 -0
  115. package/dist/session/codex-app-server.d.ts +122 -0
  116. package/dist/session/codex-app-server.js +1031 -0
  117. package/dist/session/control.d.ts +14 -1
  118. package/dist/session/control.js +38 -0
  119. package/dist/session/conversation-types.d.ts +4 -4
  120. package/dist/session/types.d.ts +24 -6
  121. package/dist/session/types.js +28 -0
  122. package/dist/spawn.d.ts +6 -31
  123. package/dist/spawn.js +57 -234
  124. package/dist/temp-lifecycle.d.ts +1 -1
  125. package/dist/watchdog/config.d.ts +10 -7
  126. package/dist/watchdog/config.js +29 -19
  127. package/dist/watchdog/run.js +4 -13
  128. package/dist/web/fleet-config-service.d.ts +1 -0
  129. package/dist/web/fleet-config-service.js +27 -8
  130. package/dist/web/runtime.js +11 -6
  131. package/dist/web/server.js +28 -1
  132. package/dist/web/topology-promote.js +8 -1
  133. package/dist/web-app/assets/index-C0h3ALvs.js +10 -0
  134. package/dist/web-app/index.html +1 -1
  135. package/package.json +3 -2
  136. package/presets/brain-catalog.json +16 -0
  137. package/presets/fleet/agent_templates/Critic.yaml +4 -0
  138. package/presets/fleet/agent_templates/Developer.yaml +4 -0
  139. package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -0
  140. package/presets/fleet/agents/FleetCoordinator.yaml +3 -0
  141. package/presets/fleet/brains/claude-default.yaml +5 -0
  142. package/presets/fleet/brains/claude-fable-5-high.yaml +5 -0
  143. package/presets/fleet/brains/claude-fable-5-low.yaml +5 -0
  144. package/presets/fleet/brains/claude-fable-5-max.yaml +5 -0
  145. package/presets/fleet/brains/claude-fable-5-medium.yaml +5 -0
  146. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +5 -0
  147. package/presets/fleet/brains/claude-opus-5-high.yaml +5 -0
  148. package/presets/fleet/brains/claude-opus-5-low.yaml +5 -0
  149. package/presets/fleet/brains/claude-opus-5-max.yaml +5 -0
  150. package/presets/fleet/brains/claude-opus-5-medium.yaml +5 -0
  151. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +5 -0
  152. package/presets/fleet/brains/claude-sonnet-5-high.yaml +5 -0
  153. package/presets/fleet/brains/claude-sonnet-5-low.yaml +5 -0
  154. package/presets/fleet/brains/claude-sonnet-5-max.yaml +5 -0
  155. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +5 -0
  156. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +5 -0
  157. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +5 -0
  158. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +5 -0
  159. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +5 -0
  160. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +5 -0
  161. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +5 -0
  162. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +5 -0
  163. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +5 -0
  164. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +5 -0
  165. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +5 -0
  166. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +5 -0
  167. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +5 -0
  168. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +5 -0
  169. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +5 -0
  170. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +5 -0
  171. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +5 -0
  172. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +5 -0
  173. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +5 -0
  174. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +5 -0
  175. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +5 -0
  176. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +5 -0
  177. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +5 -0
  178. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +5 -0
  179. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +5 -0
  180. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +5 -0
  181. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +5 -0
  182. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +5 -0
  183. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +5 -0
  184. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +5 -0
  185. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +5 -0
  186. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +5 -0
  187. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +5 -0
  188. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +5 -0
  189. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +5 -0
  190. package/presets/fleet/roles/Coordinator.yaml +30 -0
  191. package/presets/fleet/roles/Critic.yaml +19 -0
  192. package/presets/fleet/roles/Developer.yaml +19 -0
  193. package/presets/fleet/roles/LocalCoordinator.yaml +25 -0
  194. package/presets/fleet/room_templates/pair.yaml +10 -0
  195. package/presets/fleet/room_templates/single.yaml +7 -0
  196. package/presets/fleet/room_templates/team.yaml +12 -0
  197. package/presets/fleet.yaml +7 -0
  198. package/presets/manifest.json +6 -0
  199. package/dist/web-app/assets/index-BbE9EX6n.js +0 -10
package/dist/docs.js CHANGED
@@ -6,11 +6,11 @@
6
6
  */
7
7
  export const AI_DOCS = `# ours-fleet reference
8
8
 
9
- ours-fleet runs persistent or temporary, identity-bound AI roles through the
10
- structured ACP session path:
9
+ ours-fleet runs persistent or temporary, identity-bound AI roles through a
10
+ provider-neutral managed-session interface:
11
11
 
12
12
  - harness: \`claude-code\` or \`codex\`
13
- - session: \`acp\` (default and only supported value)
13
+ - session: \`acp\` (default) or \`codex-app-server\` (Codex only)
14
14
  - lifetime: permanent (supervised, restartable) or \`spawn --temp\`
15
15
 
16
16
  ## Discover and validate
@@ -24,15 +24,19 @@ ours-fleet version [--json] # build identity, capabilities, every in
24
24
  \`\`\`
25
25
 
26
26
  Configuration v2 is \`~/fleet.yaml\` plus typed bare documents under the exact
27
- stem directories \`~/fleet/agents\`, \`~/fleet/roles\`, and \`~/fleet/brains\`.
27
+ stem directories \`~/fleet/agents\`, \`~/fleet/agent_templates\`, \`~/fleet/roles\`, \`~/fleet/brains\`, and
28
+ \`~/fleet/room_templates\`.
28
29
  The manifest owns fleet-wide operational defaults and automation; each Agent
29
30
  selects one inline/ref Role and Brain and carries its operational fields.
31
+ Agent Templates under \`~/fleet/agent_templates\` are inert reusable launch definitions;
32
+ only explicit files under \`~/fleet/agents\` are persistent lifecycle instances.
33
+ Room members use \`agent_template\` and receive immutable content-addressed snapshots.
30
34
  Legacy top-level \`roles:\` and \`fleet.d\` are rejected. Validate the complete
31
35
  trusted source set with \`config\` and \`doctor\` before starting or restarting.
32
36
 
33
37
  Permanent \`spawn\` writes \`~/fleet/agents/Name.yaml\`. The web console edits an
34
- explicit \`{manifest, agents}\` model while Role/Brain presets remain read-only.
35
- Its aggregate revision includes every Agent/Role/Brain source, previews a
38
+ explicit \`{manifest, agents, agent_templates}\` model while Role/Brain presets remain read-only.
39
+ Its aggregate revision includes every Agent/Role/Brain/Room-template source, previews a
36
40
  redacted per-document diff in an exact-stem private staging tree, and saves under
37
41
  one root lock with a private multi-file backup and full rollback. A no-op is
38
42
  byte-identical and creates no backup.
@@ -78,7 +82,7 @@ PATH order.
78
82
  ## Lifecycle and console commands
79
83
 
80
84
  \`\`\`sh
81
- ours-fleet init
85
+ ours-fleet init [-c FILE] # interactive missing-default seed; TTY required
82
86
  ours-fleet up|down [Name...]
83
87
  ours-fleet restart [Name...] # preserve/resume harness context
84
88
  ours-fleet force-restart [Name...] # fresh context; briefing is reloaded
@@ -91,6 +95,27 @@ ours-fleet watchdog-report <name> [run-id] [--list] [--json]
91
95
  ours-fleet watchdog-run <name>
92
96
  \`\`\`
93
97
 
98
+ \`init\` is an interactive missing-default workflow that preserves existing files byte-for-byte.
99
+ It names the resolved manifest and split directory, asks a default-No confirmation,
100
+ then subscriptions (Codex, Claude, or both), model assignment (one explicit model for
101
+ every job or explicit development/review/coordination choices), one reasoning level,
102
+ and a final default-No review. Quick/Balanced/Thorough generate low/medium/high.
103
+ Model pickers show packaged supported IDs; catalog membership is not a recommendation
104
+ or entitlement claim. Run \`ours-fleet doctor\` for local Codex availability; Claude
105
+ entitlement is checked when a role launches. The generated brains contain no
106
+ \`model_chain\`, so Fleet never silently substitutes another model.
107
+
108
+ At either confirmation, N, Enter, Escape, Ctrl-C, Ctrl-D, or EOF cancels. In a picker,
109
+ Escape, Ctrl-C, Ctrl-D, or EOF cancels; Enter records the highlight or continues a
110
+ non-empty multi-select, N is ignored, and an empty subscription selection remains blocked.
111
+ Every cancellation before final approval performs no host or configuration mutation.
112
+ Redirected/non-TTY invocation is refused with the same guarantee. After the final Yes,
113
+ host setup precedes publication. Path ownership/type/mode/symlink and
114
+ same-filesystem checks run before host setup and again under a per-setup lock. Publication
115
+ stages and validates the complete combined setup, backs up whichever old target(s) exist,
116
+ and retains a private recovery record. A hard process/host termination cannot promise
117
+ rollback; inspect host integration and private init stage/recovery evidence.
118
+
94
119
  \`peek\`, \`attach\`, and text \`send\` use the structured agent session.
95
120
  Attachment also accepts \`/permit <permission-id> <option-id>\`, \`/interrupt\`,
96
121
  and \`/detach\`.
@@ -149,21 +174,19 @@ harness's own default.
149
174
  ## Spawn
150
175
 
151
176
  \`\`\`sh
152
- ours-fleet spawn [--temp] [Name | --role Name] \\
153
- --harness codex|claude-code --session acp \\
154
- --mission "one line" --cwd /absolute/path --identity Identity \\
155
- --coordinator Coordinator --model MODEL \\
177
+ ours-fleet spawn [--temp] [Name | --name Name] \\
178
+ --brain BRAIN_ID --role ROLE_ID \\
179
+ --cwd /absolute/path --identity Identity --coordinator Coordinator \\
156
180
  --approval ask|auto|allow \\
157
181
  --filesystem read-only|workspace|unrestricted \\
158
- --unattended deny|wait \\
159
- --bio-file /path/bio.md --persona-file /path/persona.md
182
+ --unattended deny|wait --isolation-file /path/isolation.yaml
160
183
  \`\`\`
161
184
 
162
185
  Permanent spawn writes \`~/fleet/agents/Name.yaml\` and starts a supervised role.
163
186
  \`--temp\` writes active state under \`~/.ours-fleet/tmp\` and starts an independent
164
187
  transient supervisor (a collected systemd unit or submitted launchd job). It is
165
188
  not enabled across reboot and does not die when the role that spawned it restarts.
166
- Both lifetimes support \`--session acp\`. When a temporary role's bound identity
189
+ Brain definitions own the managed session backend. When a temporary role's bound identity
167
190
  closes or its session ends, the supervisor, monitor and live roster entry retire
168
191
  together; state moves intact to \`~/.ours-fleet/recovery/temporary\` with a
169
192
  termination record. Failed launches use the same archive rather than deleting
@@ -195,27 +218,32 @@ only sustained authoritative absence closes the role. Unreachable, malformed, or
195
218
  valid-but-empty daemon indexes are ambiguous and reset closure debounce rather
196
219
  than becoming cleanup authority.
197
220
 
198
- Inside a managed ACP role, the same CLI automatically routes a real \`spawn\`
199
- through that role's authenticated supervisor control socket. \`--role Name\` is
200
- accepted as an alternative to the positional name, so a minimal delegated call
201
- is \`ours-fleet spawn --role DeveloperX --temp\`. The supervisor records the
202
- calling role, performs creation, and only after success sends a structured
203
- spawn notice through the caller's owner channel when one is configured.
204
-
205
- Omitted harness, session, working directory, coordinator, neutral permissions,
206
- fleet monitor policy, and (when the harness is unchanged) model inherit from the
207
- calling role. Explicit options always win. Selecting a different harness without
208
- \`--model\` leaves model selection to that harness/fleet defaults rather than
209
- copying an incompatible caller model. This automatic proxy is a convenience and
221
+ Inside a managed role, public \`ours-fleet\` commands cross an authenticated
222
+ supervisor attribution boundary before Commander parsing. The original CLI remains
223
+ the executor inside the role's existing OS sandbox, and ordinary CLI validation is
224
+ the source of truth. Hidden worker entry points remain internal; public lifecycle and
225
+ operator commands are not restricted by the proxy.
226
+
227
+ Command invocation, raw argv, read-only work, validation failures, and generic
228
+ outcomes are never forwarded to the Owner-visible channel. Fleet announces only
229
+ confirmed Agent, Task, and Room lifecycle changes. Local diagnostics retain
230
+ structurally redacted command metadata. Lifecycle delivery uncertainty is logged,
231
+ never recursively announced, and never reruns or blindly retries an effect.
232
+ Room participant summaries describe creation and activation. Fleet has no public
233
+ post-create Room membership mutation, so it does not claim a separate membership event.
234
+
235
+ Omitted Brain and Role selections, working directory, coordinator, neutral permissions,
236
+ and fleet monitor policy inherit from the calling Agent. Explicit options always win.
237
+ Identity, mission/profile text, environment, owner routing, auth proxy, room startup,
238
+ isolation, worklog, and sensitive inline Brain values never inherit implicitly.
239
+ This automatic proxy is a convenience and
210
240
  attribution mechanism, not an isolation boundary: an unrestricted role can still
211
241
  invoke another binary path directly. Host/operator shells keep the ordinary direct
212
242
  CLI behavior.
213
243
 
214
- Codex-specific spawn flags: \`--sandbox\`, \`--permission-mode\`, \`--launcher\`,
215
- \`--profile\`, \`--search\`, repeatable \`--codex-config key=value\`, repeatable
216
- \`--add-dir\`, and legacy \`--monitor\` (consent for the native Codex monitor,
217
- not the \`monitor.mode\` wake-owner selector). Run \`ours-fleet help spawn\` for
218
- exact values.
244
+ Brain owns harness, session, model, reasoning effort, token limits, and native harness
245
+ options. Removed runtime flags are rejected with migration guidance rather than silently
246
+ reinterpreted. A selection is a stable ID or an explicit \`inline:{...}\` mapping.
219
247
 
220
248
  ## fleet.yaml
221
249
 
@@ -238,25 +266,19 @@ watchdogs:
238
266
  enabled: true # default true; false = configured but never scheduled
239
267
  interval: 10m # default 10m; 30s | 10m | 2h, minimum 1m
240
268
  watch: [Alice, CodexReviewer] # explicit lists are exact; omit for configured + live temp roles
241
- harness: claude-code # default: built-in claude-code
242
- model: claude-fable-5 # default: same resolution rule roles use (resolveRoleModel)
243
- session: acp # default: built-in ACP
269
+ agent: { ref: WatchdogAgent } # required: declared Agent ID, or canonical inline Agent definition
244
270
  identity: Watchdog-nightwatch # default: Watchdog-<name>
245
271
  timeout: 5m # default 5m; a run past this is killed and recorded as error
246
272
  keep_reports: 50 # default 50 reports retained per watchdog
247
273
  alert_cooldown: 60m # default 60m before the same finding alerts again
248
274
  prompt_file: /abs/extra.md # optional extra focus, APPENDED to the fixed contract
249
- isolation: # optional; omitted means no OS sandbox, like an ordinary role
250
- backend: bubblewrap # when present, the ordinary role isolation schema applies
251
- network: broker
252
- fs: { read: [/opt/watch-data] }
253
275
  \`\`\`
254
276
 
255
277
  An Agent is a separate bare document under \`~/fleet/agents/<ID>.yaml\`:
256
278
 
257
279
  \`\`\`yaml
258
280
  role: { inline: { mission: Coordinate work and delegate implementation. } }
259
- brain: { inline: { harness: codex, session: acp, model: gpt-model-id } }
281
+ brain: { inline: { harness: codex, session: codex-app-server, model: gpt-model-id } }
260
282
  identity: Coordinator
261
283
  cwd: \${work_root}/project
262
284
  oversee: [{ agent: Worker, interval: 5m }]
@@ -266,9 +288,9 @@ A watchdog observes and reports; it never restarts, stops, spawns, or removes a
266
288
  role, answers a pending permission, edits a workspace, or approves anything on
267
289
  the owner's behalf. \`watchdogs:\` may appear only in the base config
268
290
  (\`~/fleet.yaml\` or \`-c FILE\`); Agent/Role/Brain documents never own it.
269
- Watchdogs are not isolated by default. An explicit watchdog \`isolation:\` block
270
- uses the same policy schema as a role and is applied unchanged; declare every
271
- extra filesystem access required by a custom prompt there.
291
+ The selected Agent owns Brain, Role, permissions, isolation, and every other
292
+ agent setting. Legacy watchdog \`harness\`, \`model\`, \`session\`, and
293
+ \`isolation\` fields fail with migration guidance.
272
294
  When \`watch:\` is omitted, each run watches the configured roles plus temporary
273
295
  fleet roles that are live when the run starts. An explicit \`watch:\` list is
274
296
  never augmented.
@@ -285,6 +307,45 @@ the shared daemon only through an explicit operator or installer/setup flow.
285
307
 
286
308
  ## Rooms and tasks
287
309
 
310
+ \`init\` materializes editable \`single\`, \`pair\`, and \`team\` Room templates plus
311
+ their exact-cased Agent, Role, and Brain presets. The command prints the packaged
312
+ preset revision and source directory. Inspect provenance and content before use:
313
+
314
+ \`\`\`sh
315
+ ours-fleet config [-c FILE]
316
+ ours-fleet template list [-c FILE]
317
+ ours-fleet template show team [-c FILE]
318
+ ours-fleet task create --title "Solo task" --template single [-c FILE]
319
+ ours-fleet task create --title "Reviewed change" --template pair [-c FILE]
320
+ ours-fleet task create --title "Phased delivery" --template team [-c FILE]
321
+ \`\`\`
322
+
323
+ An alternate manifest \`-c /path/custom.yaml\` uses \`/path/custom/\` as its split
324
+ root. Repeated init only fills missing files and never adopts a newer default.
325
+ Revision-3 packaged-bootstrap and generated role defaults have an exact-semantic,
326
+ fail-closed migration (dry-run by default):
327
+
328
+ \`ours-fleet migrate-role-defaults [-c FILE]\`
329
+ \`ours-fleet migrate-role-defaults [-c FILE] --write\`
330
+
331
+ Review removals, replacements, additions, preserved custom files, staging path,
332
+ and recovery path. Same-named custom files stay byte-identical; dangling custom
333
+ references refuse publication, and a successful rerun is a no-op. For explicit
334
+ single-file adoption, copy from init's reported packaged source beside the target
335
+ as \`.new-default\`, inspect \`diff -u TARGET TARGET.new-default\`, then replace it.
336
+
337
+ The exact generated six-worker legacy starter Agent set has its own fail-closed
338
+ migration (dry-run by default):
339
+
340
+ \`ours-fleet migrate-agent-templates [-c FILE]\`
341
+ \`ours-fleet migrate-agent-templates [-c FILE] --write\`
342
+
343
+ Review the dry-run moves, addition, staging path, and retained recovery-backup path
344
+ before \`--write\`. Customized/partial known starters and unsafe trees refuse without
345
+ mutation; unrelated custom persistent Agents remain persistent. A manifest-level template
346
+ may shadow a same-named file only with \`override_builtin: true\` and a higher
347
+ version; this compatibility marker is deprecated and reported as a diagnostic.
348
+
288
349
  Rooms always use \`ours-cowork\`; there is no room-provider selector. Configure
289
350
  the cowork daemon connection and room owner directly:
290
351
 
@@ -312,6 +373,13 @@ Cowork role, and task. The agent creates that identity itself with ours MCP
312
373
  work immediately. Fleet activates the room from Cowork's authenticated seat; there
313
374
  is no briefing hash, startup ACK, or separate role-briefing readiness gate.
314
375
 
376
+ Set \`room.anonymous: true\` on a room template, or pass \`--anonymous\` to
377
+ \`task create\`, \`task start\`, \`task work\`, or \`room create\`, to create an
378
+ anonymous Cowork room. \`--no-anonymous\` explicitly overrides an anonymous
379
+ template. Fleet records the resolved value before room creation so retries keep
380
+ the same choice. Temporary members of an anonymous room are instructed to call
381
+ \`create_temporary_identity\` with \`expose_local=false\`.
382
+
315
383
  Human task and room results use the same compact Markdown presentation in the
316
384
  CLI and authenticated owner channel: a short heading, icon-plus-word status,
317
385
  code-formatted identifiers, bounded summaries, and actionable recovery or error
@@ -360,11 +428,24 @@ The prerelease configuration names \`tasks.close_room_on_done\` and
360
428
  semantics. Older prerelease \`closed\` room records are deleted directly the next
361
429
  time \`room list\` reconciles Fleet with Cowork.
362
430
 
363
- \`ours-fleet task delete <id> <id>\` removes only a \`done\` task's Fleet backlog
364
- record. The exact task ID is required twice for confirmation. Delete rejects every
365
- other task state, never changes any room state, and reports an already-missing
366
- task as an idempotent no-op. The Owner-channel equivalent is
367
- \`/task delete <id> <id>\`.
431
+ \`ours-fleet task delete <id> <id>\` permanently deletes a task in ANY lifecycle
432
+ state — backlog, provisioning, active, blocked, review, done, cancelled, failed,
433
+ or partially settled. The exact task ID is required twice for confirmation. A
434
+ durable deletion intent is persisted before any side effect; the cleanup worker
435
+ then retires managed room members with evidence, closes and deletes an attached
436
+ room (tolerating already-missing remote rooms), releases the sealed launch
437
+ snapshot, and unlinks the task record last. While cleanup settles the task is
438
+ hidden from normal listings and every lifecycle mutation is rejected; if
439
+ cleanup cannot complete (for example Cowork is unreachable), the deletion stays
440
+ in a precise recoverable state — repeat the delete command or run
441
+ \`task recover <id>\` to converge after outages, crashes, or restarts. Deletion
442
+ never fabricates a \`done\` transition. A metadata-only deletion receipt
443
+ (acceptance actor, original state, timestamps, completion) is retained under
444
+ \`deletion-receipts/\` as durable audit evidence. An already-missing task is an
445
+ idempotent no-op. The Owner-channel equivalent is \`/task delete <id> <id>\`; the
446
+ management API equivalent is \`DELETE /api/v1/tasks/<id>?confirm=<id>\` (200 when
447
+ settled, 202 while pending; \`GET /api/v1/tasks?includeDeleting=true\` exposes
448
+ deletion-pending tasks to operators).
368
449
 
369
450
  ## Permissions
370
451
 
@@ -373,12 +454,13 @@ Prefer the harness-neutral \`permissions\` block:
373
454
  - \`approval: ask|auto|allow\`: portable permission policy. \`deny\` remains a
374
455
  deprecated, fail-closed compatibility alias for existing fleet files.
375
456
  - \`filesystem: read-only|workspace|unrestricted\`: filesystem intent
376
- - \`unattended: deny|wait\`: what ACP does when no console can answer a request
457
+ - \`unattended: deny|wait\`: what a managed session does when no console can
458
+ answer a request
377
459
 
378
- The backend translates this common intent. Harness-native settings in
379
- \`harness_options\` take precedence where supplied. Do not choose
380
- \`allow\`/\`unrestricted\`, Codex \`never\`/\`danger-full-access\`, or Claude
381
- \`bypassPermissions\` without explicit authorization.
460
+ The backend translates this common intent. Native Codex app-server roles reject
461
+ permission aliases in \`harness_options\`; Codex ACP and Claude retain their
462
+ legacy native-override compatibility. Do not choose \`allow\`/\`unrestricted\`
463
+ or Claude \`bypassPermissions\` without explicit authorization.
382
464
 
383
465
  ### Creation-time isolation
384
466
 
@@ -451,12 +533,14 @@ permissions through its harness and check the result against a fixed floor:
451
533
  deny those requests with nobody to see it; with \`unattended: wait\` it warns,
452
534
  because a human can still attach and answer.
453
535
 
454
- Security meaning: \`ask\` maps to Codex \`untrusted\` and Claude \`default\`.
455
- \`auto\` selects Codex ACP \`agent\` (\`on-request\` + \`workspace-write\`) and
456
- Claude \`acceptEdits\`. \`approval: allow\` selects Codex ACP's fully
457
- non-interactive yolo mode, reported as \`agent-full-access\` (\`never\` +
458
- \`danger-full-access\`), and Claude \`bypassPermissions\`. These modes genuinely
459
- permit the actions the role was authorized to take —
536
+ Security meaning: native Codex maps \`ask\` → \`untrusted\`, \`auto\` →
537
+ \`on-request\`, and \`allow\` → \`never\`; its independent filesystem mapping is
538
+ \`read-only\` → \`read-only\`, \`workspace\` → \`workspace-write\`, and
539
+ \`unrestricted\` → \`danger-full-access\`. Users configure only the Fleet names.
540
+ Claude maps \`ask\` to \`default\`, \`auto\` to \`acceptEdits\`, and \`allow\` to
541
+ \`bypassPermissions\`. Codex ACP retains its adapter-specific coupled modes:
542
+ \`auto\` selects \`agent\`, while \`allow\` selects \`agent-full-access\`. These
543
+ modes genuinely permit the actions the role was authorized to take —
460
544
  \`dontAsk\` only suppresses the prompt while still refusing the action. Nothing
461
545
  other than an explicit \`allow\` becomes non-interactive. Legacy \`deny\` keeps
462
546
  its conservative Codex \`on-request\` / Claude \`plan\` translation. \`allow\` is therefore a real grant and
@@ -511,10 +595,31 @@ refused at validation rather than accepted and dropped. This narrows a role's
511
595
  tool surface; it does not stop the harness deferring tool schemas, which is the
512
596
  harness's own decision.
513
597
 
514
- Codex \`harness_options\`: \`launcher\` (auto, ours-codex, codex), \`sandbox\`
515
- (read-only, workspace-write, danger-full-access), \`approval\` or
516
- \`permission_mode\` (untrusted, on-request, never), \`profile\`, \`search\`,
517
- \`config\`, \`add_dirs\`, and \`monitor\`.
598
+ Codex \`harness_options\`: \`launcher\` (auto, ours-codex, codex), \`search\`,
599
+ \`config\`, \`add_dirs\`, and \`monitor\`; Codex ACP additionally supports
600
+ \`profile\`. Native app-server roles reject \`profile\` because Codex does not
601
+ accept \`--profile\` for \`app-server\`. They
602
+ must express approval and filesystem authority through the shared
603
+ \`permissions:\` block, never through harness options. The adapter translates
604
+ \`ask|auto|allow\` to Codex \`untrusted|on-request|never\` and translates
605
+ \`read-only|workspace|unrestricted\` to Codex
606
+ \`read-only|workspace-write|danger-full-access\`. Native \`config\` currently
607
+ allows only \`model_reasoning_effort\`; ACP retains the broader Codex config surface.
608
+
609
+ For Codex, the opt-in \`session: codex-app-server\` directly runs Codex's native
610
+ JSONL app server behind Fleet's provider-neutral session contract. It supports native item
611
+ streaming, commentary/final phases, prompt admission, steering, interruption,
612
+ permission requests, durable conversation projection, and thread resume. Packaged
613
+ Codex brains and the init wizard continue to select \`session: acp\` for compatibility;
614
+ Claude Code also uses ACP. Native Codex defaults to \`codex app-server\` (or \`ours-codex app-server\`
615
+ when launcher auto finds it). Override the exact command when necessary:
616
+
617
+ \`session_options: { codex_app_server: { command: [codex, app-server] } }\`
618
+
619
+ An exact command override receives no appended profile, search, or subcommand
620
+ arguments. Native sessions persist their Codex thread in Fleet's \`.session-id\`
621
+ and participate in its bounded fresh/resume recovery; cross-provider conversation
622
+ portability is never assumed.
518
623
 
519
624
  ## ACP adapters
520
625
 
@@ -567,7 +672,7 @@ Inspect \`ours-fleet status Name\`, \`peek Name\`, role logs, and
567
672
 
568
673
  ## Trusted owner channel
569
674
 
570
- An ACP role may declare a separate ours identity which fleet — never the agent —
675
+ Any managed role may declare a separate ours identity which fleet — never the agent —
571
676
  creates when missing and binds:
572
677
 
573
678
  \`\`\`yaml
@@ -668,12 +773,12 @@ provenance checks.
668
773
  The channel identity must be unique and must not be a role identity. The bridge
669
774
  persists bounded wire IDs only, never message/reply plaintext, and requeues input
670
775
  before starting its turn for at-least-once crash recovery. It currently requires
671
- the structured agent-session interface backed by ACP so correlated final replies
672
- retain their delivery guarantee.
776
+ the structured agent-session interface so correlated final replies retain their
777
+ delivery guarantee.
673
778
 
674
779
  ### Live contact and owner administration
675
780
 
676
- The supervisor which is already running the ACP role remains the sole binder of
781
+ The supervisor which is already running the managed role remains the sole binder of
677
782
  \`owner_channel.identity\`. The CLI reaches that exact live \`OwnerChannel\`
678
783
  through the role's token-authenticated, mode-0600 Unix control socket for contact
679
784
  inspection and setup; it never starts another ours client and never force-binds:
package/dist/doctor.d.ts CHANGED
@@ -15,5 +15,7 @@ export declare function doctor(opts?: {
15
15
  path?: string;
16
16
  argv1?: string;
17
17
  };
18
+ /** Override the local Codex model cache path (tests). */
19
+ codexCatalogPath?: string;
18
20
  }, exec?: Exec, platform?: NodeJS.Platform, fetchImpl?: FetchLike, attachDaemon?: AttachDoctorDaemon): Promise<PrereqReport>;
19
21
  export {};
package/dist/doctor.js CHANGED
@@ -13,6 +13,8 @@ import { authResolutionHint, resolveEndpoint, } from './monitor.js';
13
13
  import { readScheduledLoops, storedLoopHealth } from './loops/state.js';
14
14
  import { controlSocketPath } from './session/control.js';
15
15
  import { analyzeInstalls, buildInfo, buildLabel, discoverInstalls, BIN_NAME, } from './provenance.js';
16
+ import { readDaemonRecoveryStatus } from './daemon-recovery.js';
17
+ import { codexModelCatalog } from './application/model-catalog.js';
16
18
  /** Which cgroup-v2 controllers are delegated to this user manager (advisory). */
17
19
  function cgroupDelegationDetail() {
18
20
  try {
@@ -106,6 +108,35 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
106
108
  ok: true,
107
109
  detail: `warning: ${diagnostic.message}`,
108
110
  });
111
+ if (loaded.ok) {
112
+ const packaged = Object.entries(loaded.brainPresets ?? {}).flatMap(([id, brain]) => brain.harness === 'codex' && typeof brain.model === 'string' && typeof brain.effort === 'string'
113
+ ? [{ id, model: brain.model, effort: brain.effort }] : [])
114
+ .sort((a, b) => a.id.localeCompare(b.id));
115
+ if (packaged.length) {
116
+ const runtime = codexModelCatalog(opts.codexCatalogPath);
117
+ const available = new Set(runtime.models.flatMap(model => model.reasoningEfforts.map(effort => `${model.id}\0${effort}`)));
118
+ const missing = packaged.filter(({ model, effort }) => !available.has(`${model}\0${effort}`));
119
+ checks.push({ name: 'brain catalog: Codex runtime drift', ok: true,
120
+ detail: runtime.models.length
121
+ ? missing.length ? `warning: packaged Brain preset(s) absent from local Codex catalog: ${missing
122
+ .map(({ id, model, effort }) => `${id} (${model}/${effort})`).join(', ')}`
123
+ : `all ${packaged.length} packaged Codex model/effort pairs are present locally`
124
+ : runtime.warnings.join('; ') });
125
+ }
126
+ }
127
+ for (const role of roles) {
128
+ const recovery = readDaemonRecoveryStatus(agentDir(role.name));
129
+ if (!recovery)
130
+ continue;
131
+ const paths = ['agent', 'owner']
132
+ .map(name => `${name}=${recovery.paths[name].state}`)
133
+ .join(', ');
134
+ checks.push({
135
+ name: `daemon recovery: ${role.name}`,
136
+ ok: recovery.state === 'recovered',
137
+ detail: `${recovery.state}; ${paths}; epoch ${recovery.epoch || 'unavailable'}`,
138
+ });
139
+ }
109
140
  // ── Rooms/tasks checks ────────────────────────────────────────
110
141
  if (loaded.ok && loaded.rooms) {
111
142
  const rooms = loaded.rooms;
@@ -146,16 +177,16 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
146
177
  const { listTemplates, resolveTemplate } = await import('./rooms-tasks/templates.js');
147
178
  const customs = loaded.roomTemplates ?? {};
148
179
  const templates = listTemplates(customs);
149
- const roleNames = new Set(roles.map(r => r.name));
180
+ const agentTemplateNames = new Set(Object.keys(loaded.agentTemplates ?? {}));
150
181
  for (const t of templates) {
151
182
  const badRefs = t.members
152
- .filter(m => m.role_ref && !roleNames.has(m.role_ref))
153
- .map(m => m.role_ref);
183
+ .filter(m => !agentTemplateNames.has(m.agent_template))
184
+ .map(m => m.agent_template);
154
185
  if (badRefs.length) {
155
186
  checks.push({
156
187
  name: `template: ${t.name}@${t.version}`,
157
188
  ok: true,
158
- detail: `warning: role_ref(s) ${badRefs.join(', ')} not found in configured roles`,
189
+ detail: `warning: Agent Template(s) ${badRefs.join(', ')} not found`,
159
190
  });
160
191
  }
161
192
  }
@@ -513,6 +544,23 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
513
544
  : `${command} not found or failed — install the ACP adapter or set session_options.acp.command`,
514
545
  });
515
546
  }
547
+ for (const role of roles.filter(role => role.session === 'codex-app-server')) {
548
+ const configured = role.session_options?.codex_app_server?.command;
549
+ const launcher = role.harness_options?.launcher;
550
+ const command = Array.isArray(configured)
551
+ ? configured[0]
552
+ : typeof configured === 'string'
553
+ ? configured.trim().split(/\s+/)[0]
554
+ : launcher === 'ours-codex' ? 'ours-codex' : 'codex';
555
+ const result = await exec('sh', ['-c', 'command -v "$1" >/dev/null 2>&1', 'sh', command]);
556
+ checks.push({
557
+ name: `codex-app-server: ${role.name}`,
558
+ ok: result.code === 0,
559
+ detail: result.code === 0
560
+ ? `${command} available`
561
+ : `${command} not found — install Codex CLI or set session_options.codex_app_server.command`,
562
+ });
563
+ }
516
564
  return { ok: checks.every(c => c.ok), checks };
517
565
  }
518
566
  function loadConfigResult(configPath, yamlMode) {
@@ -521,6 +569,8 @@ function loadConfigResult(configPath, yamlMode) {
521
569
  return {
522
570
  ok: true, roles: cfg.roles, files: cfg.files, diagnostics: cfg.diagnostics,
523
571
  rooms: cfg.rooms, roomTemplates: cfg.roomTemplates, tasks: cfg.tasks,
572
+ agentTemplates: cfg.agentTemplates,
573
+ brainPresets: cfg.brainPresets,
524
574
  ownerInviteFingerprint: cfg.ownerInviteFingerprint,
525
575
  };
526
576
  }