@ours.network/fleet 1.1.0-nightly.9 → 1.1.1

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 (202) hide show
  1. package/README.md +285 -46
  2. package/dist/application/capabilities.js +18 -6
  3. package/dist/application/fleet-query-service.js +7 -4
  4. package/dist/application/role-command-service.js +9 -0
  5. package/dist/application/role-creation-service.d.ts +4 -4
  6. package/dist/application/role-creation-service.js +8 -1
  7. package/dist/application/role-repository.d.ts +4 -2
  8. package/dist/application/role-repository.js +6 -3
  9. package/dist/application/session-control.d.ts +3 -1
  10. package/dist/application/session-control.js +4 -2
  11. package/dist/application/task-room-service.d.ts +92 -39
  12. package/dist/application/task-room-service.js +562 -289
  13. package/dist/briefing.js +79 -22
  14. package/dist/build-info.json +5 -5
  15. package/dist/canonical-json.d.ts +2 -0
  16. package/dist/canonical-json.js +10 -0
  17. package/dist/cli.js +129 -47
  18. package/dist/config.d.ts +42 -3
  19. package/dist/config.js +202 -29
  20. package/dist/creation.d.ts +1 -1
  21. package/dist/creation.js +7 -4
  22. package/dist/docs.d.ts +1 -1
  23. package/dist/docs.js +195 -41
  24. package/dist/doctor.d.ts +2 -0
  25. package/dist/doctor.js +40 -4
  26. package/dist/fleet-command-audit.d.ts +22 -1
  27. package/dist/fleet-command-audit.js +355 -50
  28. package/dist/fleet-proxy.d.ts +5 -2
  29. package/dist/harness/claude-code-session.js +5 -1
  30. package/dist/harness/codex-app-server-proxy.d.ts +40 -0
  31. package/dist/harness/codex-app-server-proxy.js +348 -14
  32. package/dist/harness/codex-session.d.ts +9 -2
  33. package/dist/harness/codex-session.js +21 -2
  34. package/dist/harness/codex.d.ts +5 -1
  35. package/dist/harness/codex.js +104 -10
  36. package/dist/harness/types.d.ts +1 -1
  37. package/dist/index.d.ts +4 -3
  38. package/dist/index.js +3 -2
  39. package/dist/init-guidance.d.ts +1 -1
  40. package/dist/init-guidance.js +1 -1
  41. package/dist/init-wizard.d.ts +98 -0
  42. package/dist/init-wizard.js +631 -0
  43. package/dist/lifecycle-summary.d.ts +134 -0
  44. package/dist/lifecycle-summary.js +179 -0
  45. package/dist/loops/config.d.ts +10 -1
  46. package/dist/loops/config.js +38 -5
  47. package/dist/model-recovery.d.ts +1 -1
  48. package/dist/ops.js +2 -17
  49. package/dist/owner-channel/channel.d.ts +19 -3
  50. package/dist/owner-channel/channel.js +301 -120
  51. package/dist/owner-channel/commands.d.ts +28 -6
  52. package/dist/owner-channel/commands.js +109 -27
  53. package/dist/owner-channel/lifecycle-outbox.d.ts +24 -0
  54. package/dist/owner-channel/lifecycle-outbox.js +87 -0
  55. package/dist/owner-channel/ours-client.d.ts +19 -0
  56. package/dist/owner-channel/ours-client.js +3 -0
  57. package/dist/permissions.js +1 -1
  58. package/dist/preset-migration.d.ts +42 -0
  59. package/dist/preset-migration.js +450 -0
  60. package/dist/reports/artifact.d.ts +10 -0
  61. package/dist/reports/artifact.js +32 -0
  62. package/dist/reports/index.d.ts +5 -0
  63. package/dist/reports/index.js +5 -0
  64. package/dist/reports/render.d.ts +6 -0
  65. package/dist/reports/render.js +240 -0
  66. package/dist/reports/service.d.ts +42 -0
  67. package/dist/reports/service.js +57 -0
  68. package/dist/reports/tasks.d.ts +52 -0
  69. package/dist/reports/tasks.js +177 -0
  70. package/dist/reports/types.d.ts +315 -0
  71. package/dist/reports/types.js +6 -0
  72. package/dist/resolved-plan.js +13 -1
  73. package/dist/rooms-tasks/cli.d.ts +2 -0
  74. package/dist/rooms-tasks/cli.js +361 -285
  75. package/dist/rooms-tasks/close.d.ts +9 -1
  76. package/dist/rooms-tasks/close.js +23 -7
  77. package/dist/rooms-tasks/config.js +16 -25
  78. package/dist/rooms-tasks/cowork-adapter.d.ts +5 -0
  79. package/dist/rooms-tasks/cowork-adapter.js +13 -0
  80. package/dist/rooms-tasks/deletion.d.ts +51 -0
  81. package/dist/rooms-tasks/deletion.js +217 -0
  82. package/dist/rooms-tasks/external-worker.d.ts +8 -0
  83. package/dist/rooms-tasks/external-worker.js +38 -0
  84. package/dist/rooms-tasks/launch-snapshot.d.ts +19 -0
  85. package/dist/rooms-tasks/launch-snapshot.js +181 -0
  86. package/dist/rooms-tasks/member-overrides.d.ts +30 -0
  87. package/dist/rooms-tasks/member-overrides.js +204 -0
  88. package/dist/rooms-tasks/member-startup.d.ts +1 -0
  89. package/dist/rooms-tasks/member-startup.js +9 -2
  90. package/dist/rooms-tasks/provision.js +146 -83
  91. package/dist/rooms-tasks/room-state.d.ts +1 -0
  92. package/dist/rooms-tasks/room-state.js +12 -1
  93. package/dist/rooms-tasks/task-room-name.d.ts +12 -0
  94. package/dist/rooms-tasks/task-room-name.js +61 -0
  95. package/dist/rooms-tasks/task-state.d.ts +115 -3
  96. package/dist/rooms-tasks/task-state.js +361 -11
  97. package/dist/rooms-tasks/templates.d.ts +4 -1
  98. package/dist/rooms-tasks/templates.js +34 -3
  99. package/dist/rooms-tasks/terminal.d.ts +3 -0
  100. package/dist/rooms-tasks/terminal.js +10 -4
  101. package/dist/rooms-tasks/types.d.ts +92 -7
  102. package/dist/rooms-tasks/types.js +14 -1
  103. package/dist/runner.d.ts +3 -0
  104. package/dist/runner.js +97 -47
  105. package/dist/session/acp.d.ts +27 -1
  106. package/dist/session/acp.js +307 -17
  107. package/dist/session/arbiter.d.ts +2 -1
  108. package/dist/session/arbiter.js +2 -0
  109. package/dist/session/codex-app-server-transport.d.ts +53 -0
  110. package/dist/session/codex-app-server-transport.js +184 -0
  111. package/dist/session/codex-app-server.d.ts +122 -0
  112. package/dist/session/codex-app-server.js +1031 -0
  113. package/dist/session/control.d.ts +1 -1
  114. package/dist/session/control.js +17 -1
  115. package/dist/session/conversation-types.d.ts +4 -4
  116. package/dist/session/stall-watchdog.d.ts +60 -0
  117. package/dist/session/stall-watchdog.js +210 -0
  118. package/dist/session/types.d.ts +29 -8
  119. package/dist/session/types.js +28 -0
  120. package/dist/spawn.d.ts +9 -0
  121. package/dist/spawn.js +77 -9
  122. package/dist/web/fleet-config-service.d.ts +1 -0
  123. package/dist/web/fleet-config-service.js +25 -7
  124. package/dist/web/runtime.js +11 -6
  125. package/dist/web/server.js +28 -1
  126. package/dist/web-app/assets/{index-BbTc5KtZ.js → index-C0h3ALvs.js} +8 -8
  127. package/dist/web-app/index.html +1 -1
  128. package/package.json +4 -4
  129. package/presets/brain-catalog.json +17 -0
  130. package/presets/fleet/{agents → agent_templates}/Critic.yaml +2 -0
  131. package/presets/fleet/{agents/Agent.yaml → agent_templates/Developer.yaml} +3 -1
  132. package/presets/fleet/agent_templates/LocalCoordinator.yaml +50 -0
  133. package/presets/fleet/agents/{Developer.yaml → FleetCoordinator.yaml} +1 -1
  134. package/presets/fleet/brains/claude-fable-5-high.yaml +5 -0
  135. package/presets/fleet/brains/claude-fable-5-low.yaml +5 -0
  136. package/presets/fleet/brains/claude-fable-5-max.yaml +5 -0
  137. package/presets/fleet/brains/claude-fable-5-medium.yaml +5 -0
  138. package/presets/fleet/brains/claude-fable-5-xhigh.yaml +5 -0
  139. package/presets/fleet/brains/claude-opus-5-high.yaml +5 -0
  140. package/presets/fleet/brains/claude-opus-5-low.yaml +5 -0
  141. package/presets/fleet/brains/claude-opus-5-max.yaml +5 -0
  142. package/presets/fleet/brains/claude-opus-5-medium.yaml +5 -0
  143. package/presets/fleet/brains/claude-opus-5-xhigh.yaml +5 -0
  144. package/presets/fleet/brains/claude-sonnet-5-high.yaml +5 -0
  145. package/presets/fleet/brains/claude-sonnet-5-low.yaml +5 -0
  146. package/presets/fleet/brains/claude-sonnet-5-max.yaml +5 -0
  147. package/presets/fleet/brains/claude-sonnet-5-medium.yaml +5 -0
  148. package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +5 -0
  149. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +5 -0
  150. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +5 -0
  151. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +5 -0
  152. package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +5 -0
  153. package/presets/fleet/brains/codex-gpt-5-4-high.yaml +5 -0
  154. package/presets/fleet/brains/codex-gpt-5-4-low.yaml +5 -0
  155. package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +5 -0
  156. package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +5 -0
  157. package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +5 -0
  158. package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +5 -0
  159. package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +5 -0
  160. package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +5 -0
  161. package/presets/fleet/brains/codex-gpt-5-5-high.yaml +5 -0
  162. package/presets/fleet/brains/codex-gpt-5-5-low.yaml +5 -0
  163. package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +5 -0
  164. package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +5 -0
  165. package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +5 -0
  166. package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +5 -0
  167. package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +5 -0
  168. package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +5 -0
  169. package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +5 -0
  170. package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +5 -0
  171. package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +5 -0
  172. package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +5 -0
  173. package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +5 -0
  174. package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +5 -0
  175. package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +5 -0
  176. package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +5 -0
  177. package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +5 -0
  178. package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +5 -0
  179. package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +5 -0
  180. package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +5 -0
  181. package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +5 -0
  182. package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +5 -0
  183. package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +5 -0
  184. package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +5 -0
  185. package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +5 -0
  186. package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +5 -0
  187. package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +5 -0
  188. package/presets/fleet/roles/Coordinator.yaml +37 -0
  189. package/presets/fleet/roles/Critic.yaml +23 -1
  190. package/presets/fleet/roles/Developer.yaml +27 -5
  191. package/presets/fleet/roles/LocalCoordinator.yaml +35 -0
  192. package/presets/fleet/room_templates/pair.yaml +9 -7
  193. package/presets/fleet/room_templates/single.yaml +5 -4
  194. package/presets/fleet/room_templates/team.yaml +12 -8
  195. package/presets/manifest.json +2 -1
  196. package/presets/fleet/agents/Architect.yaml +0 -3
  197. package/presets/fleet/agents/Secretary.yaml +0 -3
  198. package/presets/fleet/agents/Tester.yaml +0 -3
  199. package/presets/fleet/roles/Agent.yaml +0 -6
  200. package/presets/fleet/roles/Architect.yaml +0 -6
  201. package/presets/fleet/roles/Secretary.yaml +0 -6
  202. package/presets/fleet/roles/Tester.yaml +0 -6
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,24 @@ 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\`, \`~/fleet/brains\`, and
27
+ stem directories \`~/fleet/agents\`, \`~/fleet/agent_templates\`, \`~/fleet/roles\`, \`~/fleet/brains\`, and
28
28
  \`~/fleet/room_templates\`.
29
29
  The manifest owns fleet-wide operational defaults and automation; each Agent
30
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.
34
+ An Agent Template may declare up to 64 temporary-only named \`loops\`; persistent Agent
35
+ instances reject them. Each loop requires \`interval\` (1m..30d) and bounded
36
+ nonblank \`prompt\`, with optional \`enabled\` (default true), \`initial_delay\`
37
+ (default interval, 0s..30d), and \`jitter\` (default 0s, < interval, <=1h).
38
+ Execution is fixed skip-if-busy with no ordinary missed-tick backlog/replay;
39
+ restart recovery may preserve at most one recent late occurrence.
31
40
  Legacy top-level \`roles:\` and \`fleet.d\` are rejected. Validate the complete
32
41
  trusted source set with \`config\` and \`doctor\` before starting or restarting.
33
42
 
34
43
  Permanent \`spawn\` writes \`~/fleet/agents/Name.yaml\`. The web console edits an
35
- explicit \`{manifest, agents}\` model while Role/Brain presets remain read-only.
44
+ explicit \`{manifest, agents, agent_templates}\` model while Role/Brain presets remain read-only.
36
45
  Its aggregate revision includes every Agent/Role/Brain/Room-template source, previews a
37
46
  redacted per-document diff in an exact-stem private staging tree, and saves under
38
47
  one root lock with a private multi-file backup and full rollback. A no-op is
@@ -79,7 +88,7 @@ PATH order.
79
88
  ## Lifecycle and console commands
80
89
 
81
90
  \`\`\`sh
82
- ours-fleet init [-c FILE] # seed missing presets; never replace an existing file
91
+ ours-fleet init [-c FILE] # interactive missing-default seed; TTY required
83
92
  ours-fleet up|down [Name...]
84
93
  ours-fleet restart [Name...] # preserve/resume harness context
85
94
  ours-fleet force-restart [Name...] # fresh context; briefing is reloaded
@@ -92,6 +101,27 @@ ours-fleet watchdog-report <name> [run-id] [--list] [--json]
92
101
  ours-fleet watchdog-run <name>
93
102
  \`\`\`
94
103
 
104
+ \`init\` is an interactive missing-default workflow that preserves existing files byte-for-byte.
105
+ It names the resolved manifest and split directory, asks a default-No confirmation,
106
+ then subscriptions (Codex, Claude, or both), model assignment (one explicit model for
107
+ every job or explicit development/review/coordination choices), one reasoning level,
108
+ and a final default-No review. Quick/Balanced/Thorough generate low/medium/high.
109
+ Model pickers show packaged supported IDs; catalog membership is not a recommendation
110
+ or entitlement claim. Run \`ours-fleet doctor\` for local Codex availability; Claude
111
+ entitlement is checked when a role launches. The generated brains contain no
112
+ \`model_chain\`, so Fleet never silently substitutes another model.
113
+
114
+ At either confirmation, N, Enter, Escape, Ctrl-C, Ctrl-D, or EOF cancels. In a picker,
115
+ Escape, Ctrl-C, Ctrl-D, or EOF cancels; Enter records the highlight or continues a
116
+ non-empty multi-select, N is ignored, and an empty subscription selection remains blocked.
117
+ Every cancellation before final approval performs no host or configuration mutation.
118
+ Redirected/non-TTY invocation is refused with the same guarantee. After the final Yes,
119
+ host setup precedes publication. Path ownership/type/mode/symlink and
120
+ same-filesystem checks run before host setup and again under a per-setup lock. Publication
121
+ stages and validates the complete combined setup, backs up whichever old target(s) exist,
122
+ and retains a private recovery record. A hard process/host termination cannot promise
123
+ rollback; inspect host integration and private init stage/recovery evidence.
124
+
95
125
  \`peek\`, \`attach\`, and text \`send\` use the structured agent session.
96
126
  Attachment also accepts \`/permit <permission-id> <option-id>\`, \`/interrupt\`,
97
127
  and \`/detach\`.
@@ -162,7 +192,7 @@ Permanent spawn writes \`~/fleet/agents/Name.yaml\` and starts a supervised role
162
192
  \`--temp\` writes active state under \`~/.ours-fleet/tmp\` and starts an independent
163
193
  transient supervisor (a collected systemd unit or submitted launchd job). It is
164
194
  not enabled across reboot and does not die when the role that spawned it restarts.
165
- Brain definitions own the ACP session backend. When a temporary role's bound identity
195
+ Brain definitions own the managed session backend. When a temporary role's bound identity
166
196
  closes or its session ends, the supervisor, monitor and live roster entry retire
167
197
  together; state moves intact to \`~/.ours-fleet/recovery/temporary\` with a
168
198
  termination record. Failed launches use the same archive rather than deleting
@@ -194,7 +224,7 @@ only sustained authoritative absence closes the role. Unreachable, malformed, or
194
224
  valid-but-empty daemon indexes are ambiguous and reset closure debounce rather
195
225
  than becoming cleanup authority.
196
226
 
197
- Inside a managed ACP role, public \`ours-fleet\` commands cross an authenticated
227
+ Inside a managed role, public \`ours-fleet\` commands cross an authenticated
198
228
  supervisor attribution boundary before Commander parsing. The original CLI remains
199
229
  the executor inside the role's existing OS sandbox, and ordinary CLI validation is
200
230
  the source of truth. Hidden worker entry points remain internal; public lifecycle and
@@ -221,6 +251,26 @@ Brain owns harness, session, model, reasoning effort, token limits, and native h
221
251
  options. Removed runtime flags are rejected with migration guidance rather than silently
222
252
  reinterpreted. A selection is a stable ID or an explicit \`inline:{...}\` mapping.
223
253
 
254
+ Packaged Developer, Critic, and LocalCoordinator Agent Templates set
255
+ \`monitor: { mode: fleet, interrupt: after_tool }\`. Every member of the standard
256
+ \`single\`, \`pair\`, and \`team\` Room Templates therefore resolves to fleet-owned,
257
+ after-tool delivery. Explicit per-member and custom Agent Template values remain
258
+ authoritative and merge key by key.
259
+
260
+ Managed ACP stall recovery is opt-in: \`monitor: { mode: fleet, stall_recovery: true,
261
+ stall_timeout_ms: 900000 }\`. The validated timeout is 60000–86400000 milliseconds.
262
+ Omitted/false preserves existing behavior. Silence is measured from meaningful live
263
+ progress; replay and retry chatter do not reset it. Strong authenticated retry
264
+ evidence requires one window, generic silence two. Tools, permissions, modal or
265
+ unknown boundaries, steering and human cancellation protect the turn. Recovery
266
+ uses one bounded cancel and diagnostic continuation in the same ACP session/queue
267
+ slot; it never restarts the adapter. Startup and queued mail wait behind recovery.
268
+ A durable claim permits at most one automatic attempt per ACP session ID, including
269
+ across supervisor restarts; later mail is non-cancelling. Failed or re-stalled
270
+ recovery reports a blocker. Inspect \`.stall-recovery/audit.jsonl\` and recorded
271
+ terminal events before continuing; never replay ambiguous or completed mutations.
272
+ Native monitoring/non-ACP sessions are unchanged. No room or identity coupling.
273
+
224
274
  ## fleet.yaml
225
275
 
226
276
  \`\`\`yaml
@@ -254,7 +304,7 @@ An Agent is a separate bare document under \`~/fleet/agents/<ID>.yaml\`:
254
304
 
255
305
  \`\`\`yaml
256
306
  role: { inline: { mission: Coordinate work and delegate implementation. } }
257
- brain: { inline: { harness: codex, session: acp, model: gpt-model-id } }
307
+ brain: { inline: { harness: codex, session: codex-app-server, model: gpt-model-id } }
258
308
  identity: Coordinator
259
309
  cwd: \${work_root}/project
260
310
  oversee: [{ agent: Worker, interval: 5m }]
@@ -294,14 +344,46 @@ ours-fleet template show team [-c FILE]
294
344
  ours-fleet task create --title "Solo task" --template single [-c FILE]
295
345
  ours-fleet task create --title "Reviewed change" --template pair [-c FILE]
296
346
  ours-fleet task create --title "Phased delivery" --template team [-c FILE]
347
+ ours-fleet spawn --temp Scout --role SELECTION --brain SELECTION --loops-file PRIVATE.yaml
348
+ ours-fleet task start TASK --member developer --loops-file PRIVATE.yaml
349
+ ours-fleet task start TASK --member critic --no-loops
297
350
  \`\`\`
298
351
 
352
+ \`--loops-file\` must be an owner-only, non-symlink regular file <=1 MB containing
353
+ exactly one top-level non-empty \`loops:\` mapping. \`--no-loops\` explicitly
354
+ disables loops. They are mutually exclusive and rejected for permanent spawn.
355
+ For a grouped room member the whole CLI block overrides its Agent Template;
356
+ the template overrides omission. Omission preserves historical no-loop behavior
357
+ and never inherits manifest wildcard loops. Fleet validates before side effects,
358
+ seals normalized timings plus exact private prompts, and reuses that snapshot for
359
+ idempotent start, retry, recovery, and replacement. Trusted authoring and the
360
+ private sealed runtime retain exact prompts; resolved launch, task, room,
361
+ provenance, and audit presentations show source, policy, timing, prompt bytes,
362
+ and prompt SHA-256 instead of prompt text.
363
+
299
364
  An alternate manifest \`-c /path/custom.yaml\` uses \`/path/custom/\` as its split
300
365
  root. Repeated init only fills missing files and never adopts a newer default.
301
- For explicit adoption, copy one file from init's reported packaged source beside
302
- the target as \`.new-default\`, inspect \`diff -u TARGET TARGET.new-default\`, then
303
- replace TARGET yourself. Upgrades from hardcoded templates require one
304
- \`ours-fleet init\` (or \`init -c FILE\`) migration pass. A manifest-level template
366
+ Exact known revision-3 through revision-5 packaged-bootstrap and generated role defaults have an exact-semantic,
367
+ fail-closed migration (dry-run by default):
368
+
369
+ \`ours-fleet migrate-role-defaults [-c FILE]\`
370
+ \`ours-fleet migrate-role-defaults [-c FILE] --write\`
371
+
372
+ Review removals, replacements, additions, preserved custom files, staging path,
373
+ and recovery path. Same-named custom files stay byte-identical; dangling custom
374
+ references refuse publication, and a successful rerun is a no-op. For explicit
375
+ single-file adoption, copy from init's reported packaged source beside the target
376
+ as \`.new-default\`, inspect \`diff -u TARGET TARGET.new-default\`, then replace it.
377
+
378
+ The exact generated six-worker legacy starter Agent set has its own fail-closed
379
+ migration (dry-run by default):
380
+
381
+ \`ours-fleet migrate-agent-templates [-c FILE]\`
382
+ \`ours-fleet migrate-agent-templates [-c FILE] --write\`
383
+
384
+ Review the dry-run moves, addition, staging path, and retained recovery-backup path
385
+ before \`--write\`. Customized/partial known starters and unsafe trees refuse without
386
+ mutation; unrelated custom persistent Agents remain persistent. A manifest-level template
305
387
  may shadow a same-named file only with \`override_builtin: true\` and a higher
306
388
  version; this compatibility marker is deprecated and reported as a diagnostic.
307
389
 
@@ -329,8 +411,37 @@ Fleet launches each template member with a dedicated one-time Cowork invite.
329
411
  The generated temporary-agent briefing contains the exact identity name, invite,
330
412
  Cowork role, and task. The agent creates that identity itself with ours MCP
331
413
  \`create_temporary_identity\`, accepts the invite with \`add_contact\`, and starts
332
- work immediately. Fleet activates the room from Cowork's authenticated seat; there
333
- is no briefing hash, startup ACK, or separate role-briefing readiness gate.
414
+ work immediately. A room is ready only after the Cowork room (and its task, when
415
+ task-bound) is durably active, every configured member seat is authenticated and active with its matching
416
+ live Fleet launch, and the configured Owner seat is active when owner attachment is
417
+ enabled. There is no briefing hash, startup ACK, or separate role-briefing readiness
418
+ gate.
419
+
420
+ Normal Task provisioning emits exactly one authenticated Owner lifecycle notice after
421
+ the ready predicate above is true; standalone Room provisioning likewise emits one
422
+ ready notice. Intermediate task, saga, member-spawn, timeout, and recoverable-failure
423
+ transitions stay in local state and logs. A terminal failed Task emits one actionable
424
+ failure notice; the command result carries the exact blocker and canonical recovery
425
+ action.
426
+
427
+ \`task start\` and create-and-start wait for readiness. If their bounded wait expires,
428
+ they return an explicit \`in_progress\` result and start a safe continuation. The detached
429
+ continuation is serialized per Task and remains alive until convergence or an
430
+ Owner-action blocker. Re-running \`task start <id>\` safely resumes the same durable
431
+ provisioning operation after the blocker is corrected or a process restarts.
432
+
433
+ Set \`room.anonymous: true\` on a room template, or pass \`--anonymous\` to
434
+ \`task create\`, \`task start\`, \`task work\`, or \`room create\`, to create an
435
+ anonymous Cowork room. \`--no-anonymous\` explicitly overrides an anonymous
436
+ template. Fleet records the resolved value before room creation so retries keep
437
+ the same choice. Temporary members of an anonymous room are instructed to call
438
+ \`create_temporary_identity\` with \`expose_local=false\`. Their generated briefings
439
+ do not disclose or compare an Owner participant CID. A participant-originated
440
+ instruction has Owner authority only when the authenticated Cowork room envelope
441
+ attributes that participant seat the exact \`Owner\` role. Literal text, display
442
+ names, ordinary direct messages, and room-authored or rest-role messages with an
443
+ Owner-looking label never grant that authority. Non-anonymous rooms remain pinned
444
+ to the exact authenticated Owner CID.
334
445
 
335
446
  Human task and room results use the same compact Markdown presentation in the
336
447
  CLI and authenticated owner channel: a short heading, icon-plus-word status,
@@ -380,11 +491,24 @@ The prerelease configuration names \`tasks.close_room_on_done\` and
380
491
  semantics. Older prerelease \`closed\` room records are deleted directly the next
381
492
  time \`room list\` reconciles Fleet with Cowork.
382
493
 
383
- \`ours-fleet task delete <id> <id>\` removes only a \`done\` task's Fleet backlog
384
- record. The exact task ID is required twice for confirmation. Delete rejects every
385
- other task state, never changes any room state, and reports an already-missing
386
- task as an idempotent no-op. The Owner-channel equivalent is
387
- \`/task delete <id> <id>\`.
494
+ \`ours-fleet task delete <id> <id>\` permanently deletes a task in ANY lifecycle
495
+ state — backlog, provisioning, active, blocked, review, done, cancelled, failed,
496
+ or partially settled. The exact task ID is required twice for confirmation. A
497
+ durable deletion intent is persisted before any side effect; the cleanup worker
498
+ then retires managed room members with evidence, closes and deletes an attached
499
+ room (tolerating already-missing remote rooms), releases the sealed launch
500
+ snapshot, and unlinks the task record last. While cleanup settles the task is
501
+ hidden from normal listings and every lifecycle mutation is rejected; if
502
+ cleanup cannot complete (for example Cowork is unreachable), the deletion stays
503
+ in a precise resumable state — repeat the identical delete command to converge
504
+ after outages, crashes, or restarts. Deletion
505
+ never fabricates a \`done\` transition. A metadata-only deletion receipt
506
+ (acceptance actor, original state, timestamps, completion) is retained under
507
+ \`deletion-receipts/\` as durable audit evidence. An already-missing task is an
508
+ idempotent no-op. The Owner-channel equivalent is \`/task delete <id> <id>\`; the
509
+ management API equivalent is \`DELETE /api/v1/tasks/<id>?confirm=<id>\` (200 when
510
+ settled, 202 while pending; \`GET /api/v1/tasks?includeDeleting=true\` exposes
511
+ deletion-pending tasks to operators).
388
512
 
389
513
  ## Permissions
390
514
 
@@ -393,12 +517,13 @@ Prefer the harness-neutral \`permissions\` block:
393
517
  - \`approval: ask|auto|allow\`: portable permission policy. \`deny\` remains a
394
518
  deprecated, fail-closed compatibility alias for existing fleet files.
395
519
  - \`filesystem: read-only|workspace|unrestricted\`: filesystem intent
396
- - \`unattended: deny|wait\`: what ACP does when no console can answer a request
520
+ - \`unattended: deny|wait\`: what a managed session does when no console can
521
+ answer a request
397
522
 
398
- The backend translates this common intent. Harness-native settings in
399
- \`harness_options\` take precedence where supplied. Do not choose
400
- \`allow\`/\`unrestricted\`, Codex \`never\`/\`danger-full-access\`, or Claude
401
- \`bypassPermissions\` without explicit authorization.
523
+ The backend translates this common intent. Native Codex app-server roles reject
524
+ permission aliases in \`harness_options\`; Codex ACP and Claude retain their
525
+ legacy native-override compatibility. Do not choose \`allow\`/\`unrestricted\`
526
+ or Claude \`bypassPermissions\` without explicit authorization.
402
527
 
403
528
  ### Creation-time isolation
404
529
 
@@ -471,12 +596,14 @@ permissions through its harness and check the result against a fixed floor:
471
596
  deny those requests with nobody to see it; with \`unattended: wait\` it warns,
472
597
  because a human can still attach and answer.
473
598
 
474
- Security meaning: \`ask\` maps to Codex \`untrusted\` and Claude \`default\`.
475
- \`auto\` selects Codex ACP \`agent\` (\`on-request\` + \`workspace-write\`) and
476
- Claude \`acceptEdits\`. \`approval: allow\` selects Codex ACP's fully
477
- non-interactive yolo mode, reported as \`agent-full-access\` (\`never\` +
478
- \`danger-full-access\`), and Claude \`bypassPermissions\`. These modes genuinely
479
- permit the actions the role was authorized to take —
599
+ Security meaning: native Codex maps \`ask\` → \`untrusted\`, \`auto\` →
600
+ \`on-request\`, and \`allow\` → \`never\`; its independent filesystem mapping is
601
+ \`read-only\` → \`read-only\`, \`workspace\` → \`workspace-write\`, and
602
+ \`unrestricted\` → \`danger-full-access\`. Users configure only the Fleet names.
603
+ Claude maps \`ask\` to \`default\`, \`auto\` to \`acceptEdits\`, and \`allow\` to
604
+ \`bypassPermissions\`. Codex ACP retains its adapter-specific coupled modes:
605
+ \`auto\` selects \`agent\`, while \`allow\` selects \`agent-full-access\`. These
606
+ modes genuinely permit the actions the role was authorized to take —
480
607
  \`dontAsk\` only suppresses the prompt while still refusing the action. Nothing
481
608
  other than an explicit \`allow\` becomes non-interactive. Legacy \`deny\` keeps
482
609
  its conservative Codex \`on-request\` / Claude \`plan\` translation. \`allow\` is therefore a real grant and
@@ -531,10 +658,31 @@ refused at validation rather than accepted and dropped. This narrows a role's
531
658
  tool surface; it does not stop the harness deferring tool schemas, which is the
532
659
  harness's own decision.
533
660
 
534
- Codex \`harness_options\`: \`launcher\` (auto, ours-codex, codex), \`sandbox\`
535
- (read-only, workspace-write, danger-full-access), \`approval\` or
536
- \`permission_mode\` (untrusted, on-request, never), \`profile\`, \`search\`,
537
- \`config\`, \`add_dirs\`, and \`monitor\`.
661
+ Codex \`harness_options\`: \`launcher\` (auto, ours-codex, codex), \`search\`,
662
+ \`config\`, \`add_dirs\`, and \`monitor\`; Codex ACP additionally supports
663
+ \`profile\`. Native app-server roles reject \`profile\` because Codex does not
664
+ accept \`--profile\` for \`app-server\`. They
665
+ must express approval and filesystem authority through the shared
666
+ \`permissions:\` block, never through harness options. The adapter translates
667
+ \`ask|auto|allow\` to Codex \`untrusted|on-request|never\` and translates
668
+ \`read-only|workspace|unrestricted\` to Codex
669
+ \`read-only|workspace-write|danger-full-access\`. Native \`config\` currently
670
+ allows only \`model_reasoning_effort\`; ACP retains the broader Codex config surface.
671
+
672
+ For Codex, the opt-in \`session: codex-app-server\` directly runs Codex's native
673
+ JSONL app server behind Fleet's provider-neutral session contract. It supports native item
674
+ streaming, commentary/final phases, prompt admission, steering, interruption,
675
+ permission requests, durable conversation projection, and thread resume. Packaged
676
+ Codex brains and the init wizard continue to select \`session: acp\` for compatibility;
677
+ Claude Code also uses ACP. Native Codex defaults to \`codex app-server\` (or \`ours-codex app-server\`
678
+ when launcher auto finds it). Override the exact command when necessary:
679
+
680
+ \`session_options: { codex_app_server: { command: [codex, app-server] } }\`
681
+
682
+ An exact command override receives no appended profile, search, or subcommand
683
+ arguments. Native sessions persist their Codex thread in Fleet's \`.session-id\`
684
+ and participate in its bounded fresh/resume recovery; cross-provider conversation
685
+ portability is never assumed.
538
686
 
539
687
  ## ACP adapters
540
688
 
@@ -542,8 +690,7 @@ The maintained \`@agentclientprotocol/codex-acp\` and
542
690
  \`@agentclientprotocol/claude-agent-acp\` runtimes are bundled automatically as
543
691
  optional ours-fleet dependencies. The supervisor resolves their executable
544
692
  entrypoints internally, so default ACP roles do not depend on global PATH.
545
- The maintained Claude adapter requires Node 22; Codex ACP continues to work on
546
- the ours-fleet core minimum of Node 20.
693
+ ours-fleet and both maintained adapters require Node 22 or newer.
547
694
 
548
695
  Override an adapter only when necessary with \`session_options.acp.command\`
549
696
  (string or argv list). If optional dependencies were deliberately omitted,
@@ -587,7 +734,7 @@ Inspect \`ours-fleet status Name\`, \`peek Name\`, role logs, and
587
734
 
588
735
  ## Trusted owner channel
589
736
 
590
- An ACP role may declare a separate ours identity which fleet — never the agent —
737
+ Any managed role may declare a separate ours identity which fleet — never the agent —
591
738
  creates when missing and binds:
592
739
 
593
740
  \`\`\`yaml
@@ -640,6 +787,13 @@ adapter executes them locally (claude-code: all three; codex: \`/compact\`
640
787
  only) and are otherwise refused with a notice, so slash text never reaches the
641
788
  model as a prompt.
642
789
 
790
+ The supervisor advertises the same primary registry entries as recipient-scoped
791
+ ours typed commands. Their single arguments field is converted back to the text
792
+ after the slash command name and enters the same dispatcher; aliases stay
793
+ slash-only. Typed handlers repeat the live authenticated Owner-CID check before
794
+ dispatch and return a null protocol completion because the existing correlated
795
+ owner-channel reply remains the result.
796
+
643
797
  While a request runs, the agent's live ACP commentary is relayed as messages
644
798
  prefixed with the single stable label \`🟡 Live update:\`, so an owner can see
645
799
  exactly which messages the setting controls. \`owner_channel.comments\`
@@ -688,12 +842,12 @@ provenance checks.
688
842
  The channel identity must be unique and must not be a role identity. The bridge
689
843
  persists bounded wire IDs only, never message/reply plaintext, and requeues input
690
844
  before starting its turn for at-least-once crash recovery. It currently requires
691
- the structured agent-session interface backed by ACP so correlated final replies
692
- retain their delivery guarantee.
845
+ the structured agent-session interface so correlated final replies retain their
846
+ delivery guarantee.
693
847
 
694
848
  ### Live contact and owner administration
695
849
 
696
- The supervisor which is already running the ACP role remains the sole binder of
850
+ The supervisor which is already running the managed role remains the sole binder of
697
851
  \`owner_channel.identity\`. The CLI reaches that exact live \`OwnerChannel\`
698
852
  through the role's token-authenticated, mode-0600 Unix control socket for contact
699
853
  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
@@ -14,6 +14,7 @@ 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
16
  import { readDaemonRecoveryStatus } from './daemon-recovery.js';
17
+ import { codexModelCatalog } from './application/model-catalog.js';
17
18
  /** Which cgroup-v2 controllers are delegated to this user manager (advisory). */
18
19
  function cgroupDelegationDetail() {
19
20
  try {
@@ -107,6 +108,22 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
107
108
  ok: true,
108
109
  detail: `warning: ${diagnostic.message}`,
109
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
+ }
110
127
  for (const role of roles) {
111
128
  const recovery = readDaemonRecoveryStatus(agentDir(role.name));
112
129
  if (!recovery)
@@ -160,16 +177,16 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
160
177
  const { listTemplates, resolveTemplate } = await import('./rooms-tasks/templates.js');
161
178
  const customs = loaded.roomTemplates ?? {};
162
179
  const templates = listTemplates(customs);
163
- const roleNames = new Set(roles.map(r => r.name));
180
+ const agentTemplateNames = new Set(Object.keys(loaded.agentTemplates ?? {}));
164
181
  for (const t of templates) {
165
182
  const badRefs = t.members
166
- .filter(m => 'ref' in m.agent && !roleNames.has(m.agent.ref))
167
- .map(m => 'ref' in m.agent ? m.agent.ref : '');
183
+ .filter(m => !agentTemplateNames.has(m.agent_template))
184
+ .map(m => m.agent_template);
168
185
  if (badRefs.length) {
169
186
  checks.push({
170
187
  name: `template: ${t.name}@${t.version}`,
171
188
  ok: true,
172
- detail: `warning: Agent ref(s) ${badRefs.join(', ')} not found in configured Agents`,
189
+ detail: `warning: Agent Template(s) ${badRefs.join(', ')} not found`,
173
190
  });
174
191
  }
175
192
  }
@@ -527,6 +544,23 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
527
544
  : `${command} not found or failed — install the ACP adapter or set session_options.acp.command`,
528
545
  });
529
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
+ }
530
564
  return { ok: checks.every(c => c.ok), checks };
531
565
  }
532
566
  function loadConfigResult(configPath, yamlMode) {
@@ -535,6 +569,8 @@ function loadConfigResult(configPath, yamlMode) {
535
569
  return {
536
570
  ok: true, roles: cfg.roles, files: cfg.files, diagnostics: cfg.diagnostics,
537
571
  rooms: cfg.rooms, roomTemplates: cfg.roomTemplates, tasks: cfg.tasks,
572
+ agentTemplates: cfg.agentTemplates,
573
+ brainPresets: cfg.brainPresets,
538
574
  ownerInviteFingerprint: cfg.ownerInviteFingerprint,
539
575
  };
540
576
  }
@@ -1,3 +1,5 @@
1
+ import { type AgentLaunchConfiguration } from './lifecycle-summary.js';
2
+ import type { SessionBackendId } from './config.js';
1
3
  export type FleetCommandDecision = 'allow' | 'deny' | 'unsupported';
2
4
  export type FleetCommandOutcomeClass = 'success' | 'validation' | 'denied' | 'runtime' | 'timeout' | 'proxy' | 'delivery';
3
5
  export declare class FleetCliExit extends Error {
@@ -15,12 +17,13 @@ export type FleetAuditPresentation = {
15
17
  brain: string;
16
18
  role: string;
17
19
  harness: string;
18
- session: 'acp';
20
+ session: SessionBackendId;
19
21
  model?: string;
20
22
  permissions?: string;
21
23
  parent: string;
22
24
  actionId: string;
23
25
  inherited: string[];
26
+ configuration?: AgentLaunchConfiguration;
24
27
  } | {
25
28
  kind: 'task';
26
29
  operation: 'create' | 'start' | 'work' | 'block' | 'unblock' | 'review' | 'done' | 'cancel' | 'finish' | 'delete' | 'settling';
@@ -31,6 +34,8 @@ export type FleetAuditPresentation = {
31
34
  newState: string;
32
35
  template?: string;
33
36
  roomId?: string;
37
+ roomName?: string;
38
+ reason?: string;
34
39
  revision?: string;
35
40
  list?: string;
36
41
  agents: Array<{
@@ -38,6 +43,7 @@ export type FleetAuditPresentation = {
38
43
  brain?: string;
39
44
  role: string;
40
45
  permissions?: string;
46
+ configuration?: AgentLaunchConfiguration;
41
47
  }>;
42
48
  } | {
43
49
  kind: 'room';
@@ -50,18 +56,23 @@ export type FleetAuditPresentation = {
50
56
  name?: string;
51
57
  template?: string;
52
58
  taskId?: string;
59
+ anonymous?: boolean;
60
+ memberCount?: number;
61
+ ownerAttached?: boolean;
53
62
  participants: Array<{
54
63
  name: string;
55
64
  id?: string;
56
65
  brain?: string;
57
66
  role: string;
58
67
  permissions?: string;
68
+ configuration?: AgentLaunchConfiguration;
59
69
  }>;
60
70
  } | {
61
71
  kind: 'lifecycle_failure';
62
72
  eventId: string;
63
73
  resource: 'Agent' | 'Task' | 'Room';
64
74
  id: string;
75
+ label?: string;
65
76
  state: string;
66
77
  category: 'provision_failed' | 'provision_pending' | 'readiness_failed' | 'settlement_failed' | 'settlement_pending' | 'cleanup_failed' | 'cleanup_pending';
67
78
  };
@@ -70,10 +81,19 @@ export declare const FLEET_LIFECYCLE_EVENT_KINDS: readonly ["agent_started", "ta
70
81
  /** Stable semantic dedupe basis: resource kind + stable resource ID + transition/action ID. */
71
82
  export declare function lifecycleEventDigestBasis(value: FleetAuditPresentation): string;
72
83
  export declare function beginFleetAuditCollection(): void;
84
+ export declare function setFleetAuditLifecycleCheckpoint(checkpoint: ((presentations: FleetAuditPresentation[]) => Promise<void>) | undefined): void;
85
+ /**
86
+ * Deliver already-recorded lifecycle events while a managed command is still
87
+ * running. On a failed checkpoint the events remain in the final audit batch,
88
+ * so a temporary Owner-channel outage loses timing, never the notice itself.
89
+ */
90
+ export declare function checkpointFleetAuditPresentations(): Promise<void>;
73
91
  export declare function recordFleetAuditResource(kind: 'agent' | 'task' | 'room', id: string | undefined): void;
74
92
  type FleetAuditPresentationInput = FleetAuditPresentation extends infer T ? T extends FleetAuditPresentation ? Omit<T, 'eventId'> & {
75
93
  eventId?: string;
76
94
  } : never : never;
95
+ /** Immutable, single-line human label captured before mutable Task/Room state can disappear. */
96
+ export declare function fleetPresentationLabel(value: unknown): string | undefined;
77
97
  export declare function recordFleetAuditPresentation(value: FleetAuditPresentationInput): void;
78
98
  export declare function recordFleetAuditFailure(failure: {
79
99
  class: FleetCommandOutcomeClass;
@@ -155,6 +175,7 @@ export declare function validateFleetAuditFinish(value: unknown): asserts value
155
175
  resourceIds?: Record<string, string>;
156
176
  presentations?: FleetAuditPresentation[];
157
177
  };
178
+ export declare function validateFleetAuditPresentations(value: unknown): asserts value is FleetAuditPresentation[];
158
179
  /** Compact Owner presentation. It intentionally has no command, argv, environment, or correlation data. */
159
180
  export declare function renderFleetLifecycleEvent(value: FleetAuditPresentation): string;
160
181
  export {};