@ours.network/fleet 1.2.0-nightly.7 → 1.2.0-nightly.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -68
- package/dist/account-origin.d.ts +2 -0
- package/dist/account-origin.js +6 -0
- package/dist/agent-ours/bridge.js +26 -9
- package/dist/agent-ours/correspondence.d.ts +10 -0
- package/dist/agent-ours/correspondence.js +1 -0
- package/dist/agent-ours/file-rpc.d.ts +12 -0
- package/dist/agent-ours/file-rpc.js +18 -4
- package/dist/agent-ours/harness.js +9 -1
- package/dist/agent-ours/mcp-endpoint.d.ts +19 -0
- package/dist/agent-ours/mcp-endpoint.js +98 -25
- package/dist/agent-ours/runtime.d.ts +9 -1
- package/dist/agent-ours/runtime.js +50 -2
- package/dist/agent-ours/service.d.ts +24 -1
- package/dist/agent-ours/service.js +97 -13
- package/dist/application/codex-models.d.ts +15 -0
- package/dist/application/codex-models.js +56 -0
- package/dist/application/conversation-history.d.ts +34 -0
- package/dist/application/conversation-history.js +280 -0
- package/dist/application/conversation-role-observer.d.ts +62 -0
- package/dist/application/conversation-role-observer.js +206 -0
- package/dist/application/fleet-query-service.d.ts +1 -1
- package/dist/application/fleet-query-service.js +3 -3
- package/dist/application/log-service.js +8 -8
- package/dist/application/model-catalog.d.ts +1 -1
- package/dist/application/model-catalog.js +5 -2
- package/dist/application/preset-provenance.d.ts +19 -0
- package/dist/application/preset-provenance.js +59 -0
- package/dist/application/resource-observer.d.ts +40 -0
- package/dist/application/resource-observer.js +278 -0
- package/dist/application/role-creation-service.js +3 -2
- package/dist/application/role-removal-service.js +17 -3
- package/dist/application/role-repository.d.ts +1 -1
- package/dist/application/role-repository.js +30 -7
- package/dist/application/room-layout-definitions.d.ts +45 -0
- package/dist/application/room-layout-definitions.js +130 -0
- package/dist/application/session-control.d.ts +61 -17
- package/dist/application/session-control.js +207 -23
- package/dist/application/supervisor-ours-tools.js +5 -11
- package/dist/application/task-layouts.d.ts +91 -0
- package/dist/application/task-layouts.js +261 -0
- package/dist/application/task-room-service.d.ts +101 -3
- package/dist/application/task-room-service.js +286 -33
- package/dist/application/types.d.ts +2 -0
- package/dist/atomic-file.d.ts +34 -1
- package/dist/atomic-file.js +161 -18
- package/dist/briefing.d.ts +3 -1
- package/dist/briefing.js +97 -31
- package/dist/build-info.json +9 -4
- package/dist/capabilities.d.ts +9 -1
- package/dist/capabilities.js +13 -0
- package/dist/cli.js +400 -37
- package/dist/client-profile.d.ts +5 -17
- package/dist/client-profile.js +4 -127
- package/dist/config.d.ts +45 -0
- package/dist/config.js +57 -6
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +4 -4
- package/dist/daemon-recovery.d.ts +14 -9
- package/dist/daemon-recovery.js +124 -115
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +207 -19
- package/dist/doctor.d.ts +4 -1
- package/dist/doctor.js +75 -60
- package/dist/erased-resources.d.ts +9 -0
- package/dist/erased-resources.js +87 -0
- package/dist/file-delivery/reader.d.ts +15 -0
- package/dist/file-delivery/reader.js +63 -0
- package/dist/file-delivery/store.d.ts +15 -0
- package/dist/file-delivery/store.js +124 -0
- package/dist/file-delivery/types.d.ts +19 -0
- package/dist/file-delivery/types.js +1 -0
- package/dist/fleet-command-audit.d.ts +7 -0
- package/dist/fleet-command-audit.js +24 -8
- package/dist/harness/agent-session.d.ts +4 -0
- package/dist/harness/claude-code-session.js +1 -1
- package/dist/harness/claude-code.js +21 -11
- package/dist/harness/claude-runtime.d.ts +12 -0
- package/dist/harness/claude-runtime.js +43 -0
- package/dist/harness/codex-app-server-proxy.d.ts +4 -1
- package/dist/harness/codex-app-server-proxy.js +41 -5
- package/dist/harness/codex-reasoning.d.ts +5 -0
- package/dist/harness/codex-reasoning.js +12 -0
- package/dist/harness/codex-runtime.d.ts +11 -1
- package/dist/harness/codex-runtime.js +31 -4
- package/dist/harness/codex-session.js +2 -2
- package/dist/harness/codex.js +24 -12
- package/dist/init-wizard.d.ts +2 -0
- package/dist/init-wizard.js +38 -19
- package/dist/isolation/policy.js +6 -1
- package/dist/isolation/types.d.ts +5 -0
- package/dist/managed-cli.d.ts +253 -0
- package/dist/managed-cli.js +923 -0
- package/dist/managed-recovery.d.ts +13 -0
- package/dist/managed-recovery.js +31 -0
- package/dist/minimal-setup.d.ts +2 -0
- package/dist/minimal-setup.js +44 -0
- package/dist/monitor.d.ts +9 -34
- package/dist/monitor.js +90 -153
- package/dist/notifications/fleet-producer.d.ts +22 -0
- package/dist/notifications/fleet-producer.js +237 -0
- package/dist/notifications/outbox.d.ts +46 -0
- package/dist/notifications/outbox.js +158 -0
- package/dist/notifications/target-cleanup.d.ts +11 -0
- package/dist/notifications/target-cleanup.js +63 -0
- package/dist/notifications/task-producer.d.ts +20 -0
- package/dist/notifications/task-producer.js +100 -0
- package/dist/ops.d.ts +2 -0
- package/dist/ops.js +20 -3
- package/dist/owner-channel/channel.js +17 -6
- package/dist/owner-channel/commands.d.ts +4 -0
- package/dist/owner-channel/commands.js +8 -0
- package/dist/owner-channel/lifecycle-outbox.js +4 -3
- package/dist/owner-channel/ours-client.js +2 -17
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +2 -0
- package/dist/preset-migration.js +43 -0
- package/dist/process-incarnation.d.ts +23 -0
- package/dist/process-incarnation.js +42 -0
- package/dist/reminders/manager.d.ts +75 -0
- package/dist/reminders/manager.js +278 -0
- package/dist/reminders/runtime.d.ts +27 -0
- package/dist/reminders/runtime.js +32 -0
- package/dist/reminders/schedule.d.ts +37 -0
- package/dist/reminders/schedule.js +104 -0
- package/dist/reminders/store.d.ts +341 -0
- package/dist/reminders/store.js +762 -0
- package/dist/reminders/tools.d.ts +20 -0
- package/dist/reminders/tools.js +114 -0
- package/dist/resolved-plan.js +1 -0
- package/dist/rooms-tasks/add-member.d.ts +48 -0
- package/dist/rooms-tasks/add-member.js +84 -0
- package/dist/rooms-tasks/archived-absence.d.ts +8 -0
- package/dist/rooms-tasks/archived-absence.js +48 -0
- package/dist/rooms-tasks/cli.js +65 -5
- package/dist/rooms-tasks/close.d.ts +6 -2
- package/dist/rooms-tasks/close.js +246 -37
- package/dist/rooms-tasks/config.d.ts +1 -1
- package/dist/rooms-tasks/config.js +11 -4
- package/dist/rooms-tasks/cowork-adapter.d.ts +12 -5
- package/dist/rooms-tasks/cowork-adapter.js +15 -121
- package/dist/rooms-tasks/cowork-http.js +56 -6
- package/dist/rooms-tasks/deletion.d.ts +1 -1
- package/dist/rooms-tasks/deletion.js +84 -5
- package/dist/rooms-tasks/erasure.d.ts +6 -0
- package/dist/rooms-tasks/erasure.js +173 -0
- package/dist/rooms-tasks/external-worker.d.ts +1 -1
- package/dist/rooms-tasks/external-worker.js +3 -4
- package/dist/rooms-tasks/layout-binding-client.d.ts +11 -0
- package/dist/rooms-tasks/layout-binding-client.js +56 -0
- package/dist/rooms-tasks/layout-binding-grants.d.ts +21 -0
- package/dist/rooms-tasks/layout-binding-grants.js +128 -0
- package/dist/rooms-tasks/layout-cli.d.ts +4 -0
- package/dist/rooms-tasks/layout-cli.js +107 -0
- package/dist/rooms-tasks/layout-config.d.ts +11 -0
- package/dist/rooms-tasks/layout-config.js +89 -0
- package/dist/rooms-tasks/layout-control.d.ts +21 -0
- package/dist/rooms-tasks/layout-control.js +52 -0
- package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
- package/dist/rooms-tasks/layout-member-retirement.js +90 -0
- package/dist/rooms-tasks/layout-service.d.ts +43 -0
- package/dist/rooms-tasks/layout-service.js +203 -0
- package/dist/rooms-tasks/layout.d.ts +121 -0
- package/dist/rooms-tasks/layout.js +286 -0
- package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
- package/dist/rooms-tasks/legacy-task-member.js +116 -0
- package/dist/rooms-tasks/live-readiness.d.ts +18 -0
- package/dist/rooms-tasks/live-readiness.js +85 -0
- package/dist/rooms-tasks/member-ownership.d.ts +5 -0
- package/dist/rooms-tasks/member-ownership.js +40 -0
- package/dist/rooms-tasks/member-startup.d.ts +1 -0
- package/dist/rooms-tasks/member-startup.js +2 -0
- package/dist/rooms-tasks/provision.d.ts +3 -0
- package/dist/rooms-tasks/provision.js +101 -49
- package/dist/rooms-tasks/recovery.d.ts +19 -0
- package/dist/rooms-tasks/recovery.js +110 -0
- package/dist/rooms-tasks/room-state.d.ts +4 -2
- package/dist/rooms-tasks/room-state.js +47 -8
- package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
- package/dist/rooms-tasks/task-service-retirement.js +21 -0
- package/dist/rooms-tasks/task-state.d.ts +52 -8
- package/dist/rooms-tasks/task-state.js +251 -26
- package/dist/rooms-tasks/types.d.ts +40 -0
- package/dist/rooms-tasks/workspace-artifacts.d.ts +6 -0
- package/dist/rooms-tasks/workspace-artifacts.js +93 -0
- package/dist/rooms-tasks/workspace.d.ts +35 -0
- package/dist/rooms-tasks/workspace.js +325 -0
- package/dist/runner.d.ts +33 -4
- package/dist/runner.js +410 -62
- package/dist/session/acp.d.ts +75 -2
- package/dist/session/acp.js +345 -82
- package/dist/session/arbiter.d.ts +98 -0
- package/dist/session/arbiter.js +272 -3
- package/dist/session/codex-app-server.d.ts +45 -1
- package/dist/session/codex-app-server.js +225 -32
- package/dist/session/control.d.ts +17 -3
- package/dist/session/control.js +213 -23
- package/dist/session/conversation-normalizer.d.ts +2 -1
- package/dist/session/conversation-normalizer.js +1 -1
- package/dist/session/conversation-observation.d.ts +25 -0
- package/dist/session/conversation-observation.js +100 -0
- package/dist/session/conversation-replay.d.ts +50 -0
- package/dist/session/conversation-replay.js +203 -0
- package/dist/session/conversation-store.d.ts +15 -1
- package/dist/session/conversation-store.js +206 -26
- package/dist/session/conversation-types.d.ts +57 -4
- package/dist/session/prompt-batch.d.ts +79 -0
- package/dist/session/prompt-batch.js +120 -0
- package/dist/session/task-notice.d.ts +14 -0
- package/dist/session/task-notice.js +13 -0
- package/dist/session/types.d.ts +42 -1
- package/dist/setup-tunnel-preflight.d.ts +34 -0
- package/dist/setup-tunnel-preflight.js +62 -0
- package/dist/socket-path.d.ts +2 -0
- package/dist/socket-path.js +22 -0
- package/dist/spawn.d.ts +5 -1
- package/dist/spawn.js +40 -4
- package/dist/startup-prompt.d.ts +15 -0
- package/dist/startup-prompt.js +71 -0
- package/dist/startup-readiness.d.ts +32 -0
- package/dist/startup-readiness.js +101 -0
- package/dist/startup-telemetry.d.ts +16 -0
- package/dist/startup-telemetry.js +46 -0
- package/dist/subscriptions/cli.d.ts +91 -0
- package/dist/subscriptions/cli.js +223 -0
- package/dist/subscriptions/launch.d.ts +37 -0
- package/dist/subscriptions/launch.js +93 -0
- package/dist/subscriptions/login.d.ts +77 -0
- package/dist/subscriptions/login.js +215 -0
- package/dist/subscriptions/observed.d.ts +7 -0
- package/dist/subscriptions/observed.js +44 -0
- package/dist/subscriptions/probe.d.ts +10 -0
- package/dist/subscriptions/probe.js +73 -0
- package/dist/subscriptions/service.d.ts +102 -0
- package/dist/subscriptions/service.js +364 -0
- package/dist/subscriptions/store.d.ts +71 -0
- package/dist/subscriptions/store.js +143 -0
- package/dist/supervisor/adoption.d.ts +8 -0
- package/dist/supervisor/adoption.js +78 -0
- package/dist/supervisor/catalog.d.ts +62 -0
- package/dist/supervisor/catalog.js +254 -0
- package/dist/supervisor/fleet.d.ts +8 -0
- package/dist/supervisor/fleet.js +89 -0
- package/dist/supervisor/index.js +3 -6
- package/dist/supervisor/launchd.d.ts +1 -1
- package/dist/supervisor/launchd.js +26 -13
- package/dist/supervisor/legacy.d.ts +35 -0
- package/dist/supervisor/legacy.js +524 -0
- package/dist/supervisor/manager.d.ts +15 -0
- package/dist/supervisor/manager.js +270 -0
- package/dist/supervisor/registration-refresh.d.ts +45 -0
- package/dist/supervisor/registration-refresh.js +266 -0
- package/dist/supervisor/scope.d.ts +4 -0
- package/dist/supervisor/scope.js +10 -0
- package/dist/supervisor/systemd.d.ts +2 -2
- package/dist/supervisor/systemd.js +19 -33
- package/dist/task-supervision.d.ts +9 -0
- package/dist/task-supervision.js +145 -0
- package/dist/temp-idle.d.ts +17 -0
- package/dist/temp-idle.js +42 -0
- package/dist/temp-lifecycle.d.ts +23 -8
- package/dist/temp-lifecycle.js +123 -66
- package/dist/temp-supervisor-recovery.d.ts +1 -1
- package/dist/temp-supervisor-recovery.js +2 -2
- package/dist/tunnel-setup-completion.d.ts +7 -0
- package/dist/tunnel-setup-completion.js +13 -0
- package/dist/tunnel-setup-input.d.ts +19 -0
- package/dist/tunnel-setup-input.js +124 -0
- package/dist/watchdog/query.d.ts +3 -1
- package/dist/watchdog/query.js +2 -1
- package/dist/web/agent-attachments.d.ts +29 -0
- package/dist/web/agent-attachments.js +162 -0
- package/dist/web/auth.d.ts +65 -2
- package/dist/web/auth.js +201 -11
- package/dist/web/available-port.d.ts +2 -0
- package/dist/web/available-port.js +23 -0
- package/dist/web/control.d.ts +3 -3
- package/dist/web/control.js +10 -8
- package/dist/web/conversation-stream-codec.d.ts +23 -0
- package/dist/web/conversation-stream-codec.js +110 -0
- package/dist/web/conversation-stream.d.ts +25 -0
- package/dist/web/conversation-stream.js +231 -0
- package/dist/web/events.d.ts +2 -0
- package/dist/web/events.js +9 -0
- package/dist/web/fleet-config-service.d.ts +4 -1
- package/dist/web/fleet-config-service.js +46 -15
- package/dist/web/prefix-gateway.d.ts +32 -0
- package/dist/web/prefix-gateway.js +248 -0
- package/dist/web/resource-views.d.ts +124 -0
- package/dist/web/resource-views.js +424 -0
- package/dist/web/runtime.d.ts +3 -1
- package/dist/web/runtime.js +132 -34
- package/dist/web/server.d.ts +19 -0
- package/dist/web/server.js +802 -67
- package/dist/web/service.d.ts +11 -2
- package/dist/web/service.js +30 -4
- package/dist/web/workspace-devices.d.ts +107 -0
- package/dist/web/workspace-devices.js +277 -0
- package/dist/web/workspace-tunnel.d.ts +1 -0
- package/dist/web/workspace-tunnel.js +34 -0
- package/dist/workspace-enrollment.d.ts +83 -0
- package/dist/workspace-enrollment.js +580 -0
- package/dist/workspace-replacement.d.ts +66 -0
- package/dist/workspace-replacement.js +220 -0
- package/docs/acp-files.md +146 -0
- package/docs/conversation-stream.md +196 -0
- package/docs/fleet-migration.md +54 -0
- package/docs/live-voice.md +13 -0
- package/docs/room-layouts.md +227 -0
- package/docs/self-reminders.md +374 -0
- package/docs/task-workspaces.md +225 -0
- package/docs/validation/managed-cli-permissions.md +421 -0
- package/examples/room-layouts/fresh.yaml +27 -0
- package/examples/room-layouts/scoped.yaml +21 -0
- package/examples/room-layouts/shared.yaml +19 -0
- package/package.json +24 -20
- package/presets/README.md +78 -0
- package/presets/brain-catalog.json +8 -2
- package/presets/fleet/agent_templates/Critic.yaml +1 -1
- package/presets/fleet/agent_templates/Developer.yaml +1 -1
- package/presets/fleet/agent_templates/Engineer.yaml +5 -0
- package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -2
- package/presets/fleet/agents/FleetCoordinator.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-1-high.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-low.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-max.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-medium.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-1-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-fable-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/claude-haiku-4-5-20251001-default.yaml +4 -0
- package/presets/fleet/brains/claude-opus-5-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-opus-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-high.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-low.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-max.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-medium.yaml +1 -1
- package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-1-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-1-sol-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +1 -1
- package/presets/fleet/brains/codex-gpt-6-luna-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-luna-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-sol-xhigh.yaml +5 -0
- package/presets/fleet/roles/Coordinator.yaml +12 -11
- package/presets/fleet/roles/Critic.yaml +13 -0
- package/presets/fleet/roles/Developer.yaml +13 -0
- package/presets/fleet/roles/Engineer.yaml +53 -0
- package/presets/fleet/room_layouts/engineering.yaml +25 -0
- package/presets/fleet/room_layouts/pair.yaml +24 -0
- package/presets/fleet/room_layouts/single.yaml +17 -0
- package/presets/fleet/room_layouts/team.yaml +30 -0
- package/presets/fleet/room_templates/engineering.yaml +19 -0
- package/presets/manifest.json +2 -2
- package/dist/web-app/assets/index-59GF-gsZ.css +0 -1
- package/dist/web-app/assets/index-C0h3ALvs.js +0 -10
- package/dist/web-app/icons/ours-fleet-maskable.svg +0 -4
- package/dist/web-app/icons/ours-fleet.svg +0 -4
- package/dist/web-app/index.html +0 -17
- package/dist/web-app/manifest.webmanifest +0 -15
- package/dist/web-app/offline.html +0 -18
- package/dist/web-app/sw.js +0 -51
package/dist/docs.js
CHANGED
|
@@ -172,34 +172,29 @@ rollback; inspect host integration and private init stage/recovery evidence.
|
|
|
172
172
|
Attachment also accepts \`/permit <permission-id> <option-id>\`, \`/interrupt\`,
|
|
173
173
|
and \`/detach\`.
|
|
174
174
|
|
|
175
|
-
## Local
|
|
175
|
+
## Local HTTP service
|
|
176
176
|
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
Fleet runs an HTTP service for the App. It serves no pages and opens no
|
|
178
|
+
browser; every screen is in the App.
|
|
179
179
|
|
|
180
180
|
\`\`\`sh
|
|
181
181
|
npm i -g @ours.network/fleet
|
|
182
|
-
ours-fleet
|
|
183
|
-
ours-fleet
|
|
184
|
-
ours-fleet web # install/update service, start, pair browser
|
|
182
|
+
ours-fleet setup-tunnel --file /private/setup.txt # connect host; prints QR and connection code
|
|
183
|
+
ours-fleet link-device # connect another browser or device
|
|
185
184
|
\`\`\`
|
|
186
185
|
|
|
187
|
-
The
|
|
188
|
-
owner-level systemd user service (Linux) or LaunchAgent (macOS)
|
|
189
|
-
five-minute one-use pairing link in the local browser. After pairing, bookmark
|
|
190
|
-
the plain URL or install the PWA. To pair a new, signed-out, or revoked browser,
|
|
191
|
-
run \`ours-fleet web open\`.
|
|
186
|
+
The service listens on \`http://127.0.0.1:49271/\` and is installed as an
|
|
187
|
+
owner-level systemd user service (Linux) or LaunchAgent (macOS).
|
|
192
188
|
|
|
193
189
|
\`\`\`sh
|
|
194
190
|
ours-fleet web status
|
|
195
191
|
ours-fleet web start|stop|restart
|
|
196
|
-
ours-fleet web
|
|
197
|
-
ours-fleet web revoke-all # revoke every browser and active session
|
|
192
|
+
ours-fleet web revoke-all # revoke every device and active session
|
|
198
193
|
ours-fleet web uninstall
|
|
199
|
-
ours-fleet web serve --port 0
|
|
194
|
+
ours-fleet web serve --port 0 # isolated foreground/testing mode
|
|
200
195
|
\`\`\`
|
|
201
196
|
|
|
202
|
-
The
|
|
197
|
+
The service is IPv4-loopback-only by default. Both \`localhost\` and
|
|
203
198
|
\`127.0.0.1\` are accepted locally. For an nginx/TLS reverse proxy, keep the
|
|
204
199
|
default bind and declare the exact browser origin:
|
|
205
200
|
|
|
@@ -271,6 +266,88 @@ the executor inside the role's existing OS sandbox, and ordinary CLI validation
|
|
|
271
266
|
the source of truth. Hidden worker entry points remain internal; public lifecycle and
|
|
272
267
|
operator commands are not restricted by the proxy.
|
|
273
268
|
|
|
269
|
+
### Fleet commands from a command sandbox (\`managed_cli\`)
|
|
270
|
+
|
|
271
|
+
That supervisor connection is a Unix socket. A harness command sandbox (Codex
|
|
272
|
+
\`workspace-write\`, Claude's OS sandbox) can refuse it with \`connect EPERM\`
|
|
273
|
+
before any command, even \`--help\`, is parsed. Fleet prepares the native
|
|
274
|
+
harness policy for one declared workflow; you never write Codex rules or Claude
|
|
275
|
+
sandbox settings by hand.
|
|
276
|
+
|
|
277
|
+
Opt an Agent (or Agent Template) in explicitly. It is never inferred from a
|
|
278
|
+
role's name or persona and is not inherited by agents it spawns:
|
|
279
|
+
|
|
280
|
+
\`\`\`yaml
|
|
281
|
+
# fleet/agents/FleetCoordinator.yaml
|
|
282
|
+
role: { ref: Coordinator }
|
|
283
|
+
brain: { ref: codex-gpt-5-4-medium }
|
|
284
|
+
permissions: { approval: auto, filesystem: workspace, unattended: deny }
|
|
285
|
+
managed_cli: [task-workflow]
|
|
286
|
+
\`\`\`
|
|
287
|
+
|
|
288
|
+
\`ours-fleet managed-cli setup --enable FleetCoordinator\` adds that one key to
|
|
289
|
+
an existing Agent file and changes nothing else, permissions included.
|
|
290
|
+
\`ours-fleet managed-cli setup\` generates the policy for every declaring agent
|
|
291
|
+
and \`ours-fleet managed-cli status\` compares without writing. Neither starts a
|
|
292
|
+
session or a model. The same preparation runs at every agent start, so spawned
|
|
293
|
+
and task-room agents need no separate step.
|
|
294
|
+
|
|
295
|
+
\`task-workflow\` prepares: \`task create|start|finish|block|unblock|review\`,
|
|
296
|
+
\`task list|show\`, \`room show|members\`, \`template list|show|validate\`,
|
|
297
|
+
\`config\`, \`docs\` and \`--help\`. \`task start\` and \`task finish\`
|
|
298
|
+
provision and retire rooms and agents: this is real authority. Not prepared, and
|
|
299
|
+
still sandboxed: \`spawn\`, \`ours tools|call\`, \`status|peek|send\`, room
|
|
300
|
+
create/delete/close, task cancel/delete and service administration.
|
|
301
|
+
|
|
302
|
+
The agent invokes a prepared command through the pinned entry form shown in its
|
|
303
|
+
briefing:
|
|
304
|
+
|
|
305
|
+
\`\`\`sh
|
|
306
|
+
/abs/node /abs/fleet/dist/cli.js --managed-configuration /abs/fleet.yaml task create --title "..." --backlog --no-room
|
|
307
|
+
\`\`\`
|
|
308
|
+
|
|
309
|
+
What the native policy does and does not do:
|
|
310
|
+
|
|
311
|
+
- A rule fixes the Node executable, this Fleet CLI, the configuration and the
|
|
312
|
+
command. It matches an argv prefix and admits every trailing option and
|
|
313
|
+
argument. It is not argument validation, target authorization or per-agent
|
|
314
|
+
isolation.
|
|
315
|
+
- A later \`-c\`/\`--configuration\` naming another file is refused by the
|
|
316
|
+
Fleet CLI itself, after the process has started outside the sandbox. That is
|
|
317
|
+
Fleet validation, not a native policy denial.
|
|
318
|
+
- The supervisor audit and ordinary CLI validation are unchanged. The pinned
|
|
319
|
+
form is refused outside a managed session, where no supervisor would audit it.
|
|
320
|
+
- Compound, piped, redirected, \`$(...)\` and \`VAR=value\`-prefixed command
|
|
321
|
+
lines do not match and stay sandboxed.
|
|
322
|
+
- Codex: a Fleet-owned \`.codex/rules/ours-fleet-<id>.rules\` in the agent's
|
|
323
|
+
workspace. It applies to every trusted Codex session in that workspace, and
|
|
324
|
+
Codex must trust the workspace; Fleet does not change trust. Other files in
|
|
325
|
+
that directory are never touched.
|
|
326
|
+
- Claude: entries in the agent's own Fleet settings overlay
|
|
327
|
+
(\`permissions.allow\` and \`sandbox.excludedCommands\`). Your Claude settings
|
|
328
|
+
are not modified and Fleet never enables or disables Claude's OS sandbox.
|
|
329
|
+
- A Fleet CLI or configuration path containing spaces is spelled in single
|
|
330
|
+
quotes (Codex >= 0.160.0). The Node executable itself must be at a path that
|
|
331
|
+
needs no quoting: neither harness matches a quoted executable against a rule.
|
|
332
|
+
A path containing anything but letters, digits, spaces and \`_@%+=:,./-\`
|
|
333
|
+
(quotes, backslashes, \`*\` and other pattern characters), or located inside
|
|
334
|
+
the agent's workspace or a \`harness_options.add_dirs\` directory (also through
|
|
335
|
+
a symlink), is reported as unsupported; so is a Codex role with
|
|
336
|
+
\`harness_options.config\` or \`profile\`, whose sandbox Fleet does not inspect.
|
|
337
|
+
- Prepared for: Codex native app-server and bundled ACP, Claude bundled ACP, on
|
|
338
|
+
Linux and macOS. The generated setup was qualified end to end on Linux
|
|
339
|
+
(Codex 0.160.0, Claude Code 2.1.289); the macOS run of that matrix is
|
|
340
|
+
outstanding and \`managed-cli status\` says so there. Custom session
|
|
341
|
+
commands, other harnesses, roles declaring \`isolation:\` and other
|
|
342
|
+
platforms are reported as unsupported and left exactly as sandboxed as before.
|
|
343
|
+
|
|
344
|
+
\`ours-fleet doctor\` reports three separate facts per declaring agent: the
|
|
345
|
+
generated setup (static), whether the last launch loaded the current policy, and
|
|
346
|
+
what the supervisor audit ledger recorded since. A prepared setup is not
|
|
347
|
+
evidence of supervisor access, and a successful \`--help\` proves only its own
|
|
348
|
+
audited path, not the task lifecycle. See
|
|
349
|
+
\`docs/validation/managed-cli-permissions.md\`.
|
|
350
|
+
|
|
274
351
|
Command invocation, raw argv, read-only work, validation failures, and generic
|
|
275
352
|
outcomes are never forwarded to the Owner-visible channel. Fleet announces only
|
|
276
353
|
confirmed Agent, Task, and Room lifecycle changes. Local diagnostics retain
|
|
@@ -492,6 +569,17 @@ Messenger-bound results are capped at 3,500 Unicode code points and 12,000 UTF-8
|
|
|
492
569
|
bytes with structural omission notices. \`--json\` bypasses this presentation layer
|
|
493
570
|
and retains the versioned machine schema and serialization order.
|
|
494
571
|
|
|
572
|
+
Active task \`show\` reports current readiness separately from lifecycle, also in
|
|
573
|
+
Owner commands. Start/work preserve the fail-closed \`task_not_ready\` behavior.
|
|
574
|
+
Unknown control health does not prove a dead agent or authorize replacement.
|
|
575
|
+
Before deliberate recovery, Fleet Coordinator inspects current seats and exact
|
|
576
|
+
old-launch worklogs/termination evidence in \`recovery/temporary\`, preserves
|
|
577
|
+
original records, and privately records verified old/new launch provenance.
|
|
578
|
+
A new inbox is not complete history: page scoped history to the end, authenticate
|
|
579
|
+
historical Owner authors, and compare completed actions and replies before resuming.
|
|
580
|
+
Do not restore archived identity state, reuse invites, adopt same-role seats or
|
|
581
|
+
blindly replay instructions. Ask the Owner if authority/completion is uncertain.
|
|
582
|
+
|
|
495
583
|
Every task belongs to a named list. The built-in \`default\` list always exists,
|
|
496
584
|
and legacy tasks or create calls without \`--list\` resolve to it. Use \`task lists\`,
|
|
497
585
|
\`task list-create <name>\`, \`task list-rename <name> <new-name>\`, and
|
|
@@ -738,6 +826,32 @@ Override an adapter only when necessary with \`session_options.acp.command\`
|
|
|
738
826
|
ours-fleet falls back to a compatible globally installed \`codex-acp\` or
|
|
739
827
|
\`claude-agent-acp\`. \`ours-fleet doctor -c FILE\` verifies the resolved adapter.
|
|
740
828
|
|
|
829
|
+
## Boot-time daemon readiness
|
|
830
|
+
|
|
831
|
+
Linux permanent-agent services wait for their configured daemon before launching
|
|
832
|
+
Fleet's runner. This uses the role's saved manifest path and environment, including
|
|
833
|
+
host profiles, gateway endpoints and expected daemon identity; no Docker container
|
|
834
|
+
names or default ports are assumed. The read-only probe requires verified startup
|
|
835
|
+
readiness and an available identity index. Unavailable or unauthorized daemons leave
|
|
836
|
+
the service waiting, with a diagnostic code in the journal. Each wait is bounded
|
|
837
|
+
and systemd retries it until the daemon is ready; stopping the service cancels it.
|
|
838
|
+
This does not consume the agent crash budget or discard its session context.
|
|
839
|
+
Once the runner starts, its normal crash circuit breaker still applies.
|
|
840
|
+
After upgrading Fleet, run \`ours-fleet service refresh\` (\`ours-install\` does it for
|
|
841
|
+
you). Service definitions start the exact release tree that wrote them, so an
|
|
842
|
+
unrefreshed one starts the previous release after the next reboot.
|
|
843
|
+
\`ours-fleet service check\` reports each supervisor, web and watchdog definition,
|
|
844
|
+
and whether its running process uses another release, without changing anything.
|
|
845
|
+
\`refresh\` only re-points the release paths in definitions Fleet generated, runs
|
|
846
|
+
\`daemon-reload\`, and never creates, starts, stops or restarts a service. A running
|
|
847
|
+
supervisor keeps its code until it is restarted.
|
|
848
|
+
Temporary agents and macOS services retain their existing lifecycle behavior.
|
|
849
|
+
|
|
850
|
+
After a supervisor restart or reboot, prompts a role had admitted but never
|
|
851
|
+
started are dispatched only once its control socket is listening, so recovered
|
|
852
|
+
work cannot reach the previous run's socket (\`connect ECONNREFUSED\`). Turns that
|
|
853
|
+
had already started are closed as \`unknown_after_restart\` and never replayed.
|
|
854
|
+
|
|
741
855
|
## Reliable mail wake
|
|
742
856
|
|
|
743
857
|
\`monitor.mode\` selects exactly one wake owner:
|
|
@@ -749,10 +863,12 @@ ours-fleet falls back to a compatible globally installed \`codex-acp\` or
|
|
|
749
863
|
- \`native\`: ours-fleet starts no supervisor monitor; the generated briefing
|
|
750
864
|
instructs Claude Code or Codex to arm its harness-native wake mechanism.
|
|
751
865
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
866
|
+
\`monitor.interrupt\` defaults to \`after_tool\` for every harness except Hermes,
|
|
867
|
+
which defaults to \`false\`; an explicit value always wins, and temporary snapshots
|
|
868
|
+
written without one keep \`false\`. Set \`monitor.interrupt: true\` in fleet mode to
|
|
869
|
+
cancel active work before every configured wake. \`after_tool\` preserves an active
|
|
870
|
+
ACP tool (and any pending permission), then steers the wake at the first
|
|
871
|
+
tool-terminal boundary without cancellation. A hung boundary is bounded at 120 seconds and falls back
|
|
756
872
|
to non-cancelling steering/queueing; adapters without authenticated tool events
|
|
757
873
|
use the same conservative fallback. Explicit human/control interrupts remain
|
|
758
874
|
immediate. The policy is content-blind because the supervisor cannot inspect
|
|
@@ -773,6 +889,78 @@ selection.
|
|
|
773
889
|
Inspect \`ours-fleet status Name\`, \`peek Name\`, role logs, and
|
|
774
890
|
\`~/.ours-fleet/agents/Name/.monitor-status\` when diagnosing delivery.
|
|
775
891
|
|
|
892
|
+
## Self-reminders
|
|
893
|
+
|
|
894
|
+
Every managed agent (\`session: acp\` or \`codex-app-server\`, Claude or Codex,
|
|
895
|
+
persistent, temporary or task-owned) can schedule one-time wakes for ITSELF.
|
|
896
|
+
The tools are on the agent's own fixed-identity ours MCP server, so there is no
|
|
897
|
+
agent, identity or recipient argument and no setup, worker, service, chat or key:
|
|
898
|
+
|
|
899
|
+
- \`fleet_reminder_create\` — \`request_key\` (stable per decision; a repeat with
|
|
900
|
+
the same input returns the same reminder, different input is refused),
|
|
901
|
+
\`title\`, optional \`note\`, \`local_time\` (date and time WITHOUT an offset, e.g.
|
|
902
|
+
\`2027-01-20T16:00\`), \`time_zone\` (IANA, e.g. \`Europe/London\`, \`UTC\`), optional
|
|
903
|
+
\`fold\` (0/1, required only for a time that occurs twice when clocks go back;
|
|
904
|
+
times skipped by a spring-forward gap are refused), \`late_window_seconds\`
|
|
905
|
+
(60..604800, default 3600) and \`interrupt\` (default false; see below).
|
|
906
|
+
- \`fleet_reminder_list\` — \`state\` \`open\` (default) | \`closed\` | \`all\`, \`limit\`, \`after\`.
|
|
907
|
+
- \`fleet_reminder_update\` / \`fleet_reminder_cancel\` — \`id\` + \`expected_revision\`;
|
|
908
|
+
every change bumps the revision and voids any wake issued for the old one.
|
|
909
|
+
- \`fleet_reminder_inspect\` — \`event_id\` from a wake: the note, whether the
|
|
910
|
+
wake is still current and eligible, and for an urgent one \`interrupt.state\`.
|
|
911
|
+
- \`fleet_reminder_ack\` — \`event_id\` + \`expected_revision\`: records that the
|
|
912
|
+
wake was handled. Idempotent; sends nothing and claims no external action.
|
|
913
|
+
|
|
914
|
+
When a reminder is due the supervisor starts one turn beginning \`[fleet-reminder]\`
|
|
915
|
+
with the event id. It is the agent's own stored reminder, not an owner
|
|
916
|
+
instruction or ours mail, and grants no authority. Fleet never sends anything
|
|
917
|
+
on the agent's behalf; whether to message anyone is the agent's own decision
|
|
918
|
+
under its existing tools and authorization.
|
|
919
|
+
|
|
920
|
+
Delivery: the supervisor process that runs the agent owns the timer — an idle
|
|
921
|
+
agent with no open reminders costs nothing, and only a due reminder creates a
|
|
922
|
+
model turn. By default a wake never interrupts or queues behind work: it is
|
|
923
|
+
admitted at the next idle turn boundary after its due time and after the agent's
|
|
924
|
+
startup turn.
|
|
925
|
+
|
|
926
|
+
Urgent (\`interrupt: true\`), only for a return genuinely bound to a time: when
|
|
927
|
+
due and the agent is busy with an interruptible turn (mail wake, scheduled loop,
|
|
928
|
+
local console), the supervisor durably records the request, asks that exact turn
|
|
929
|
+
to stop once per revision, keeps the session and context, and releases the wake
|
|
930
|
+
through the same fence. It never stops owner-channel or owner-console work,
|
|
931
|
+
startup, stall recovery, another reminder, a pending permission, queued work or a
|
|
932
|
+
turn it cannot identify; then it waits like an ordinary reminder and \`inspect\`
|
|
933
|
+
shows \`interrupt_deferred\`. Due, interruption requested, its terminal
|
|
934
|
+
(\`cancelled\` only when correlated; else \`ended\`/\`forced\`/\`failed\`/\`unknown\`),
|
|
935
|
+
release, ack and any external action are separate facts. A forced or failed stop
|
|
936
|
+
never queues the wake. It is not a hard real-time alarm and does nothing while
|
|
937
|
+
the host or agent is down.
|
|
938
|
+
If the host, Fleet or the agent is down, paused or busy, a reminder is still
|
|
939
|
+
delivered when it comes back within its late window, and otherwise expires
|
|
940
|
+
without a turn. Reminders survive supervisor, Fleet and host restarts and
|
|
941
|
+
ordinary stop/start. They do not survive the agent: removing or retiring an
|
|
942
|
+
agent or its task cancels them and deletes their state, and a replaced identity
|
|
943
|
+
or same-named successor never inherits them.
|
|
944
|
+
|
|
945
|
+
Guarantees are at most once per reminder revision. Queue acceptance, release to
|
|
946
|
+
the model, the agent's ack, and any external action are distinct facts. A wake
|
|
947
|
+
is marked dispatched durably at the moment it is handed to the model; if the
|
|
948
|
+
supervisor stops before that, the same event is retried. If it stops after, the
|
|
949
|
+
event is held \`uncertain\` (shown by \`list\`/\`inspect\`, never re-sent): check your
|
|
950
|
+
own records, then ack it or schedule something new.
|
|
951
|
+
|
|
952
|
+
Waiting on a peer (Developer/Critic/Engineer): before waiting on a specific
|
|
953
|
+
review, answer or artifact, schedule ONE idle-only reminder about 20 minutes out
|
|
954
|
+
naming the task/room and the expectation; cancel or reschedule it (with its
|
|
955
|
+
revision) when the state changes; on the wake re-check, ack if resolved, else one
|
|
956
|
+
follow-up in the same room and at most one more reminder, then report the
|
|
957
|
+
nonresponse once. No polling, recurring chains, repeated follow-ups or automatic
|
|
958
|
+
done.
|
|
959
|
+
|
|
960
|
+
Operators can read an agent's reminders with
|
|
961
|
+
\`ours-fleet ours call Name fleet_reminder_list\`. Full guide, examples and the
|
|
962
|
+
migration from the standalone \`self-reminders\` worker skill: \`docs/self-reminders.md\`.
|
|
963
|
+
|
|
776
964
|
## Trusted owner channel
|
|
777
965
|
|
|
778
966
|
Any managed role may declare a separate ours identity which fleet — never the agent —
|
package/dist/doctor.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { type RefreshOptions } from './supervisor/registration-refresh.js';
|
|
1
2
|
import { type AttachOursClientOptions, type OursClient } from '@ours.network/sdk/client';
|
|
2
3
|
import { type Exec } from './exec.js';
|
|
3
4
|
import type { YamlMode } from './config-yaml.js';
|
|
4
5
|
import { type FetchLike } from './monitor.js';
|
|
5
6
|
import type { PrereqReport } from './harness/types.js';
|
|
6
|
-
type DoctorDaemonClient = Pick<OursClient, 'version' | 'close'
|
|
7
|
+
type DoctorDaemonClient = Pick<OursClient, 'version' | 'close'> & Partial<Pick<OursClient, 'identities'>>;
|
|
7
8
|
type AttachDoctorDaemon = (options: AttachOursClientOptions) => Promise<DoctorDaemonClient>;
|
|
8
9
|
/** Host-level + per-harness prerequisite report with actionable messages. */
|
|
9
10
|
export declare function doctor(opts?: {
|
|
@@ -17,5 +18,7 @@ export declare function doctor(opts?: {
|
|
|
17
18
|
};
|
|
18
19
|
/** Override the local Codex model cache path (tests). */
|
|
19
20
|
codexCatalogPath?: string;
|
|
21
|
+
/** Compare installed service definitions with this release (read-only). */
|
|
22
|
+
serviceRegistration?: Pick<RefreshOptions, 'binPath' | 'homeDir' | 'exists' | 'processArgv'>;
|
|
20
23
|
}, exec?: Exec, platform?: NodeJS.Platform, fetchImpl?: FetchLike, attachDaemon?: AttachDoctorDaemon): Promise<PrereqReport>;
|
|
21
24
|
export {};
|
package/dist/doctor.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { userInfo
|
|
1
|
+
import { describeRegistration, refreshServiceRegistrations, registrationDrift } from './supervisor/registration-refresh.js';
|
|
2
|
+
import { userInfo } from 'node:os';
|
|
3
3
|
import { existsSync, readFileSync } from 'node:fs';
|
|
4
4
|
import { attachOursClient, } from '@ours.network/sdk/client';
|
|
5
5
|
import { realExec } from './exec.js';
|
|
6
6
|
import { isolationContextFor, loadConfig } from './config.js';
|
|
7
7
|
import { getAdapter, productionAdapters } from './harness/registry.js';
|
|
8
8
|
import { analyzeFleetPermissions, formatNative } from './permissions.js';
|
|
9
|
+
import { managedCliReport } from './managed-cli.js';
|
|
9
10
|
import { resolveBundledAcpAgent } from './harness/acp-agent.js';
|
|
10
11
|
import { agentDir, deriveXdgRuntimeDir } from './paths.js';
|
|
11
12
|
import { resolveIsolation, harnessRuntimeDir } from './isolation/policy.js';
|
|
12
13
|
import { hermesConfiguredProvider } from './harness/hermes-startup.js';
|
|
13
14
|
import { makeBubblewrapBackend } from './isolation/bubblewrap.js';
|
|
14
|
-
import { authResolutionHint, resolveEndpoint, } from './monitor.js';
|
|
15
15
|
import { readClientProfile } from './client-profile.js';
|
|
16
16
|
import { readScheduledLoops, storedLoopHealth } from './loops/state.js';
|
|
17
17
|
import { controlSocketPath } from './session/control.js';
|
|
@@ -37,25 +37,21 @@ function resolveMonitorProfiles(roles) {
|
|
|
37
37
|
const profiles = [];
|
|
38
38
|
for (const role of roles.filter(r => r.monitor?.mode === 'fleet')) {
|
|
39
39
|
const env = { ...process.env, ...(role.env ?? {}) };
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
existing.roles.push(role.name);
|
|
47
|
-
else
|
|
48
|
-
profiles.push({ client, roles: [role.name] });
|
|
40
|
+
let client;
|
|
41
|
+
try {
|
|
42
|
+
client = readClientProfile(env);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
profiles.push({ roles: [role.name], error: error instanceof Error ? error.message : 'Invalid gateway profile' });
|
|
49
46
|
continue;
|
|
50
47
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
&& p.endpoint.headers['x-ours-api-token'] === token);
|
|
48
|
+
const existing = profiles.find(p => p.client?.endpoint === client.endpoint
|
|
49
|
+
&& p.client.expectedInstanceId === client.expectedInstanceId
|
|
50
|
+
&& p.client.credentialPath === client.credentialPath);
|
|
55
51
|
if (existing)
|
|
56
52
|
existing.roles.push(role.name);
|
|
57
53
|
else
|
|
58
|
-
profiles.push({
|
|
54
|
+
profiles.push({ client, roles: [role.name] });
|
|
59
55
|
}
|
|
60
56
|
return profiles;
|
|
61
57
|
}
|
|
@@ -101,6 +97,25 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
101
97
|
// trustworthy as the answer, and a second install with the same semver and
|
|
102
98
|
// different behaviour is invisible to `--version`.
|
|
103
99
|
checks.push(...installChecks(opts.installScan));
|
|
100
|
+
if (opts.serviceRegistration) {
|
|
101
|
+
try {
|
|
102
|
+
const reports = await refreshServiceRegistrations({
|
|
103
|
+
...opts.serviceRegistration, write: false, exec, platform,
|
|
104
|
+
});
|
|
105
|
+
for (const report of reports.filter(report => report.state !== 'absent'))
|
|
106
|
+
checks.push({
|
|
107
|
+
name: `service: ${report.service}`,
|
|
108
|
+
// Same predicate as `service check`, so a pending reload is drift here too.
|
|
109
|
+
ok: registrationDrift([report]).length === 0,
|
|
110
|
+
detail: describeRegistration(report).replace(/^\S+\s+/, '')
|
|
111
|
+
+ (report.state === 'stale' ? '; run: ours-fleet service refresh' : ''),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
checks.push({ name: 'service definitions', ok: false,
|
|
116
|
+
detail: `could not inspect: ${error?.message ?? String(error)}` });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
104
119
|
const major = Number(process.versions.node.split('.')[0]);
|
|
105
120
|
checks.push({
|
|
106
121
|
name: 'node', ok: major >= 20,
|
|
@@ -156,7 +171,7 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
156
171
|
// ── Rooms/tasks checks ────────────────────────────────────────
|
|
157
172
|
if (loaded.ok && loaded.rooms) {
|
|
158
173
|
const rooms = loaded.rooms;
|
|
159
|
-
// Cowork
|
|
174
|
+
// Cowork gateway reachability
|
|
160
175
|
const coworkConfig = rooms.cowork?.config;
|
|
161
176
|
try {
|
|
162
177
|
const { createCoworkAdapter } = await import('./rooms-tasks/cowork-adapter.js');
|
|
@@ -165,14 +180,14 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
165
180
|
checks.push({
|
|
166
181
|
name: 'cowork', ok: reachable,
|
|
167
182
|
detail: reachable
|
|
168
|
-
? 'management
|
|
169
|
-
: `management
|
|
183
|
+
? 'gateway management reachable'
|
|
184
|
+
: `gateway management unreachable${coworkConfig ? ` (config: ${coworkConfig})` : ''}`,
|
|
170
185
|
});
|
|
171
186
|
}
|
|
172
187
|
catch (e) {
|
|
173
188
|
checks.push({
|
|
174
189
|
name: 'cowork', ok: false,
|
|
175
|
-
detail: `management
|
|
190
|
+
detail: `gateway management error${coworkConfig ? ` (config: ${coworkConfig})` : ''}: ${e?.message ?? e}`,
|
|
176
191
|
});
|
|
177
192
|
}
|
|
178
193
|
// Owner CID shape
|
|
@@ -219,17 +234,6 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
219
234
|
: `template '${defaultTemplate}' not found`,
|
|
220
235
|
});
|
|
221
236
|
}
|
|
222
|
-
// Shared-daemon selection coherence
|
|
223
|
-
if (rooms.cowork?.config) {
|
|
224
|
-
const { existsSync: exists } = await import('node:fs');
|
|
225
|
-
const configOk = exists(rooms.cowork.config);
|
|
226
|
-
checks.push({
|
|
227
|
-
name: 'rooms: cowork config', ok: configOk,
|
|
228
|
-
detail: configOk
|
|
229
|
-
? `cowork config at ${rooms.cowork.config}`
|
|
230
|
-
: `cowork config not found: ${rooms.cowork.config}`,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
237
|
// Hard room-management capability check
|
|
234
238
|
try {
|
|
235
239
|
const { createCoworkAdapter } = await import('./rooms-tasks/cowork-adapter.js');
|
|
@@ -273,20 +277,17 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
273
277
|
}
|
|
274
278
|
catch { /* state dir may not exist yet */ }
|
|
275
279
|
}
|
|
276
|
-
let managedSelection =
|
|
280
|
+
let managedSelection = true;
|
|
277
281
|
try {
|
|
278
282
|
// Mark explicit selection before validation so a damaged managed profile does
|
|
279
283
|
// not produce advice to start an unrelated local daemon.
|
|
280
|
-
managedSelection =
|
|
281
|
-
|| existsSync(join(process.env.HOME || homedir(), '.ours-client', 'profile.json'));
|
|
284
|
+
managedSelection = true;
|
|
282
285
|
const selected = readClientProfile(process.env);
|
|
283
286
|
managedSelection = selected !== undefined;
|
|
284
|
-
const client = await attachDaemon(
|
|
287
|
+
const client = await attachDaemon({
|
|
285
288
|
endpoint: selected.endpoint, expectedInstanceId: selected.expectedInstanceId,
|
|
286
289
|
credentialPath: selected.credentialPath, env: {}, sessionMode: 'external',
|
|
287
290
|
leaseToken: `ours-fleet-doctor-${process.pid}`,
|
|
288
|
-
} : {
|
|
289
|
-
env: process.env, leaseToken: `ours-fleet-doctor-${process.pid}`, clientPid: process.pid,
|
|
290
291
|
});
|
|
291
292
|
let daemonVersion;
|
|
292
293
|
try {
|
|
@@ -368,6 +369,32 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
368
369
|
+ `grants only ${analysis.capabilities.join(', ') || '(nothing)'}`,
|
|
369
370
|
});
|
|
370
371
|
}
|
|
372
|
+
// Managed CLI policy. Three separate rows on purpose: what Fleet generated
|
|
373
|
+
// (static), what the running session loaded, and what the supervisor audit
|
|
374
|
+
// ledger actually recorded. The first two never stand in for the third.
|
|
375
|
+
if (roles.some(role => role.managed_cli?.length)) {
|
|
376
|
+
const report = managedCliReport({ roles }, opts.configPath, { write: false, platform });
|
|
377
|
+
for (const role of report.roles.filter(item => item.setup.state !== 'not-declared')) {
|
|
378
|
+
checks.push({
|
|
379
|
+
name: `managed CLI setup: ${role.role}`,
|
|
380
|
+
ok: ['prepared', 'generated-at-launch', 'not-required'].includes(role.setup.state),
|
|
381
|
+
detail: `static: ${role.setup.state} — ${role.setup.detail}`
|
|
382
|
+
+ (['missing', 'stale'].includes(role.setup.state) ? '; run: ours-fleet managed-cli setup' : '')
|
|
383
|
+
+ (role.warnings.length ? `; ${role.warnings.join('; ')}` : ''),
|
|
384
|
+
});
|
|
385
|
+
if (role.session_policy !== 'not-applicable')
|
|
386
|
+
checks.push({
|
|
387
|
+
name: `managed CLI session: ${role.role}`, ok: true,
|
|
388
|
+
detail: role.session_policy === 'restart-required'
|
|
389
|
+
? 'the last launch loaded a different policy — restart this agent to load the current one'
|
|
390
|
+
: role.session_policy === 'never-launched' ? 'not launched since setup; the policy loads at its next start'
|
|
391
|
+
: 'the last launch loaded the current policy',
|
|
392
|
+
});
|
|
393
|
+
checks.push({
|
|
394
|
+
name: `managed CLI observed: ${role.role}`, ok: true, detail: role.observed.summary,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
371
398
|
for (const role of roles.filter(candidate => candidate.auth_proxy !== undefined)) {
|
|
372
399
|
const proxy = role.auth_proxy;
|
|
373
400
|
const credentialKeys = Object.keys(role.env ?? {}).filter(key => /^(ANTHROPIC_API_KEY|ANTHROPIC_AUTH_TOKEN|AUTHORIZATION)$/i.test(key)
|
|
@@ -448,14 +475,18 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
448
475
|
// shared-mode misconfig (401) surfaces here rather than as a silent deaf monitor.
|
|
449
476
|
const monitorProfiles = resolveMonitorProfiles(roles);
|
|
450
477
|
for (const profile of monitorProfiles) {
|
|
451
|
-
const
|
|
478
|
+
const selected = profile.client;
|
|
452
479
|
const checkName = monitorProfiles.length === 1
|
|
453
480
|
? 'monitor: daemon API'
|
|
454
481
|
: `monitor: daemon API (${profile.roles.join(', ')})`;
|
|
455
|
-
let ok = false, detail;
|
|
482
|
+
let ok = false, detail = 'gateway profile unavailable';
|
|
483
|
+
if (profile.error) {
|
|
484
|
+
checks.push({ name: checkName, ok: false, detail: profile.error });
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
456
487
|
try {
|
|
457
488
|
if (selected) {
|
|
458
|
-
const daemon = await
|
|
489
|
+
const daemon = await attachDaemon({
|
|
459
490
|
endpoint: selected.endpoint,
|
|
460
491
|
expectedInstanceId: selected.expectedInstanceId,
|
|
461
492
|
credentialPath: selected.credentialPath,
|
|
@@ -464,7 +495,7 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
464
495
|
});
|
|
465
496
|
try {
|
|
466
497
|
const [info, identities] = await Promise.all([
|
|
467
|
-
daemon.version(), daemon.identities(),
|
|
498
|
+
daemon.version(), daemon.identities?.(),
|
|
468
499
|
]);
|
|
469
500
|
if (info.name !== 'ours' || !Array.isArray(identities))
|
|
470
501
|
throw new Error('selected daemon metadata is invalid');
|
|
@@ -477,27 +508,11 @@ export async function doctor(opts = {}, exec = realExec, platform = process.plat
|
|
|
477
508
|
checks.push({ name: checkName, ok, detail });
|
|
478
509
|
continue;
|
|
479
510
|
}
|
|
480
|
-
const live = await fetchImpl(`${endpoint.origin}/state-dir`, {});
|
|
481
|
-
if (!live.ok) {
|
|
482
|
-
detail = `daemon on :${endpoint.port} answered /state-dir with HTTP ${live.status} — not the ours daemon?`;
|
|
483
|
-
}
|
|
484
|
-
else {
|
|
485
|
-
const auth = await fetchImpl(`${endpoint.origin}/identities`, { headers: endpoint.headers });
|
|
486
|
-
if (auth.status === 401)
|
|
487
|
-
detail = `reachable on :${endpoint.port} but the API token was rejected (401) — ` +
|
|
488
|
-
authResolutionHint(endpoint);
|
|
489
|
-
else if (!auth.ok)
|
|
490
|
-
detail = `reachable on :${endpoint.port} but /identities returned HTTP ${auth.status}`;
|
|
491
|
-
else {
|
|
492
|
-
ok = true;
|
|
493
|
-
detail = `reachable on :${endpoint.port}, authorized — supervisor wake stream available`;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
511
|
}
|
|
497
512
|
catch (e) {
|
|
498
|
-
const target = selected
|
|
513
|
+
const target = selected.endpoint;
|
|
499
514
|
detail = `unreachable on ${target} — monitored roles run degraded until it is up ` +
|
|
500
|
-
`(
|
|
515
|
+
`(check the configured gateway and issued credential) [${e?.message ?? e}]`;
|
|
501
516
|
}
|
|
502
517
|
checks.push({ name: checkName, ok, detail });
|
|
503
518
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const erasedArg: (value: string) => string;
|
|
2
|
+
export declare function redactErasedContent<T>(value: T): T;
|
|
3
|
+
/** Every cooperative writer filters stale in-memory snapshots under the same lock as erasure. */
|
|
4
|
+
export declare function writePrivacyFilteredLedger(path: string, value: unknown): void;
|
|
5
|
+
/** Content-free resource IDs persist to prevent active writers resurrecting erased labels. */
|
|
6
|
+
export declare function eraseResourcePresentations(resources: ReadonlyArray<{
|
|
7
|
+
kind: 'task' | 'room' | 'agent';
|
|
8
|
+
id: string;
|
|
9
|
+
}>): void;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { replaceFileAtomically, withSynchronousFileLock } from './atomic-file.js';
|
|
5
|
+
import { stateRoot } from './paths.js';
|
|
6
|
+
const registryPath = () => join(stateRoot(), 'erased-resources.json');
|
|
7
|
+
const lockPath = () => join(stateRoot(), 'locks', 'audit-erasure');
|
|
8
|
+
const ledgerNames = ['.fleet-command-audit.json', '.owner-channel-command-audit.json', '.owner-channel-lifecycle-outbox.json'];
|
|
9
|
+
export const erasedArg = (value) => `[erased:${createHash('sha256').update(value).digest('hex')}]`;
|
|
10
|
+
function registry() {
|
|
11
|
+
if (!existsSync(registryPath()))
|
|
12
|
+
return new Set();
|
|
13
|
+
const value = JSON.parse(readFileSync(registryPath(), 'utf8'));
|
|
14
|
+
if (!Array.isArray(value) || value.some(v => typeof v !== 'string'))
|
|
15
|
+
throw new Error('Invalid erasure registry');
|
|
16
|
+
return new Set(value);
|
|
17
|
+
}
|
|
18
|
+
/** Preserve delivery/deduplication metadata while removing owned presentation content. */
|
|
19
|
+
function redact(value, erased) {
|
|
20
|
+
if (Array.isArray(value))
|
|
21
|
+
return value.map(item => redact(item, erased));
|
|
22
|
+
if (!value || typeof value !== 'object')
|
|
23
|
+
return value;
|
|
24
|
+
const next = { ...value };
|
|
25
|
+
const kind = value.kind === 'lifecycle_failure' ? value.resource?.toLowerCase() : value.kind === 'agent_started' ? 'agent' : value.kind;
|
|
26
|
+
if (typeof value.id === 'string' && erased.has(`${kind}:${value.id}`)) {
|
|
27
|
+
for (const key of ['title', 'reason', 'roomName', 'label', 'template', 'configuration', 'model', 'permissions'])
|
|
28
|
+
delete next[key];
|
|
29
|
+
if (kind === 'task')
|
|
30
|
+
next.agents = [];
|
|
31
|
+
if (kind === 'room') {
|
|
32
|
+
delete next.name;
|
|
33
|
+
next.participants = [];
|
|
34
|
+
}
|
|
35
|
+
if (kind === 'agent') {
|
|
36
|
+
next.name = 'erased';
|
|
37
|
+
next.brain = '[erased]';
|
|
38
|
+
next.role = '[erased]';
|
|
39
|
+
next.inherited = [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (typeof value.roomId === 'string' && erased.has(`room:${value.roomId}`)) {
|
|
43
|
+
delete next.roomName;
|
|
44
|
+
if (kind === 'task')
|
|
45
|
+
next.agents = [];
|
|
46
|
+
}
|
|
47
|
+
const resources = value.outcome?.resourceIds;
|
|
48
|
+
const ownsAttempt = resources && Object.entries(resources).some(([key, id]) => erased.has(`${key}:${id}`));
|
|
49
|
+
const ownsPresentation = value.outcome?.presentations?.some((p) => erased.has(`${p.kind === 'agent_started' ? 'agent' : p.kind}:${p.id}`));
|
|
50
|
+
if ((ownsAttempt || ownsPresentation) && Array.isArray(value.argv) && !value.erased) {
|
|
51
|
+
next.argv = value.argv.map(erasedArg);
|
|
52
|
+
next.erased = true;
|
|
53
|
+
}
|
|
54
|
+
for (const key of Object.keys(next))
|
|
55
|
+
if (typeof next[key] === 'object')
|
|
56
|
+
next[key] = redact(next[key], erased);
|
|
57
|
+
return next;
|
|
58
|
+
}
|
|
59
|
+
export function redactErasedContent(value) { return redact(value, registry()); }
|
|
60
|
+
/** Every cooperative writer filters stale in-memory snapshots under the same lock as erasure. */
|
|
61
|
+
export function writePrivacyFilteredLedger(path, value) {
|
|
62
|
+
withSynchronousFileLock(lockPath(), () => replaceFileAtomically(path, JSON.stringify(redact(value, registry())) + '\n'));
|
|
63
|
+
}
|
|
64
|
+
/** Content-free resource IDs persist to prevent active writers resurrecting erased labels. */
|
|
65
|
+
export function eraseResourcePresentations(resources) {
|
|
66
|
+
withSynchronousFileLock(lockPath(), () => {
|
|
67
|
+
const erased = registry();
|
|
68
|
+
for (const resource of resources)
|
|
69
|
+
erased.add(`${resource.kind}:${resource.id}`);
|
|
70
|
+
replaceFileAtomically(registryPath(), JSON.stringify([...erased]));
|
|
71
|
+
for (const root of [join(stateRoot(), 'agents'), join(stateRoot(), 'tmp'), join(stateRoot(), 'recovery', 'temporary')]) {
|
|
72
|
+
if (!existsSync(root))
|
|
73
|
+
continue;
|
|
74
|
+
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
75
|
+
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
76
|
+
continue;
|
|
77
|
+
for (const name of ledgerNames) {
|
|
78
|
+
const path = join(root, entry.name, name);
|
|
79
|
+
if (!existsSync(path) || !lstatSync(path).isFile() || lstatSync(path).isSymbolicLink())
|
|
80
|
+
continue;
|
|
81
|
+
const old = JSON.parse(readFileSync(path, 'utf8'));
|
|
82
|
+
replaceFileAtomically(path, JSON.stringify(redact(old, erased)) + '\n');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|