@ours.network/fleet 1.0.5 → 1.1.0-nightly.10
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.
- package/README.md +122 -133
- package/dist/agent-recovery-gate.d.ts +17 -0
- package/dist/agent-recovery-gate.js +135 -0
- package/dist/application/capabilities.d.ts +0 -1
- package/dist/application/capabilities.js +3 -13
- package/dist/application/fleet-query-service.d.ts +0 -3
- package/dist/application/fleet-query-service.js +14 -25
- package/dist/application/role-creation-service.d.ts +5 -24
- package/dist/application/role-creation-service.js +27 -67
- package/dist/application/role-removal-service.js +6 -3
- package/dist/application/role-repository.d.ts +1 -2
- package/dist/application/role-repository.js +7 -7
- package/dist/application/session-control.d.ts +0 -12
- package/dist/application/session-control.js +0 -42
- package/dist/application/session-mutations.d.ts +5 -5
- package/dist/application/task-room-service.d.ts +1 -1
- package/dist/application/task-room-service.js +154 -16
- package/dist/application/types.d.ts +1 -8
- package/dist/briefing.js +12 -11
- package/dist/build-info.json +5 -5
- package/dist/cli.js +143 -63
- package/dist/config-yaml.d.ts +1 -1
- package/dist/config.d.ts +66 -6
- package/dist/config.js +398 -43
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +2 -2
- package/dist/daemon-recovery.d.ts +93 -0
- package/dist/daemon-recovery.js +328 -0
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +103 -127
- package/dist/doctor.js +18 -11
- package/dist/fleet-command-audit.d.ts +160 -0
- package/dist/fleet-command-audit.js +433 -0
- package/dist/fleet-proxy.d.ts +3 -1
- package/dist/fleet-proxy.js +30 -8
- package/dist/generated-agent-source.d.ts +9 -0
- package/dist/generated-agent-source.js +53 -0
- package/dist/harness/acp-session-transport.d.ts +8 -0
- package/dist/harness/acp-session-transport.js +3 -0
- package/dist/harness/agent-session.d.ts +51 -0
- package/dist/harness/agent-session.js +1 -0
- package/dist/harness/claude-code-session.d.ts +24 -0
- package/dist/harness/claude-code-session.js +36 -0
- package/dist/harness/claude-code.d.ts +2 -1
- package/dist/harness/claude-code.js +41 -81
- package/dist/harness/codex-session.d.ts +24 -0
- package/dist/harness/codex-session.js +36 -0
- package/dist/harness/codex.d.ts +2 -1
- package/dist/harness/codex.js +55 -45
- package/dist/harness/registry.js +4 -0
- package/dist/harness/types.d.ts +6 -38
- package/dist/index.d.ts +4 -6
- package/dist/index.js +2 -4
- package/dist/init-guidance.d.ts +1 -0
- package/dist/init-guidance.js +6 -0
- package/dist/isolation/resources.d.ts +3 -7
- package/dist/isolation/resources.js +3 -7
- package/dist/model-env.d.ts +4 -6
- package/dist/model-env.js +5 -8
- package/dist/monitor.d.ts +1 -24
- package/dist/monitor.js +5 -140
- package/dist/ops.js +4 -2
- package/dist/owner-channel/channel.d.ts +58 -2
- package/dist/owner-channel/channel.js +269 -29
- package/dist/owner-channel/commands.d.ts +2 -0
- package/dist/owner-channel/commands.js +31 -13
- package/dist/owner-channel/state.d.ts +2 -0
- package/dist/owner-channel/state.js +8 -2
- package/dist/preset-bootstrap.d.ts +10 -0
- package/dist/preset-bootstrap.js +85 -0
- package/dist/reports/artifact.d.ts +10 -0
- package/dist/reports/artifact.js +32 -0
- package/dist/reports/index.d.ts +5 -0
- package/dist/reports/index.js +5 -0
- package/dist/reports/render.d.ts +6 -0
- package/dist/reports/render.js +240 -0
- package/dist/reports/service.d.ts +42 -0
- package/dist/reports/service.js +57 -0
- package/dist/reports/tasks.d.ts +52 -0
- package/dist/reports/tasks.js +177 -0
- package/dist/reports/types.d.ts +315 -0
- package/dist/reports/types.js +6 -0
- package/dist/resolved-plan.d.ts +3 -2
- package/dist/resolved-plan.js +21 -5
- package/dist/rooms-tasks/cli.js +225 -40
- package/dist/rooms-tasks/config.js +24 -13
- package/dist/rooms-tasks/external-worker.d.ts +1 -0
- package/dist/rooms-tasks/external-worker.js +14 -9
- package/dist/rooms-tasks/provision.js +98 -36
- package/dist/rooms-tasks/templates.d.ts +0 -1
- package/dist/rooms-tasks/templates.js +9 -76
- package/dist/rooms-tasks/types.d.ts +10 -16
- package/dist/rooms-tasks/types.js +1 -4
- package/dist/runner.d.ts +13 -16
- package/dist/runner.js +110 -122
- package/dist/sensitive-config.d.ts +2 -0
- package/dist/sensitive-config.js +4 -0
- package/dist/session/acp.d.ts +7 -2
- package/dist/session/acp.js +29 -6
- package/dist/session/activity.d.ts +2 -3
- package/dist/session/activity.js +2 -3
- package/dist/session/arbiter.d.ts +4 -4
- package/dist/session/control.d.ts +17 -4
- package/dist/session/control.js +35 -0
- package/dist/session/types.d.ts +11 -5
- package/dist/spawn.d.ts +8 -33
- package/dist/spawn.js +53 -213
- package/dist/supervisor/none.d.ts +1 -1
- package/dist/supervisor/none.js +2 -2
- package/dist/temp-lifecycle.d.ts +1 -1
- package/dist/tmux.d.ts +1 -14
- package/dist/tmux.js +1 -51
- package/dist/watchdog/config.d.ts +10 -7
- package/dist/watchdog/config.js +30 -18
- package/dist/watchdog/run.js +12 -36
- package/dist/web/auth.d.ts +1 -1
- package/dist/web/fleet-config-service.d.ts +11 -8
- package/dist/web/fleet-config-service.js +384 -183
- package/dist/web/runtime.js +4 -15
- package/dist/web/server.d.ts +1 -3
- package/dist/web/server.js +3 -14
- package/dist/web/topology-promote.js +26 -19
- package/dist/web/topology.js +2 -2
- package/dist/web/yaml-document-edit.js +2 -0
- package/dist/web-app/assets/index-59GF-gsZ.css +1 -0
- package/dist/web-app/assets/index-BbTc5KtZ.js +10 -0
- package/dist/web-app/index.html +2 -2
- package/examples/fleet/agents/Alice.yaml +11 -0
- package/examples/fleet/agents/FleetCoordinator.yaml +7 -0
- package/examples/fleet/brains/claude-default.yaml +5 -0
- package/examples/fleet/roles/coordinator.yaml +5 -0
- package/examples/fleet/roles/developer.yaml +3 -0
- package/examples/fleet.yaml +74 -0
- package/package.json +5 -8
- package/presets/fleet/agents/Agent.yaml +3 -0
- package/presets/fleet/agents/Architect.yaml +3 -0
- package/presets/fleet/agents/Critic.yaml +3 -0
- package/presets/fleet/agents/Developer.yaml +3 -0
- package/presets/fleet/agents/Secretary.yaml +3 -0
- package/presets/fleet/agents/Tester.yaml +3 -0
- package/presets/fleet/brains/claude-default.yaml +5 -0
- package/presets/fleet/roles/Agent.yaml +6 -0
- package/presets/fleet/roles/Architect.yaml +6 -0
- package/presets/fleet/roles/Critic.yaml +6 -0
- package/presets/fleet/roles/Developer.yaml +6 -0
- package/presets/fleet/roles/Secretary.yaml +6 -0
- package/presets/fleet/roles/Tester.yaml +6 -0
- package/presets/fleet/room_templates/pair.yaml +11 -0
- package/presets/fleet/room_templates/single.yaml +8 -0
- package/presets/fleet/room_templates/team.yaml +12 -0
- package/presets/fleet.yaml +7 -0
- package/presets/manifest.json +5 -0
- package/dist/session/tmux.d.ts +0 -28
- package/dist/session/tmux.js +0 -80
- package/dist/web/terminal/bridge.d.ts +0 -27
- package/dist/web/terminal/bridge.js +0 -317
- package/dist/web-app/assets/TerminalView-C_G1ID2P.js +0 -9
- package/dist/web-app/assets/index-BCBK78hw.js +0 -10
- package/dist/web-app/assets/index-DuC-xnX4.css +0 -1
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
|
|
10
|
-
|
|
9
|
+
ours-fleet runs persistent or temporary, identity-bound AI roles through the
|
|
10
|
+
structured ACP session path:
|
|
11
11
|
|
|
12
12
|
- harness: \`claude-code\` or \`codex\`
|
|
13
|
-
- session: \`
|
|
13
|
+
- session: \`acp\` (default and only supported value)
|
|
14
14
|
- lifetime: permanent (supervised, restartable) or \`spawn --temp\`
|
|
15
15
|
|
|
16
16
|
## Discover and validate
|
|
@@ -23,24 +23,20 @@ ours-fleet doctor [-c FILE] [--harness codex|claude-code]
|
|
|
23
23
|
ours-fleet version [--json] # build identity, capabilities, every install on PATH
|
|
24
24
|
\`\`\`
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
wholesale and drop inline comments written on its items; lines outside that
|
|
41
|
-
collection remain byte-preserved. Each save is revision-guarded, reviewed as a diff
|
|
42
|
-
of the real file before anything is written, validated by the real loader, and
|
|
43
|
-
backed up next to the file first.
|
|
26
|
+
Configuration v2 is \`~/fleet.yaml\` plus typed bare documents under the exact
|
|
27
|
+
stem directories \`~/fleet/agents\`, \`~/fleet/roles\`, \`~/fleet/brains\`, and
|
|
28
|
+
\`~/fleet/room_templates\`.
|
|
29
|
+
The manifest owns fleet-wide operational defaults and automation; each Agent
|
|
30
|
+
selects one inline/ref Role and Brain and carries its operational fields.
|
|
31
|
+
Legacy top-level \`roles:\` and \`fleet.d\` are rejected. Validate the complete
|
|
32
|
+
trusted source set with \`config\` and \`doctor\` before starting or restarting.
|
|
33
|
+
|
|
34
|
+
Permanent \`spawn\` writes \`~/fleet/agents/Name.yaml\`. The web console edits an
|
|
35
|
+
explicit \`{manifest, agents}\` model while Role/Brain presets remain read-only.
|
|
36
|
+
Its aggregate revision includes every Agent/Role/Brain/Room-template source, previews a
|
|
37
|
+
redacted per-document diff in an exact-stem private staging tree, and saves under
|
|
38
|
+
one root lock with a private multi-file backup and full rollback. A no-op is
|
|
39
|
+
byte-identical and creates no backup.
|
|
44
40
|
|
|
45
41
|
## Build identity and install provenance
|
|
46
42
|
|
|
@@ -83,7 +79,7 @@ PATH order.
|
|
|
83
79
|
## Lifecycle and console commands
|
|
84
80
|
|
|
85
81
|
\`\`\`sh
|
|
86
|
-
ours-fleet init
|
|
82
|
+
ours-fleet init [-c FILE] # seed missing presets; never replace an existing file
|
|
87
83
|
ours-fleet up|down [Name...]
|
|
88
84
|
ours-fleet restart [Name...] # preserve/resume harness context
|
|
89
85
|
ours-fleet force-restart [Name...] # fresh context; briefing is reloaded
|
|
@@ -91,15 +87,14 @@ ours-fleet ls
|
|
|
91
87
|
ours-fleet status|peek|attach|logs Name
|
|
92
88
|
ours-fleet logs -f Name
|
|
93
89
|
ours-fleet send Name "prompt"
|
|
94
|
-
ours-fleet send Name --key Enter # tmux only
|
|
95
90
|
ours-fleet rm Name
|
|
96
91
|
ours-fleet watchdog-report <name> [run-id] [--list] [--json]
|
|
97
92
|
ours-fleet watchdog-run <name>
|
|
98
93
|
\`\`\`
|
|
99
94
|
|
|
100
|
-
\`peek\`, \`attach\`, and text \`send\`
|
|
101
|
-
also accepts \`/permit <permission-id> <option-id>\`, \`/interrupt\`,
|
|
102
|
-
\`/detach\`.
|
|
95
|
+
\`peek\`, \`attach\`, and text \`send\` use the structured agent session.
|
|
96
|
+
Attachment also accepts \`/permit <permission-id> <option-id>\`, \`/interrupt\`,
|
|
97
|
+
and \`/detach\`.
|
|
103
98
|
|
|
104
99
|
## Local web console
|
|
105
100
|
|
|
@@ -155,21 +150,19 @@ harness's own default.
|
|
|
155
150
|
## Spawn
|
|
156
151
|
|
|
157
152
|
\`\`\`sh
|
|
158
|
-
ours-fleet spawn [--temp] [Name | --
|
|
159
|
-
--
|
|
160
|
-
--
|
|
161
|
-
--coordinator Coordinator --model MODEL \\
|
|
153
|
+
ours-fleet spawn [--temp] [Name | --name Name] \\
|
|
154
|
+
--brain BRAIN_ID --role ROLE_ID \\
|
|
155
|
+
--cwd /absolute/path --identity Identity --coordinator Coordinator \\
|
|
162
156
|
--approval ask|auto|allow \\
|
|
163
157
|
--filesystem read-only|workspace|unrestricted \\
|
|
164
|
-
--unattended deny|wait
|
|
165
|
-
--bio-file /path/bio.md --persona-file /path/persona.md
|
|
158
|
+
--unattended deny|wait --isolation-file /path/isolation.yaml
|
|
166
159
|
\`\`\`
|
|
167
160
|
|
|
168
|
-
Permanent spawn writes \`~/fleet
|
|
161
|
+
Permanent spawn writes \`~/fleet/agents/Name.yaml\` and starts a supervised role.
|
|
169
162
|
\`--temp\` writes active state under \`~/.ours-fleet/tmp\` and starts an independent
|
|
170
163
|
transient supervisor (a collected systemd unit or submitted launchd job). It is
|
|
171
164
|
not enabled across reboot and does not die when the role that spawned it restarts.
|
|
172
|
-
|
|
165
|
+
Brain definitions own the ACP session backend. When a temporary role's bound identity
|
|
173
166
|
closes or its session ends, the supervisor, monitor and live roster entry retire
|
|
174
167
|
together; state moves intact to \`~/.ours-fleet/recovery/temporary\` with a
|
|
175
168
|
termination record. Failed launches use the same archive rather than deleting
|
|
@@ -201,88 +194,47 @@ only sustained authoritative absence closes the role. Unreachable, malformed, or
|
|
|
201
194
|
valid-but-empty daemon indexes are ambiguous and reset closure debounce rather
|
|
202
195
|
than becoming cleanup authority.
|
|
203
196
|
|
|
204
|
-
Inside a managed ACP role,
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
197
|
+
Inside a managed ACP role, public \`ours-fleet\` commands cross an authenticated
|
|
198
|
+
supervisor attribution boundary before Commander parsing. The original CLI remains
|
|
199
|
+
the executor inside the role's existing OS sandbox, and ordinary CLI validation is
|
|
200
|
+
the source of truth. Hidden worker entry points remain internal; public lifecycle and
|
|
201
|
+
operator commands are not restricted by the proxy.
|
|
202
|
+
|
|
203
|
+
Command invocation, raw argv, read-only work, validation failures, and generic
|
|
204
|
+
outcomes are never forwarded to the Owner-visible channel. Fleet announces only
|
|
205
|
+
confirmed Agent, Task, and Room lifecycle changes. Local diagnostics retain
|
|
206
|
+
structurally redacted command metadata. Lifecycle delivery uncertainty is logged,
|
|
207
|
+
never recursively announced, and never reruns or blindly retries an effect.
|
|
208
|
+
Room participant summaries describe creation and activation. Fleet has no public
|
|
209
|
+
post-create Room membership mutation, so it does not claim a separate membership event.
|
|
210
|
+
|
|
211
|
+
Omitted Brain and Role selections, working directory, coordinator, neutral permissions,
|
|
212
|
+
and fleet monitor policy inherit from the calling Agent. Explicit options always win.
|
|
213
|
+
Identity, mission/profile text, environment, owner routing, auth proxy, room startup,
|
|
214
|
+
isolation, worklog, and sensitive inline Brain values never inherit implicitly.
|
|
215
|
+
This automatic proxy is a convenience and
|
|
216
216
|
attribution mechanism, not an isolation boundary: an unrestricted role can still
|
|
217
|
-
invoke another binary path directly.
|
|
218
|
-
|
|
217
|
+
invoke another binary path directly. Host/operator shells keep the ordinary direct
|
|
218
|
+
CLI behavior.
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
not the \`monitor.mode\` wake-owner selector). Run \`ours-fleet help spawn\` for
|
|
224
|
-
exact values.
|
|
220
|
+
Brain owns harness, session, model, reasoning effort, token limits, and native harness
|
|
221
|
+
options. Removed runtime flags are rejected with migration guidance rather than silently
|
|
222
|
+
reinterpreted. A selection is a stable ID or an explicit \`inline:{...}\` mapping.
|
|
225
223
|
|
|
226
224
|
## fleet.yaml
|
|
227
225
|
|
|
228
226
|
\`\`\`yaml
|
|
227
|
+
api_version: ours.network/fleet/v2
|
|
229
228
|
vars:
|
|
230
229
|
work_root: /home/me/work
|
|
231
230
|
start_stagger_ms: 0
|
|
232
231
|
defaults:
|
|
233
|
-
harness: codex
|
|
234
|
-
session: acp
|
|
235
|
-
model: gpt-model-id
|
|
236
232
|
permissions:
|
|
237
233
|
approval: ask
|
|
238
234
|
filesystem: workspace
|
|
239
235
|
unattended: deny
|
|
240
236
|
monitor:
|
|
241
237
|
mode: fleet # fleet (default) | native
|
|
242
|
-
roles:
|
|
243
|
-
Coordinator:
|
|
244
|
-
harness: codex
|
|
245
|
-
session: acp
|
|
246
|
-
identity: Coordinator
|
|
247
|
-
cwd: \${work_root}/project
|
|
248
|
-
mission: Coordinate work and delegate implementation.
|
|
249
|
-
model: gpt-model-id
|
|
250
|
-
permissions:
|
|
251
|
-
approval: ask
|
|
252
|
-
filesystem: workspace
|
|
253
|
-
unattended: deny
|
|
254
|
-
session_options: # advanced overrides; normally omit
|
|
255
|
-
# acp:
|
|
256
|
-
# command: [/custom/codex-acp, --flag]
|
|
257
|
-
tmux:
|
|
258
|
-
boot_grace_ms: 10000
|
|
259
|
-
monitor:
|
|
260
|
-
mode: fleet # fleet supervisor | native harness monitor
|
|
261
|
-
interrupt: false # false queues; true cancels; after_tool steers at an ACP tool boundary
|
|
262
|
-
wake_sources: [message_received, file_received, local_contact_request, pending_message]
|
|
263
|
-
batch_ms: 2000
|
|
264
|
-
inject: notification
|
|
265
|
-
turn_fail_threshold: 3
|
|
266
|
-
harness_options:
|
|
267
|
-
launcher: auto
|
|
268
|
-
sandbox: workspace-write
|
|
269
|
-
approval: on-request
|
|
270
|
-
search: false
|
|
271
|
-
profile: fleet
|
|
272
|
-
add_dirs: [/data/shared]
|
|
273
|
-
config:
|
|
274
|
-
model_reasoning_effort: high
|
|
275
|
-
mcp_servers: # claude-code: per-role MCP servers, additive by default
|
|
276
|
-
ours: { command: ours-mcp, args: [proxy] }
|
|
277
|
-
mcp_servers_only: false # true = ONLY these; drops user/project/plugin servers
|
|
278
|
-
bio: Public role card and when peers should engage it.
|
|
279
|
-
persona: Local operating contract, boundaries, and escalation policy.
|
|
280
|
-
briefing_file: /absolute/custom-briefing.md
|
|
281
|
-
coordinator: AnotherCoordinator
|
|
282
|
-
env:
|
|
283
|
-
KEY: value
|
|
284
|
-
oversee:
|
|
285
|
-
- { role: Worker, interval: 5m }
|
|
286
238
|
watchdogs:
|
|
287
239
|
nightwatch: # [A-Za-z0-9_-], must not collide with a role name
|
|
288
240
|
coordinator: FleetCoordinator # required — where alerts go
|
|
@@ -290,42 +242,69 @@ watchdogs:
|
|
|
290
242
|
enabled: true # default true; false = configured but never scheduled
|
|
291
243
|
interval: 10m # default 10m; 30s | 10m | 2h, minimum 1m
|
|
292
244
|
watch: [Alice, CodexReviewer] # explicit lists are exact; omit for configured + live temp roles
|
|
293
|
-
|
|
294
|
-
model: claude-fable-5 # default: same resolution rule roles use (resolveRoleModel)
|
|
295
|
-
session: acp # default: defaults.session
|
|
245
|
+
agent: { ref: WatchdogAgent } # required: declared Agent ID, or canonical inline Agent definition
|
|
296
246
|
identity: Watchdog-nightwatch # default: Watchdog-<name>
|
|
297
247
|
timeout: 5m # default 5m; a run past this is killed and recorded as error
|
|
298
248
|
keep_reports: 50 # default 50 reports retained per watchdog
|
|
299
249
|
alert_cooldown: 60m # default 60m before the same finding alerts again
|
|
300
250
|
prompt_file: /abs/extra.md # optional extra focus, APPENDED to the fixed contract
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
251
|
+
\`\`\`
|
|
252
|
+
|
|
253
|
+
An Agent is a separate bare document under \`~/fleet/agents/<ID>.yaml\`:
|
|
254
|
+
|
|
255
|
+
\`\`\`yaml
|
|
256
|
+
role: { inline: { mission: Coordinate work and delegate implementation. } }
|
|
257
|
+
brain: { inline: { harness: codex, session: acp, model: gpt-model-id } }
|
|
258
|
+
identity: Coordinator
|
|
259
|
+
cwd: \${work_root}/project
|
|
260
|
+
oversee: [{ agent: Worker, interval: 5m }]
|
|
305
261
|
\`\`\`
|
|
306
262
|
|
|
307
263
|
A watchdog observes and reports; it never restarts, stops, spawns, or removes a
|
|
308
264
|
role, answers a pending permission, edits a workspace, or approves anything on
|
|
309
265
|
the owner's behalf. \`watchdogs:\` may appear only in the base config
|
|
310
|
-
(\`~/fleet.yaml\` or \`-c FILE\`)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
266
|
+
(\`~/fleet.yaml\` or \`-c FILE\`); Agent/Role/Brain documents never own it.
|
|
267
|
+
The selected Agent owns Brain, Role, permissions, isolation, and every other
|
|
268
|
+
agent setting. Legacy watchdog \`harness\`, \`model\`, \`session\`, and
|
|
269
|
+
\`isolation\` fields fail with migration guidance.
|
|
314
270
|
When \`watch:\` is omitted, each run watches the configured roles plus temporary
|
|
315
271
|
fleet roles that are live when the run starts. An explicit \`watch:\` list is
|
|
316
272
|
never augmented.
|
|
317
273
|
|
|
318
|
-
|
|
319
|
-
|
|
274
|
+
Agent operational values override manifest operational defaults. Role and Brain
|
|
275
|
+
ownership never cross-merges. \`\${name}\` substitutes entries from \`vars\`.
|
|
276
|
+
Brain fields include \`max_tokens\` and \`autocompact_pct\`; isolation is Agent-owned.
|
|
320
277
|
Use README.md for the complete isolation policy and resource-cap schema.
|
|
321
278
|
|
|
322
279
|
Supervised roles connect to the operator-configured ours daemon; they do not own its
|
|
323
280
|
lifecycle. Fleet strips the obsolete, presence-sensitive \`OURS_AUTOSTART\` variable from
|
|
324
|
-
|
|
281
|
+
agent-session children; \`ours-mcp proxy\` is client-only and never starts a daemon. Start
|
|
325
282
|
the shared daemon only through an explicit operator or installer/setup flow.
|
|
326
283
|
|
|
327
284
|
## Rooms and tasks
|
|
328
285
|
|
|
286
|
+
\`init\` materializes editable \`single\`, \`pair\`, and \`team\` Room templates plus
|
|
287
|
+
their exact-cased Agent, Role, and Brain presets. The command prints the packaged
|
|
288
|
+
preset revision and source directory. Inspect provenance and content before use:
|
|
289
|
+
|
|
290
|
+
\`\`\`sh
|
|
291
|
+
ours-fleet config [-c FILE]
|
|
292
|
+
ours-fleet template list [-c FILE]
|
|
293
|
+
ours-fleet template show team [-c FILE]
|
|
294
|
+
ours-fleet task create --title "Solo task" --template single [-c FILE]
|
|
295
|
+
ours-fleet task create --title "Reviewed change" --template pair [-c FILE]
|
|
296
|
+
ours-fleet task create --title "Phased delivery" --template team [-c FILE]
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
An alternate manifest \`-c /path/custom.yaml\` uses \`/path/custom/\` as its split
|
|
300
|
+
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
|
|
305
|
+
may shadow a same-named file only with \`override_builtin: true\` and a higher
|
|
306
|
+
version; this compatibility marker is deprecated and reported as a diagnostic.
|
|
307
|
+
|
|
329
308
|
Rooms always use \`ours-cowork\`; there is no room-provider selector. Configure
|
|
330
309
|
the cowork daemon connection and room owner directly:
|
|
331
310
|
|
|
@@ -496,9 +475,7 @@ Security meaning: \`ask\` maps to Codex \`untrusted\` and Claude \`default\`.
|
|
|
496
475
|
\`auto\` selects Codex ACP \`agent\` (\`on-request\` + \`workspace-write\`) and
|
|
497
476
|
Claude \`acceptEdits\`. \`approval: allow\` selects Codex ACP's fully
|
|
498
477
|
non-interactive yolo mode, reported as \`agent-full-access\` (\`never\` +
|
|
499
|
-
\`danger-full-access\`), and Claude \`bypassPermissions\`.
|
|
500
|
-
independent approval and sandbox flags: \`auto\` is \`on-request\`, \`allow\`
|
|
501
|
-
is \`never\`, and \`filesystem\` still selects the sandbox. These modes genuinely
|
|
478
|
+
\`danger-full-access\`), and Claude \`bypassPermissions\`. These modes genuinely
|
|
502
479
|
permit the actions the role was authorized to take —
|
|
503
480
|
\`dontAsk\` only suppresses the prompt while still refusing the action. Nothing
|
|
504
481
|
other than an explicit \`allow\` becomes non-interactive. Legacy \`deny\` keeps
|
|
@@ -531,16 +508,15 @@ dontAsk, bypassPermissions), \`plugins\`, \`mem_palace\`,
|
|
|
531
508
|
\`mcp_servers\` declares MCP servers for the role, in \`.mcp.json\`'s own shape
|
|
532
509
|
(a map of name to \`{ command, args, env }\`, or \`{ type: http|sse, url,
|
|
533
510
|
headers }\`). By default they are ADDED to whatever the OS user running the role
|
|
534
|
-
already has configured
|
|
535
|
-
ACP sends them in \`session/new\`.
|
|
511
|
+
already has configured. The Claude Code adapter sends them in \`session/new\`.
|
|
536
512
|
|
|
537
513
|
When \`mcp_servers\` is absent, Fleet sends ACP's protocol-required empty
|
|
538
514
|
\`mcpServers\` array without an exclusive override, so the agent keeps its inherited
|
|
539
515
|
servers. An explicitly empty configured set is different: Fleet preserves that intent
|
|
540
516
|
through the bundled adapter's compatibility path and disables every inherited server.
|
|
541
517
|
|
|
542
|
-
\`mcp_servers_only: true\` makes the declared set EXCLUSIVE
|
|
543
|
-
|
|
518
|
+
\`mcp_servers_only: true\` makes the declared set EXCLUSIVE through
|
|
519
|
+
\`strictMcpConfig\`. It is all-or-nothing and it ignores every
|
|
544
520
|
other MCP configuration: project \`.mcp.json\`, user settings, and **plugins**.
|
|
545
521
|
The ours connector is normally installed as a plugin, so a strict role that does
|
|
546
522
|
not re-declare it has no \`send_message\` and no \`get_messages\` — it cannot even
|
|
@@ -566,8 +542,8 @@ The maintained \`@agentclientprotocol/codex-acp\` and
|
|
|
566
542
|
\`@agentclientprotocol/claude-agent-acp\` runtimes are bundled automatically as
|
|
567
543
|
optional ours-fleet dependencies. The supervisor resolves their executable
|
|
568
544
|
entrypoints internally, so default ACP roles do not depend on global PATH.
|
|
569
|
-
The maintained Claude adapter requires Node 22;
|
|
570
|
-
|
|
545
|
+
The maintained Claude adapter requires Node 22; Codex ACP continues to work on
|
|
546
|
+
the ours-fleet core minimum of Node 20.
|
|
571
547
|
|
|
572
548
|
Override an adapter only when necessary with \`session_options.acp.command\`
|
|
573
549
|
(string or argv list). If optional dependencies were deliberately omitted,
|
|
@@ -581,7 +557,7 @@ ours-fleet falls back to a compatible globally installed \`codex-acp\` or
|
|
|
581
557
|
- \`fleet\` (default): the ours-fleet supervisor consumes body-free daemon
|
|
582
558
|
events and advances its durable cursor only after delivery is accepted. ACP
|
|
583
559
|
uses live steering when supported and falls back to structured
|
|
584
|
-
\`session/prompt
|
|
560
|
+
\`session/prompt\`.
|
|
585
561
|
- \`native\`: ours-fleet starts no supervisor monitor; the generated briefing
|
|
586
562
|
instructs Claude Code or Codex to arm its harness-native wake mechanism.
|
|
587
563
|
|
|
@@ -712,8 +688,8 @@ provenance checks.
|
|
|
712
688
|
The channel identity must be unique and must not be a role identity. The bridge
|
|
713
689
|
persists bounded wire IDs only, never message/reply plaintext, and requeues input
|
|
714
690
|
before starting its turn for at-least-once crash recovery. It currently requires
|
|
715
|
-
|
|
716
|
-
|
|
691
|
+
the structured agent-session interface backed by ACP so correlated final replies
|
|
692
|
+
retain their delivery guarantee.
|
|
717
693
|
|
|
718
694
|
### Live contact and owner administration
|
|
719
695
|
|
|
@@ -761,7 +737,7 @@ contains bounded CIDs and audit actions only. Corruption disables all effective
|
|
|
761
737
|
owners and refuses mutation rather than resurrecting authority; revoking the
|
|
762
738
|
last effective owner is always refused.
|
|
763
739
|
|
|
764
|
-
A missing/stopped role,
|
|
740
|
+
A missing/stopped role, role without \`owner_channel\`, unavailable
|
|
765
741
|
MCP client, or a role entering shutdown returns an actionable error with no
|
|
766
742
|
side effects. Management uses no network listener and never logs or persists
|
|
767
743
|
invite material.
|
package/dist/doctor.js
CHANGED
|
@@ -13,6 +13,7 @@ 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';
|
|
16
17
|
/** Which cgroup-v2 controllers are delegated to this user manager (advisory). */
|
|
17
18
|
function cgroupDelegationDetail() {
|
|
18
19
|
try {
|
|
@@ -94,7 +95,7 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
94
95
|
const loaded = loadConfigResult(opts.configPath, opts.yamlMode);
|
|
95
96
|
const roles = loaded.ok ? loaded.roles : [];
|
|
96
97
|
checks.push(loaded.ok
|
|
97
|
-
? { name: 'config', ok: true, detail: loaded.files.join(' + ')
|
|
98
|
+
? { name: 'config', ok: true, detail: loaded.files.join(' + ') }
|
|
98
99
|
: { name: 'config', ok: false, detail: loaded.error });
|
|
99
100
|
checks.push(loaded.ok
|
|
100
101
|
? { name: 'roles', ok: true, detail: `${roles.length} configured` }
|
|
@@ -106,6 +107,19 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
106
107
|
ok: true,
|
|
107
108
|
detail: `warning: ${diagnostic.message}`,
|
|
108
109
|
});
|
|
110
|
+
for (const role of roles) {
|
|
111
|
+
const recovery = readDaemonRecoveryStatus(agentDir(role.name));
|
|
112
|
+
if (!recovery)
|
|
113
|
+
continue;
|
|
114
|
+
const paths = ['agent', 'owner']
|
|
115
|
+
.map(name => `${name}=${recovery.paths[name].state}`)
|
|
116
|
+
.join(', ');
|
|
117
|
+
checks.push({
|
|
118
|
+
name: `daemon recovery: ${role.name}`,
|
|
119
|
+
ok: recovery.state === 'recovered',
|
|
120
|
+
detail: `${recovery.state}; ${paths}; epoch ${recovery.epoch || 'unavailable'}`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
109
123
|
// ── Rooms/tasks checks ────────────────────────────────────────
|
|
110
124
|
if (loaded.ok && loaded.rooms) {
|
|
111
125
|
const rooms = loaded.rooms;
|
|
@@ -149,13 +163,13 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
149
163
|
const roleNames = new Set(roles.map(r => r.name));
|
|
150
164
|
for (const t of templates) {
|
|
151
165
|
const badRefs = t.members
|
|
152
|
-
.filter(m => m.
|
|
153
|
-
.map(m => m.
|
|
166
|
+
.filter(m => 'ref' in m.agent && !roleNames.has(m.agent.ref))
|
|
167
|
+
.map(m => 'ref' in m.agent ? m.agent.ref : '');
|
|
154
168
|
if (badRefs.length) {
|
|
155
169
|
checks.push({
|
|
156
170
|
name: `template: ${t.name}@${t.version}`,
|
|
157
171
|
ok: true,
|
|
158
|
-
detail: `warning:
|
|
172
|
+
detail: `warning: Agent ref(s) ${badRefs.join(', ')} not found in configured Agents`,
|
|
159
173
|
});
|
|
160
174
|
}
|
|
161
175
|
}
|
|
@@ -226,13 +240,6 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
226
240
|
}
|
|
227
241
|
catch { /* state dir may not exist yet */ }
|
|
228
242
|
}
|
|
229
|
-
if (roles.length === 0 || roles.some(role => (role.session ?? 'tmux') === 'tmux')) {
|
|
230
|
-
const tmux = await exec('tmux', ['-V']);
|
|
231
|
-
checks.push({
|
|
232
|
-
name: 'tmux', ok: tmux.code === 0,
|
|
233
|
-
detail: tmux.code === 0 ? tmux.stdout.trim() : 'not found — apt install tmux / brew install tmux',
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
243
|
try {
|
|
237
244
|
const client = await attachDaemon({
|
|
238
245
|
env: process.env,
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
export type FleetCommandDecision = 'allow' | 'deny' | 'unsupported';
|
|
2
|
+
export type FleetCommandOutcomeClass = 'success' | 'validation' | 'denied' | 'runtime' | 'timeout' | 'proxy' | 'delivery';
|
|
3
|
+
export declare class FleetCliExit extends Error {
|
|
4
|
+
readonly exitCode: number;
|
|
5
|
+
readonly outcomeClass: FleetCommandOutcomeClass;
|
|
6
|
+
readonly effect: 'not_started' | 'completed' | 'unknown';
|
|
7
|
+
constructor(exitCode: number, outcomeClass?: FleetCommandOutcomeClass, effect?: 'not_started' | 'completed' | 'unknown');
|
|
8
|
+
}
|
|
9
|
+
export type FleetAuditPresentation = {
|
|
10
|
+
kind: 'agent_started';
|
|
11
|
+
eventId: string;
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
lifetime: 'permanent' | 'temporary';
|
|
15
|
+
brain: string;
|
|
16
|
+
role: string;
|
|
17
|
+
harness: string;
|
|
18
|
+
session: 'acp';
|
|
19
|
+
model?: string;
|
|
20
|
+
permissions?: string;
|
|
21
|
+
parent: string;
|
|
22
|
+
actionId: string;
|
|
23
|
+
inherited: string[];
|
|
24
|
+
} | {
|
|
25
|
+
kind: 'task';
|
|
26
|
+
operation: 'create' | 'start' | 'work' | 'block' | 'unblock' | 'review' | 'done' | 'cancel' | 'finish' | 'delete' | 'settling';
|
|
27
|
+
eventId: string;
|
|
28
|
+
id: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
previousState?: string;
|
|
31
|
+
newState: string;
|
|
32
|
+
template?: string;
|
|
33
|
+
roomId?: string;
|
|
34
|
+
revision?: string;
|
|
35
|
+
list?: string;
|
|
36
|
+
agents: Array<{
|
|
37
|
+
name: string;
|
|
38
|
+
brain?: string;
|
|
39
|
+
role: string;
|
|
40
|
+
permissions?: string;
|
|
41
|
+
}>;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'room';
|
|
44
|
+
operation: 'create' | 'activate' | 'close' | 'delete';
|
|
45
|
+
eventId: string;
|
|
46
|
+
id: string;
|
|
47
|
+
previousState?: string;
|
|
48
|
+
newState: string;
|
|
49
|
+
revision?: string;
|
|
50
|
+
name?: string;
|
|
51
|
+
template?: string;
|
|
52
|
+
taskId?: string;
|
|
53
|
+
participants: Array<{
|
|
54
|
+
name: string;
|
|
55
|
+
id?: string;
|
|
56
|
+
brain?: string;
|
|
57
|
+
role: string;
|
|
58
|
+
permissions?: string;
|
|
59
|
+
}>;
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'lifecycle_failure';
|
|
62
|
+
eventId: string;
|
|
63
|
+
resource: 'Agent' | 'Task' | 'Room';
|
|
64
|
+
id: string;
|
|
65
|
+
state: string;
|
|
66
|
+
category: 'provision_failed' | 'provision_pending' | 'readiness_failed' | 'settlement_failed' | 'settlement_pending' | 'cleanup_failed' | 'cleanup_pending';
|
|
67
|
+
};
|
|
68
|
+
/** Commands are Owner-silent unless they record one of these semantic lifecycle kinds. */
|
|
69
|
+
export declare const FLEET_LIFECYCLE_EVENT_KINDS: readonly ["agent_started", "task", "room", "lifecycle_failure"];
|
|
70
|
+
/** Stable semantic dedupe basis: resource kind + stable resource ID + transition/action ID. */
|
|
71
|
+
export declare function lifecycleEventDigestBasis(value: FleetAuditPresentation): string;
|
|
72
|
+
export declare function beginFleetAuditCollection(): void;
|
|
73
|
+
export declare function recordFleetAuditResource(kind: 'agent' | 'task' | 'room', id: string | undefined): void;
|
|
74
|
+
type FleetAuditPresentationInput = FleetAuditPresentation extends infer T ? T extends FleetAuditPresentation ? Omit<T, 'eventId'> & {
|
|
75
|
+
eventId?: string;
|
|
76
|
+
} : never : never;
|
|
77
|
+
export declare function recordFleetAuditPresentation(value: FleetAuditPresentationInput): void;
|
|
78
|
+
export declare function recordFleetAuditFailure(failure: {
|
|
79
|
+
class: FleetCommandOutcomeClass;
|
|
80
|
+
effect: 'not_started' | 'completed' | 'unknown';
|
|
81
|
+
}): void;
|
|
82
|
+
export declare function consumeFleetAuditCollection(): {
|
|
83
|
+
resourceIds?: Record<string, string>;
|
|
84
|
+
presentations?: FleetAuditPresentation[];
|
|
85
|
+
failure?: {
|
|
86
|
+
class: FleetCommandOutcomeClass;
|
|
87
|
+
effect: 'not_started' | 'completed' | 'unknown';
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
export interface FleetCommandClassification {
|
|
91
|
+
command: string;
|
|
92
|
+
route: string;
|
|
93
|
+
decision: FleetCommandDecision;
|
|
94
|
+
}
|
|
95
|
+
export interface FleetAuditAttempt {
|
|
96
|
+
version: 1;
|
|
97
|
+
correlationId: string;
|
|
98
|
+
requestId: string;
|
|
99
|
+
caller: string;
|
|
100
|
+
invokedAt: string;
|
|
101
|
+
classification: FleetCommandClassification;
|
|
102
|
+
argv: string[];
|
|
103
|
+
invocation: 'sending' | 'delivered' | 'uncertain';
|
|
104
|
+
outcome?: {
|
|
105
|
+
completedAt: string;
|
|
106
|
+
class: FleetCommandOutcomeClass;
|
|
107
|
+
exitCode?: number;
|
|
108
|
+
effect: 'not_started' | 'completed' | 'unknown';
|
|
109
|
+
delivery: 'sending' | 'delivered' | 'uncertain';
|
|
110
|
+
resourceIds?: Record<string, string>;
|
|
111
|
+
presentations?: FleetAuditPresentation[];
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
export declare const fleetProxyCommandInventory: Readonly<{
|
|
115
|
+
[k: string]: string[];
|
|
116
|
+
}>;
|
|
117
|
+
export declare const fleetProxyTopLevelInventory: Readonly<{
|
|
118
|
+
safeRead: string[];
|
|
119
|
+
agent: string[];
|
|
120
|
+
public: string[];
|
|
121
|
+
denied: string[];
|
|
122
|
+
hidden: string[];
|
|
123
|
+
aliases: string[];
|
|
124
|
+
}>;
|
|
125
|
+
/** Classify before Commander parsing. Unknown and internal paths fail closed. */
|
|
126
|
+
export declare function classifyFleetArgv(argv: readonly string[]): FleetCommandClassification;
|
|
127
|
+
/** Faithful ordered argv with deterministic structural redaction. */
|
|
128
|
+
export declare function redactFleetArgv(argv: readonly string[]): string[];
|
|
129
|
+
/** Durable write-once attempt ledger; contains redacted argv only. */
|
|
130
|
+
export declare class FleetCommandAuditStore {
|
|
131
|
+
private readonly path;
|
|
132
|
+
private readonly deps;
|
|
133
|
+
private attempts;
|
|
134
|
+
constructor(path: string, deps?: {
|
|
135
|
+
now(): Date;
|
|
136
|
+
uuid(): string;
|
|
137
|
+
});
|
|
138
|
+
list(): readonly FleetAuditAttempt[];
|
|
139
|
+
begin(requestId: string, caller: string, argv: readonly string[]): FleetAuditAttempt;
|
|
140
|
+
invocation(correlationId: string, caller: string, delivery: 'delivered' | 'uncertain'): FleetAuditAttempt;
|
|
141
|
+
finish(correlationId: string, caller: string, outcome: Omit<NonNullable<FleetAuditAttempt['outcome']>, 'completedAt' | 'delivery'>): FleetAuditAttempt;
|
|
142
|
+
outcome(correlationId: string, caller: string, delivery: 'delivered' | 'uncertain'): FleetAuditAttempt;
|
|
143
|
+
private owned;
|
|
144
|
+
private persist;
|
|
145
|
+
}
|
|
146
|
+
export declare function validateFleetAuditBegin(value: unknown): asserts value is {
|
|
147
|
+
requestId: string;
|
|
148
|
+
argv: string[];
|
|
149
|
+
};
|
|
150
|
+
export declare function validateFleetAuditFinish(value: unknown): asserts value is {
|
|
151
|
+
correlationId: string;
|
|
152
|
+
class: FleetCommandOutcomeClass;
|
|
153
|
+
exitCode?: number;
|
|
154
|
+
effect: 'not_started' | 'completed' | 'unknown';
|
|
155
|
+
resourceIds?: Record<string, string>;
|
|
156
|
+
presentations?: FleetAuditPresentation[];
|
|
157
|
+
};
|
|
158
|
+
/** Compact Owner presentation. It intentionally has no command, argv, environment, or correlation data. */
|
|
159
|
+
export declare function renderFleetLifecycleEvent(value: FleetAuditPresentation): string;
|
|
160
|
+
export {};
|