@openrig/cli 0.6.9 → 0.6.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 +2 -2
- package/daemon/assets/onboarding/02-self-and-competent-action.md +4 -3
- package/daemon/assets/plugins/openrig-core/.claude-plugin/plugin.json +1 -1
- package/daemon/assets/plugins/openrig-core/.codex-plugin/plugin.json +1 -1
- package/daemon/assets/plugins/openrig-core/hooks/scripts/activity-relay.cjs +42 -2
- package/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md +7 -1
- package/daemon/assets/skills/rigs/SKILL.md +6 -4
- package/daemon/context-packs/help/manifest.yaml +1 -1
- package/daemon/context-packs/onboarding-width/manifest.yaml +1 -1
- package/daemon/context-packs/onboarding-width/public-what-you-can-do.md +35 -10
- package/daemon/context-packs/reference/getting-started.md +10 -6
- package/daemon/context-packs/reference/manifest.yaml +1 -1
- package/daemon/context-packs/reference/whats-new.md +146 -70
- package/daemon/context-packs/skills/agent-operated-software/manifest.yaml +1 -1
- package/daemon/context-packs/skills/agent-operated-workflows/manifest.yaml +1 -1
- package/daemon/context-packs/skills/applying-a-permission-policy/manifest.yaml +1 -1
- package/daemon/context-packs/skills/claude-compaction-restore/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/agent-starters/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/agent-startup-and-context-ingestion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/cross-host-rig-commands/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/human-in-the-loop/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/messaging-the-human/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-architect/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-cmux/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-herdr/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-skills/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-software-factory/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/openrig-upgrade/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-bundles-and-shareable-artifacts/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/rig-lifecycle/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/session-source-fork/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/specification-system/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/topology-mutation-and-seat-management/SKILL.md +2 -2
- package/daemon/context-packs/skills/core/topology-mutation-and-seat-management/manifest.yaml +1 -1
- package/daemon/context-packs/skills/core/watchdog/manifest.yaml +1 -1
- package/daemon/context-packs/skills/delegating-work/manifest.yaml +1 -1
- package/daemon/context-packs/skills/forming-an-openrig-mental-model/manifest.yaml +1 -1
- package/daemon/context-packs/skills/loading-addressable-markdown/manifest.yaml +1 -1
- package/daemon/context-packs/skills/mission-slice-sop/manifest.yaml +1 -1
- package/daemon/context-packs/skills/openrig-operating-model/manifest.yaml +1 -1
- package/daemon/context-packs/skills/openrig-user/SKILL.md +7 -1
- package/daemon/context-packs/skills/openrig-user/manifest.yaml +1 -1
- package/daemon/context-packs/skills/orienting-to-an-inherited-seat/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/backlog-capture/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/context-builder/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/exec-summary/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/office-hours/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/plan-review/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/requirements-writer/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pm/ui-mockup/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/development-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/orchestration-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/oversight-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/pods/review-team/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/agent-browser/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/context-engineering/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/dogfood/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/frontend-design/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/systematic-debugging/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/test-driven-development/manifest.yaml +1 -1
- package/daemon/context-packs/skills/process/verification-before-completion/manifest.yaml +1 -1
- package/daemon/context-packs/skills/queue-handoff/manifest.yaml +1 -1
- package/daemon/context-packs/skills/refocusing/manifest.yaml +1 -1
- package/daemon/context-packs/skills/retiring-and-inheriting-a-seat/manifest.yaml +1 -1
- package/daemon/context-packs/skills/seat-continuity-and-handover/manifest.yaml +1 -1
- package/daemon/context-packs/skills/session-compaction-and-restore/manifest.yaml +1 -1
- package/daemon/context-packs/skills/software-for-agents/manifest.yaml +1 -1
- package/daemon/context-packs/world-example/manifest.yaml +1 -1
- package/daemon/context-packs/world-public/manifest.yaml +1 -1
- package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-code-adapter.js +16 -7
- package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
- package/daemon/dist/adapters/claude-resume-launch.d.ts +4 -0
- package/daemon/dist/adapters/claude-resume-launch.d.ts.map +1 -0
- package/daemon/dist/adapters/claude-resume-launch.js +13 -0
- package/daemon/dist/adapters/claude-resume-launch.js.map +1 -0
- package/daemon/dist/adapters/claude-resume.d.ts +2 -1
- package/daemon/dist/adapters/claude-resume.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-resume.js +9 -4
- package/daemon/dist/adapters/claude-resume.js.map +1 -1
- package/daemon/dist/adapters/tmux-server.d.ts +15 -0
- package/daemon/dist/adapters/tmux-server.d.ts.map +1 -0
- package/daemon/dist/adapters/tmux-server.js +58 -0
- package/daemon/dist/adapters/tmux-server.js.map +1 -0
- package/daemon/dist/adapters/tmux.d.ts +3 -1
- package/daemon/dist/adapters/tmux.d.ts.map +1 -1
- package/daemon/dist/adapters/tmux.js +4 -2
- package/daemon/dist/adapters/tmux.js.map +1 -1
- package/daemon/dist/build-info.js +3 -3
- package/daemon/dist/db/all-migrations.d.ts.map +1 -1
- package/daemon/dist/db/all-migrations.js +4 -0
- package/daemon/dist/db/all-migrations.js.map +1 -1
- package/daemon/dist/db/migrations/099_queue_items_recovery_tags.d.ts +3 -0
- package/daemon/dist/db/migrations/099_queue_items_recovery_tags.d.ts.map +1 -0
- package/daemon/dist/db/migrations/099_queue_items_recovery_tags.js +19 -0
- package/daemon/dist/db/migrations/099_queue_items_recovery_tags.js.map +1 -0
- package/daemon/dist/db/migrations/101_claude_resume_rotation.d.ts +3 -0
- package/daemon/dist/db/migrations/101_claude_resume_rotation.d.ts.map +1 -0
- package/daemon/dist/db/migrations/101_claude_resume_rotation.js +19 -0
- package/daemon/dist/db/migrations/101_claude_resume_rotation.js.map +1 -0
- package/daemon/dist/domain/agent-activity-store.js +3 -0
- package/daemon/dist/domain/agent-activity-store.js.map +1 -1
- package/daemon/dist/domain/bootstrap-repository.js +1 -1
- package/daemon/dist/domain/bootstrap-repository.js.map +1 -1
- package/daemon/dist/domain/chat-repository.d.ts +3 -0
- package/daemon/dist/domain/chat-repository.d.ts.map +1 -1
- package/daemon/dist/domain/chat-repository.js +15 -4
- package/daemon/dist/domain/chat-repository.js.map +1 -1
- package/daemon/dist/domain/claude-managed-launch.d.ts +1 -1
- package/daemon/dist/domain/claude-managed-launch.d.ts.map +1 -1
- package/daemon/dist/domain/claude-managed-launch.js +3 -2
- package/daemon/dist/domain/claude-managed-launch.js.map +1 -1
- package/daemon/dist/domain/cmux-layout-service.d.ts.map +1 -1
- package/daemon/dist/domain/cmux-layout-service.js +2 -1
- package/daemon/dist/domain/cmux-layout-service.js.map +1 -1
- package/daemon/dist/domain/codex-git-add-dirs.js +1 -1
- package/daemon/dist/domain/codex-git-add-dirs.js.map +1 -1
- package/daemon/dist/domain/context-usage-store.d.ts.map +1 -1
- package/daemon/dist/domain/context-usage-store.js +6 -1
- package/daemon/dist/domain/context-usage-store.js.map +1 -1
- package/daemon/dist/domain/crash-cart-conductor.d.ts.map +1 -1
- package/daemon/dist/domain/crash-cart-conductor.js +3 -1
- package/daemon/dist/domain/crash-cart-conductor.js.map +1 -1
- package/daemon/dist/domain/files/file-read.d.ts.map +1 -1
- package/daemon/dist/domain/files/file-read.js +11 -3
- package/daemon/dist/domain/files/file-read.js.map +1 -1
- package/daemon/dist/domain/gateway/connections-projection.d.ts +1 -1
- package/daemon/dist/domain/gateway/slack/inbound.d.ts +21 -2
- package/daemon/dist/domain/gateway/slack/inbound.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/slack/inbound.js +70 -11
- package/daemon/dist/domain/gateway/slack/inbound.js.map +1 -1
- package/daemon/dist/domain/gateway/slack/slack-delivery.d.ts +4 -0
- package/daemon/dist/domain/gateway/slack/slack-delivery.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/slack/slack-delivery.js +1 -1
- package/daemon/dist/domain/gateway/slack/slack-delivery.js.map +1 -1
- package/daemon/dist/domain/gateway/slack/slack-subsystem.d.ts.map +1 -1
- package/daemon/dist/domain/gateway/slack/slack-subsystem.js +7 -4
- package/daemon/dist/domain/gateway/slack/slack-subsystem.js.map +1 -1
- package/daemon/dist/domain/history-query.d.ts.map +1 -1
- package/daemon/dist/domain/history-query.js +8 -6
- package/daemon/dist/domain/history-query.js.map +1 -1
- package/daemon/dist/domain/human-questions.d.ts +4 -1
- package/daemon/dist/domain/human-questions.d.ts.map +1 -1
- package/daemon/dist/domain/human-questions.js.map +1 -1
- package/daemon/dist/domain/install-engine.js +2 -2
- package/daemon/dist/domain/install-engine.js.map +1 -1
- package/daemon/dist/domain/native-process-lineage.d.ts +52 -4
- package/daemon/dist/domain/native-process-lineage.d.ts.map +1 -1
- package/daemon/dist/domain/native-process-lineage.js +224 -27
- package/daemon/dist/domain/native-process-lineage.js.map +1 -1
- package/daemon/dist/domain/node-cmux-service.d.ts.map +1 -1
- package/daemon/dist/domain/node-cmux-service.js +2 -1
- package/daemon/dist/domain/node-cmux-service.js.map +1 -1
- package/daemon/dist/domain/node-inventory.d.ts.map +1 -1
- package/daemon/dist/domain/node-inventory.js +58 -13
- package/daemon/dist/domain/node-inventory.js.map +1 -1
- package/daemon/dist/domain/progress/progress-indexer.d.ts.map +1 -1
- package/daemon/dist/domain/progress/progress-indexer.js +19 -0
- package/daemon/dist/domain/progress/progress-indexer.js.map +1 -1
- package/daemon/dist/domain/provider/codex-limit-banner.d.ts +40 -0
- package/daemon/dist/domain/provider/codex-limit-banner.d.ts.map +1 -0
- package/daemon/dist/domain/provider/codex-limit-banner.js +121 -0
- package/daemon/dist/domain/provider/codex-limit-banner.js.map +1 -0
- package/daemon/dist/domain/ps-projection.d.ts.map +1 -1
- package/daemon/dist/domain/ps-projection.js +3 -2
- package/daemon/dist/domain/ps-projection.js.map +1 -1
- package/daemon/dist/domain/queue-recovery.d.ts.map +1 -1
- package/daemon/dist/domain/queue-recovery.js +10 -3
- package/daemon/dist/domain/queue-recovery.js.map +1 -1
- package/daemon/dist/domain/queue-repository.d.ts +66 -13
- package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
- package/daemon/dist/domain/queue-repository.js +56 -40
- package/daemon/dist/domain/queue-repository.js.map +1 -1
- package/daemon/dist/domain/queue-stuck-sweep.d.ts.map +1 -1
- package/daemon/dist/domain/queue-stuck-sweep.js +5 -2
- package/daemon/dist/domain/queue-stuck-sweep.js.map +1 -1
- package/daemon/dist/domain/queue-wake-ladder.d.ts +17 -0
- package/daemon/dist/domain/queue-wake-ladder.d.ts.map +1 -1
- package/daemon/dist/domain/queue-wake-ladder.js +49 -3
- package/daemon/dist/domain/queue-wake-ladder.js.map +1 -1
- package/daemon/dist/domain/restore-guidance.d.ts +39 -0
- package/daemon/dist/domain/restore-guidance.d.ts.map +1 -0
- package/daemon/dist/domain/restore-guidance.js +163 -0
- package/daemon/dist/domain/restore-guidance.js.map +1 -0
- package/daemon/dist/domain/restore-orchestrator.d.ts +6 -1
- package/daemon/dist/domain/restore-orchestrator.d.ts.map +1 -1
- package/daemon/dist/domain/restore-orchestrator.js +160 -6
- package/daemon/dist/domain/restore-orchestrator.js.map +1 -1
- package/daemon/dist/domain/runtime-adapter.d.ts +2 -0
- package/daemon/dist/domain/runtime-adapter.d.ts.map +1 -1
- package/daemon/dist/domain/runtime-adapter.js.map +1 -1
- package/daemon/dist/domain/scope/scope-view-projection.d.ts.map +1 -1
- package/daemon/dist/domain/scope/scope-view-projection.js +5 -7
- package/daemon/dist/domain/scope/scope-view-projection.js.map +1 -1
- package/daemon/dist/domain/seat-attention-reconciler.d.ts +5 -2
- package/daemon/dist/domain/seat-attention-reconciler.d.ts.map +1 -1
- package/daemon/dist/domain/seat-attention-reconciler.js +18 -4
- package/daemon/dist/domain/seat-attention-reconciler.js.map +1 -1
- package/daemon/dist/domain/seat-identity-reconciler.d.ts.map +1 -1
- package/daemon/dist/domain/seat-identity-reconciler.js +7 -2
- package/daemon/dist/domain/seat-identity-reconciler.js.map +1 -1
- package/daemon/dist/domain/seat-lifecycle-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-status-service.d.ts +2 -1
- package/daemon/dist/domain/seat-status-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-status-service.js +1 -0
- package/daemon/dist/domain/seat-status-service.js.map +1 -1
- package/daemon/dist/domain/seat-structural-activity-service.d.ts +9 -1
- package/daemon/dist/domain/seat-structural-activity-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-structural-activity-service.js +28 -4
- package/daemon/dist/domain/seat-structural-activity-service.js.map +1 -1
- package/daemon/dist/domain/seat-switch-client-service.d.ts.map +1 -1
- package/daemon/dist/domain/seat-switch-client-service.js +2 -1
- package/daemon/dist/domain/seat-switch-client-service.js.map +1 -1
- package/daemon/dist/domain/session-registry.d.ts +46 -0
- package/daemon/dist/domain/session-registry.d.ts.map +1 -1
- package/daemon/dist/domain/session-registry.js +86 -4
- package/daemon/dist/domain/session-registry.js.map +1 -1
- package/daemon/dist/domain/session-transport.d.ts +13 -1
- package/daemon/dist/domain/session-transport.d.ts.map +1 -1
- package/daemon/dist/domain/session-transport.js +101 -5
- package/daemon/dist/domain/session-transport.js.map +1 -1
- package/daemon/dist/domain/startup-orchestrator.d.ts +8 -0
- package/daemon/dist/domain/startup-orchestrator.d.ts.map +1 -1
- package/daemon/dist/domain/startup-orchestrator.js +37 -1
- package/daemon/dist/domain/startup-orchestrator.js.map +1 -1
- package/daemon/dist/domain/terminal/terminal-service.d.ts +5 -1
- package/daemon/dist/domain/terminal/terminal-service.d.ts.map +1 -1
- package/daemon/dist/domain/terminal/terminal-service.js +30 -4
- package/daemon/dist/domain/terminal/terminal-service.js.map +1 -1
- package/daemon/dist/domain/terminal/view-composer.d.ts +6 -0
- package/daemon/dist/domain/terminal/view-composer.d.ts.map +1 -1
- package/daemon/dist/domain/terminal/view-composer.js +2 -1
- package/daemon/dist/domain/terminal/view-composer.js.map +1 -1
- package/daemon/dist/domain/transcript-store.js +1 -1
- package/daemon/dist/domain/transcript-store.js.map +1 -1
- package/daemon/dist/domain/types.d.ts +9 -0
- package/daemon/dist/domain/types.d.ts.map +1 -1
- package/daemon/dist/domain/types.js +5 -0
- package/daemon/dist/domain/types.js.map +1 -1
- package/daemon/dist/domain/usage-series.d.ts.map +1 -1
- package/daemon/dist/domain/usage-series.js +9 -4
- package/daemon/dist/domain/usage-series.js.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.js +13 -0
- package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
- package/daemon/dist/domain/view-projector.d.ts +4 -0
- package/daemon/dist/domain/view-projector.d.ts.map +1 -1
- package/daemon/dist/domain/view-projector.js +19 -4
- package/daemon/dist/domain/view-projector.js.map +1 -1
- package/daemon/dist/domain/workflow-runtime.d.ts +1 -1
- package/daemon/dist/routes/activity.d.ts.map +1 -1
- package/daemon/dist/routes/activity.js +33 -1
- package/daemon/dist/routes/activity.js.map +1 -1
- package/daemon/dist/routes/chat.d.ts.map +1 -1
- package/daemon/dist/routes/chat.js +6 -2
- package/daemon/dist/routes/chat.js.map +1 -1
- package/daemon/dist/routes/projects.d.ts.map +1 -1
- package/daemon/dist/routes/projects.js +5 -1
- package/daemon/dist/routes/projects.js.map +1 -1
- package/daemon/dist/routes/query-limit.d.ts +19 -0
- package/daemon/dist/routes/query-limit.d.ts.map +1 -0
- package/daemon/dist/routes/query-limit.js +24 -0
- package/daemon/dist/routes/query-limit.js.map +1 -0
- package/daemon/dist/routes/queue.d.ts.map +1 -1
- package/daemon/dist/routes/queue.js +18 -7
- package/daemon/dist/routes/queue.js.map +1 -1
- package/daemon/dist/routes/rig-cmux.js +8 -10
- package/daemon/dist/routes/rig-cmux.js.map +1 -1
- package/daemon/dist/routes/rigs.d.ts.map +1 -1
- package/daemon/dist/routes/rigs.js +6 -4
- package/daemon/dist/routes/rigs.js.map +1 -1
- package/daemon/dist/routes/stream.d.ts.map +1 -1
- package/daemon/dist/routes/stream.js +5 -1
- package/daemon/dist/routes/stream.js.map +1 -1
- package/daemon/dist/routes/up.d.ts.map +1 -1
- package/daemon/dist/routes/up.js +2 -1
- package/daemon/dist/routes/up.js.map +1 -1
- package/daemon/dist/routes/views.d.ts.map +1 -1
- package/daemon/dist/routes/views.js +7 -1
- package/daemon/dist/routes/views.js.map +1 -1
- package/daemon/dist/startup.d.ts.map +1 -1
- package/daemon/dist/startup.js +19 -0
- package/daemon/dist/startup.js.map +1 -1
- package/daemon/docs/reference/getting-started.md +10 -6
- package/daemon/docs/reference/slack-app-setup.md +6 -0
- package/daemon/docs/reference/whats-new.md +146 -70
- package/daemon/specs/agents/development/qa/guidance/role.md +9 -0
- package/daemon/specs/agents/shared/skills/core/topology-mutation-and-seat-management/SKILL.md +2 -2
- package/daemon/specs/rigs/launch/factory/CULTURE.md +13 -0
- package/daemon/specs/rigs/launch/factory/guidance/lead-first-move.md +18 -5
- package/daemon/specs/rigs/launch/kernel/agents/operator/agent/guidance/role.md +20 -1
- package/daemon/specs/rigs/launch/starter/CULTURE.md +13 -0
- package/daemon/specs/rigs/launch/starter/guidance/lead-first-move.md +18 -5
- package/dist/build-info.js +3 -3
- package/dist/cli-error.d.ts.map +1 -1
- package/dist/cli-error.js +2 -0
- package/dist/cli-error.js.map +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +55 -4
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/capture.d.ts +9 -0
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +93 -41
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +4 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +37 -3
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +1 -50
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +6 -0
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/heartbeat.js +2 -2
- package/dist/commands/heartbeat.js.map +1 -1
- package/dist/commands/ps.d.ts +3 -0
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +8 -3
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/queue.d.ts +39 -6
- package/dist/commands/queue.d.ts.map +1 -1
- package/dist/commands/queue.js +127 -33
- package/dist/commands/queue.js.map +1 -1
- package/dist/commands/seat.d.ts.map +1 -1
- package/dist/commands/seat.js +6 -0
- package/dist/commands/seat.js.map +1 -1
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +100 -44
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +5 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/usage.d.ts.map +1 -1
- package/dist/commands/usage.js +10 -5
- package/dist/commands/usage.js.map +1 -1
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +8 -8
- package/dist/commands/workflow.js.map +1 -1
- package/dist/config-store.d.ts +2 -1
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +14 -0
- package/dist/config-store.js.map +1 -1
- package/dist/daemon-lifecycle.d.ts +4 -0
- package/dist/daemon-lifecycle.d.ts.map +1 -1
- package/dist/daemon-lifecycle.js +16 -4
- package/dist/daemon-lifecycle.js.map +1 -1
- package/dist/lib/scope/capability-delta.d.ts.map +1 -1
- package/dist/lib/scope/capability-delta.js +8 -0
- package/dist/lib/scope/capability-delta.js.map +1 -1
- package/dist/lib/scope/progress-edit.js +1 -1
- package/dist/lib/scope/progress-edit.js.map +1 -1
- package/dist/lib/scope/scope-fs.js +3 -3
- package/dist/lib/scope/scope-fs.js.map +1 -1
- package/dist/rig-handle.d.ts +45 -0
- package/dist/rig-handle.d.ts.map +1 -0
- package/dist/rig-handle.js +51 -0
- package/dist/rig-handle.js.map +1 -0
- package/dist/system-preflight.d.ts +5 -0
- package/dist/system-preflight.d.ts.map +1 -1
- package/dist/system-preflight.js +8 -0
- package/dist/system-preflight.js.map +1 -1
- package/dist/terminal-window.d.ts.map +1 -1
- package/dist/terminal-window.js +3 -1
- package/dist/terminal-window.js.map +1 -1
- package/package.json +1 -1
- package/tui/dist/config/config-model.d.ts.map +1 -1
- package/tui/dist/config/config-model.js +1 -0
- package/tui/dist/config/config-model.js.map +1 -1
- package/tui/dist/daemon-client.d.ts +3 -0
- package/tui/dist/daemon-client.d.ts.map +1 -1
- package/tui/dist/daemon-client.js +4 -1
- package/tui/dist/daemon-client.js.map +1 -1
- package/tui/dist/detail.d.ts.map +1 -1
- package/tui/dist/detail.js +6 -1
- package/tui/dist/detail.js.map +1 -1
- package/tui/dist/hydrate.d.ts.map +1 -1
- package/tui/dist/hydrate.js +19 -17
- package/tui/dist/hydrate.js.map +1 -1
- package/tui/dist/input.d.ts.map +1 -1
- package/tui/dist/input.js +15 -4
- package/tui/dist/input.js.map +1 -1
- package/tui/dist/local-reading.js +2 -2
- package/tui/dist/local-reading.js.map +1 -1
- package/tui/dist/reading.d.ts.map +1 -1
- package/tui/dist/reading.js +14 -3
- package/tui/dist/reading.js.map +1 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// A resumed seat's working guidance.
|
|
2
|
+
//
|
|
3
|
+
// An exact resume replays no startup content (the replay containment in restore-orchestrator.ts),
|
|
4
|
+
// because managed CLAUDE.md blocks were once rewritten during a resume. Ordinary `rig down` still
|
|
5
|
+
// strips OpenRig's managed blocks from each seat's guidance file, so an exact resume came back with
|
|
6
|
+
// no role, culture or SOP guidance (and the rig reported fully_restored). The exception is narrow:
|
|
7
|
+
// before the native harness starts, put back only the managed guidance blocks that are MISSING,
|
|
8
|
+
// from the saved startup selection (guidance projections and guidance_merge startup files). An
|
|
9
|
+
// existing block is never refreshed or overwritten; nothing is sent to the conversation; no
|
|
10
|
+
// startup action, skill or plugin runs; no profile is resolved again. The blocks are rebuilt from
|
|
11
|
+
// the saved source paths' current bytes, not from a byte snapshot of the old file.
|
|
12
|
+
//
|
|
13
|
+
// Guidance problems never block the exact resume. What can't be put back is reported.
|
|
14
|
+
import nodePath from "node:path";
|
|
15
|
+
import { MANAGED_BLOCK_START, MANAGED_BLOCK_END, DEFAULT_CLAUDE_MANAGED_BLOCK_FILE, mergeManagedBlock, stripManagedBlocks, } from "./managed-blocks.js";
|
|
16
|
+
import { resolveConcreteHint } from "./runtime-adapter.js";
|
|
17
|
+
import { reanchorBuiltinStartupFile, reanchorShippedProjectionEntry } from "./builtin-startup-files.js";
|
|
18
|
+
const LEGACY_BLOCK_START = (id) => `<!-- BEGIN RIGGED MANAGED BLOCK: ${id} -->`;
|
|
19
|
+
const LEGACY_BLOCK_END = (id) => `<!-- END RIGGED MANAGED BLOCK: ${id} -->`;
|
|
20
|
+
/** The per-seat role block is delivered through send_text, never merged into a shared file
|
|
21
|
+
* (ADR-0006); the adapters skip it, and so does this. */
|
|
22
|
+
const NEVER_MERGED = new Set(["rig-role"]);
|
|
23
|
+
/** The guidance file a seat's managed blocks live in, and the blocks it should hold on restore. */
|
|
24
|
+
export function seatGuidance(startupCtx, cwd, claudeManagedBlockFile, exists, readFile) {
|
|
25
|
+
if (!startupCtx || !cwd)
|
|
26
|
+
return null;
|
|
27
|
+
const fileName = startupCtx.runtime === "claude-code"
|
|
28
|
+
? (claudeManagedBlockFile ?? DEFAULT_CLAUDE_MANAGED_BLOCK_FILE)
|
|
29
|
+
: startupCtx.runtime === "codex" ? "AGENTS.md" : null;
|
|
30
|
+
if (!fileName)
|
|
31
|
+
return null;
|
|
32
|
+
const items = new Map();
|
|
33
|
+
for (const saved of startupCtx.projectionEntries) {
|
|
34
|
+
if (saved.category !== "guidance" || saved.mergeStrategy !== "managed_block")
|
|
35
|
+
continue;
|
|
36
|
+
const e = reanchorShippedProjectionEntry(saved, undefined, exists);
|
|
37
|
+
items.set(e.effectiveId, { blockId: e.effectiveId, sourcePath: e.absolutePath });
|
|
38
|
+
}
|
|
39
|
+
// Every guidance startup file the last launch merged, whatever its appliesOn: a fresh-start-only
|
|
40
|
+
// file (onboarding, an agent starter) was merged at that launch and stayed in the file until
|
|
41
|
+
// `rig down` stripped it, so it is part of what the resumed conversation had.
|
|
42
|
+
for (const saved of startupCtx.resolvedStartupFiles) {
|
|
43
|
+
const f = reanchorBuiltinStartupFile(saved, undefined, undefined, exists);
|
|
44
|
+
// An "auto" file is classified from its content, as at launch (a `# SKILL` file is a skill,
|
|
45
|
+
// not guidance). If the source can't be read it can't be classified: it is reported, not dropped.
|
|
46
|
+
let hint = f.deliveryHint;
|
|
47
|
+
if (hint === "auto") {
|
|
48
|
+
try {
|
|
49
|
+
hint = resolveConcreteHint(f.path, readFile(f.absolutePath));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
if (f.path.endsWith(".md") && !f.path.endsWith("SKILL.md")) {
|
|
53
|
+
items.set(f.path, { blockId: f.path, sourcePath: f.absolutePath, unresolved: true });
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (hint !== "guidance_merge")
|
|
59
|
+
continue;
|
|
60
|
+
items.set(f.path, { blockId: f.path, sourcePath: f.absolutePath });
|
|
61
|
+
}
|
|
62
|
+
for (const id of NEVER_MERGED)
|
|
63
|
+
items.delete(id);
|
|
64
|
+
return { targetPath: nodePath.join(cwd, fileName), items: [...items.values()] };
|
|
65
|
+
}
|
|
66
|
+
/** A block counts only with both its markers (current or legacy form). A lone marker is incomplete:
|
|
67
|
+
* writing next to it is unsafe, because cleanup strips from a BEGIN to the next END. */
|
|
68
|
+
function blockState(content, blockId) {
|
|
69
|
+
const current = [content.includes(MANAGED_BLOCK_START(blockId)), content.includes(MANAGED_BLOCK_END(blockId))];
|
|
70
|
+
const legacy = [content.includes(LEGACY_BLOCK_START(blockId)), content.includes(LEGACY_BLOCK_END(blockId))];
|
|
71
|
+
if ((current[0] && current[1]) || (legacy[0] && legacy[1]))
|
|
72
|
+
return "complete";
|
|
73
|
+
if (current[0] || current[1] || legacy[0] || legacy[1])
|
|
74
|
+
return "incomplete";
|
|
75
|
+
return "absent";
|
|
76
|
+
}
|
|
77
|
+
function blockStates(guidance, fs) {
|
|
78
|
+
const content = fs.exists(guidance.targetPath) ? fs.readFile(guidance.targetPath) : "";
|
|
79
|
+
return new Map(guidance.items.map((item) => [item.blockId, blockState(content, item.blockId)]));
|
|
80
|
+
}
|
|
81
|
+
/** The block ids the seat's guidance file lacks right now (absent, or only partly there). */
|
|
82
|
+
export function missingGuidanceBlocks(guidance, fs) {
|
|
83
|
+
return [...blockStates(guidance, fs)].filter(([, state]) => state !== "complete").map(([id]) => id);
|
|
84
|
+
}
|
|
85
|
+
/** Put back only the missing managed guidance blocks. Existing blocks and any other text in the
|
|
86
|
+
* file are left exactly as they are. Never throws: a failure becomes a reported gap. */
|
|
87
|
+
/** Would appending these blocks to `content` be safe for the next `rig down`? Decided by effect,
|
|
88
|
+
* with cleanup itself: safe only when stripping the new file gives exactly what stripping the
|
|
89
|
+
* current one gives, so the added blocks strip away cleanly and take nothing else with them. A
|
|
90
|
+
* stray, truncated or misplaced marker (cleanup strips from any BEGIN to the next END that ends a
|
|
91
|
+
* line) makes the two differ. No second marker grammar to keep in step with cleanup. */
|
|
92
|
+
export function appendIsCleanupSafe(content, blocks) {
|
|
93
|
+
let candidate = content;
|
|
94
|
+
const memory = {
|
|
95
|
+
exists: () => true,
|
|
96
|
+
readFile: () => candidate,
|
|
97
|
+
writeFile: (_path, next) => { candidate = next; },
|
|
98
|
+
};
|
|
99
|
+
for (const block of blocks)
|
|
100
|
+
mergeManagedBlock(memory, "(in memory)", block.blockId, block.content);
|
|
101
|
+
return stripManagedBlocks(candidate) === stripManagedBlocks(content);
|
|
102
|
+
}
|
|
103
|
+
/** Put back only the missing managed guidance blocks. Existing blocks and any other text in the
|
|
104
|
+
* file are left exactly as they are, and nothing is written unless cleanup would later remove
|
|
105
|
+
* exactly what was added. Never throws: a failure becomes a reported gap. */
|
|
106
|
+
export function restoreMissingGuidance(guidance, fs) {
|
|
107
|
+
const repair = { restored: [], gaps: [] };
|
|
108
|
+
let states;
|
|
109
|
+
let existing;
|
|
110
|
+
try {
|
|
111
|
+
states = blockStates(guidance, fs);
|
|
112
|
+
existing = fs.exists(guidance.targetPath) ? fs.readFile(guidance.targetPath) : null;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
repair.gaps.push(`could not read ${guidance.targetPath}: ${err.message}`);
|
|
116
|
+
return repair;
|
|
117
|
+
}
|
|
118
|
+
const toWrite = [];
|
|
119
|
+
for (const item of guidance.items) {
|
|
120
|
+
const state = states.get(item.blockId);
|
|
121
|
+
if (state === "complete")
|
|
122
|
+
continue;
|
|
123
|
+
if (state === "incomplete") {
|
|
124
|
+
repair.gaps.push(`${item.blockId}: ${guidance.targetPath} holds only part of this block (one marker); left as it is`);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (item.unresolved) {
|
|
128
|
+
repair.gaps.push(`${item.blockId}: its source ${item.sourcePath} can't be read, so this older startup file can't be classified or put back`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
try {
|
|
132
|
+
if (!fs.exists(item.sourcePath)) {
|
|
133
|
+
repair.gaps.push(`${item.blockId}: its source ${item.sourcePath} no longer exists`);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
toWrite.push({ blockId: item.blockId, content: fs.readFile(item.sourcePath) });
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
repair.gaps.push(`${item.blockId}: ${err.message}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (toWrite.length === 0)
|
|
143
|
+
return repair;
|
|
144
|
+
// A file that doesn't exist yet holds no text to lose. An existing one is written only if the
|
|
145
|
+
// next rig down would remove exactly what is added.
|
|
146
|
+
if (existing !== null && !appendIsCleanupSafe(existing, toWrite)) {
|
|
147
|
+
for (const block of toWrite) {
|
|
148
|
+
repair.gaps.push(`${block.blockId}: not written, because ${guidance.targetPath} has a managed-block marker that the next rig down would strip together with other text, so adding blocks there could cost that text`);
|
|
149
|
+
}
|
|
150
|
+
return repair;
|
|
151
|
+
}
|
|
152
|
+
for (const block of toWrite) {
|
|
153
|
+
try {
|
|
154
|
+
mergeManagedBlock(fs, guidance.targetPath, block.blockId, block.content);
|
|
155
|
+
repair.restored.push(block.blockId);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
repair.gaps.push(`${block.blockId}: ${err.message}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return repair;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=restore-guidance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-guidance.js","sourceRoot":"","sources":["../../src/domain/restore-guidance.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type Database from "better-sqlite3";
|
|
2
2
|
import type { RigRepository } from "./rig-repository.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type SessionRegistry } from "./session-registry.js";
|
|
4
4
|
import type { EventBus } from "./event-bus.js";
|
|
5
5
|
import type { SnapshotRepository } from "./snapshot-repository.js";
|
|
6
6
|
import type { SnapshotCapture } from "./snapshot-capture.js";
|
|
@@ -180,6 +180,11 @@ export declare class RestoreOrchestrator {
|
|
|
180
180
|
private restoreNodeState;
|
|
181
181
|
private computeRestorePlan;
|
|
182
182
|
private restoreNodeWithCompensation;
|
|
183
|
+
/** A seat that came back running should also have its role, culture and SOP guidance. If its
|
|
184
|
+
* guidance file still lacks a managed block it should hold, the seat keeps its true status (a
|
|
185
|
+
* live resumed session is still running) and the gap is disclosed on the node and in the
|
|
186
|
+
* warnings, so the rig is reported partially_restored, not fully_restored. */
|
|
187
|
+
private checkRestoredGuidance;
|
|
183
188
|
/** OPR.0.3.4.2 (B) — roll a just-launched session back to ZERO sessions for
|
|
184
189
|
* the awaiting-decision outcome: kill the live blank session, mark its row
|
|
185
190
|
* superseded, and restore the prior binding/session state (the existing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore-orchestrator.d.ts","sourceRoot":"","sources":["../../src/domain/restore-orchestrator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"restore-orchestrator.d.ts","sourceRoot":"","sources":["../../src/domain/restore-orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { nonInterruptiveNotice, nonInterruptiveSummary } from "../adapters/non-interruptive.js";
|
|
2
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { NativePermissionStore } from "./native-permission-store.js";
|
|
5
5
|
import { resolvePermissionPolicyAttachment } from "./permission-policy/policy-ref.js";
|
|
6
|
+
import { claudeResumeRotation } from "./session-registry.js";
|
|
6
7
|
import { assessNativeResumeProbe } from "./native-resume-probe.js";
|
|
7
|
-
import { verifyClaudePaneProcess } from "./native-process-lineage.js";
|
|
8
|
+
import { observeClaudeDelivery, observeClaudeResumeLaunch, verifyClaudePaneProcess } from "./native-process-lineage.js";
|
|
8
9
|
import { reanchorBuiltinStartupFile, reanchorShippedProjectionEntry } from "./builtin-startup-files.js";
|
|
10
|
+
import { seatGuidance, restoreMissingGuidance, missingGuidanceBlocks } from "./restore-guidance.js";
|
|
9
11
|
import { AppliedLaunchObservationStore } from "./applied-launch-observation-store.js";
|
|
10
12
|
import { classifyPaneRuntimeMatch } from "./seat-identity-reconciler.js";
|
|
11
13
|
import { isShellForeground } from "./shell-classifier.js";
|
|
@@ -30,6 +32,9 @@ export function rollupRestoreRigResult(nodes) {
|
|
|
30
32
|
const allFailed = nodes.every((node) => node.status === "failed");
|
|
31
33
|
if (allFailed)
|
|
32
34
|
return "failed";
|
|
35
|
+
// A seat running without part of its guidance keeps its own status; the rig isn't fully restored.
|
|
36
|
+
if (nodes.some((node) => (node.guidanceGaps?.length ?? 0) > 0))
|
|
37
|
+
return "partially_restored";
|
|
33
38
|
if (nodes.some((node) => node.status === "fresh" || node.status === "fresh-primed" || node.status === "awaiting-decision" || node.status === "failed" || node.status === "attention_required")) {
|
|
34
39
|
return "partially_restored";
|
|
35
40
|
}
|
|
@@ -48,6 +53,25 @@ export const NON_RUNNING_LAUNCH_STATUSES = new Set([
|
|
|
48
53
|
export function launchStatusIsRunning(status) {
|
|
49
54
|
return !NON_RUNNING_LAUNCH_STATUSES.has(status);
|
|
50
55
|
}
|
|
56
|
+
/** What `rig launch` does for this node from this snapshot without --fresh, read as the restore path reads it: the
|
|
57
|
+
* occupant, then the pre-launch stop-and-ask check, then the resume decision (restoreNodeWithCompensation and the
|
|
58
|
+
* resume step after it). An exited agent's message offers stop-then-launch as a resume only when this says so. */
|
|
59
|
+
function snapshotLaunchOutcome(data, nodeId) {
|
|
60
|
+
const occupant = resolveActiveSnapshotSession(data, nodeId);
|
|
61
|
+
if (occupant.kind === "ambiguous")
|
|
62
|
+
return { kind: "unrecoverable", why: "can't tell which saved session is this seat's" };
|
|
63
|
+
const session = occupant.kind === "resolved" ? occupant.session : null;
|
|
64
|
+
if (!session)
|
|
65
|
+
return { kind: "fresh", why: "saves no session for this seat" };
|
|
66
|
+
const policy = session.restorePolicy ?? "resume_if_possible";
|
|
67
|
+
if (policy !== "resume_if_possible")
|
|
68
|
+
return { kind: "fresh", why: `saves this seat with restore policy '${policy}'` };
|
|
69
|
+
if (!session.resumeToken)
|
|
70
|
+
return { kind: "decision", why: "has no resume token for this seat" };
|
|
71
|
+
if (!session.resumeType || session.resumeType === "none")
|
|
72
|
+
return { kind: "fresh", why: "records no resume source for this seat" };
|
|
73
|
+
return { kind: "resume" };
|
|
74
|
+
}
|
|
51
75
|
export class RestoreOrchestrator {
|
|
52
76
|
db;
|
|
53
77
|
activeRestores = new Set();
|
|
@@ -334,11 +358,28 @@ export class RestoreOrchestrator {
|
|
|
334
358
|
.filter((s) => s.nodeId === node.id && s.status === "running");
|
|
335
359
|
let isLive = false;
|
|
336
360
|
let isUnknown = false;
|
|
361
|
+
let idleSession;
|
|
337
362
|
for (const session of sessions) {
|
|
338
363
|
try {
|
|
339
364
|
const alive = await this.tmuxAdapter.hasSession(session.sessionName);
|
|
340
365
|
if (alive) {
|
|
366
|
+
// A preserved shell is not a running agent. Reuse the process-lineage
|
|
367
|
+
// check's positive idle-shell evidence; opaque wrappers stay untouched.
|
|
341
368
|
isLive = true;
|
|
369
|
+
const binding = this.sessionRegistry.getBindingForNode(node.id);
|
|
370
|
+
const pane = binding?.tmuxSession === session.sessionName ? binding.tmuxPane : null;
|
|
371
|
+
const runtime = allNodes.find(current => current.id === node.id)?.runtime ?? node.runtime;
|
|
372
|
+
// Launch needs consistent positive evidence: both samples idle with the same fingerprint, and the
|
|
373
|
+
// bound pane still in this session (a recycled pane id could name another session's shell).
|
|
374
|
+
if (pane && ["claude-code", "codex", "pi", "omp"].includes(runtime ?? "")
|
|
375
|
+
&& isShellForeground(await this.tmuxAdapter.getPaneCommand(pane) ?? "")
|
|
376
|
+
&& (await this.tmuxAdapter.listPanes(session.sessionName)).some(candidate => candidate.id === pane)
|
|
377
|
+
&& (await observeClaudeDelivery({ target: pane, tmux: this.tmuxAdapter, listProcesses: this.listProcesses }, { unknownKeepsIdle: false })).state === "idle_shell"
|
|
378
|
+
&& isShellForeground(await this.tmuxAdapter.getPaneCommand(pane) ?? "")) {
|
|
379
|
+
idleSession = session.sessionName;
|
|
380
|
+
isLive = false;
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
342
383
|
break;
|
|
343
384
|
}
|
|
344
385
|
}
|
|
@@ -350,6 +391,26 @@ export class RestoreOrchestrator {
|
|
|
350
391
|
alreadyRunning.push({ nodeId: node.id, logicalId: node.logicalId });
|
|
351
392
|
continue;
|
|
352
393
|
}
|
|
394
|
+
if (idleSession) {
|
|
395
|
+
// Keep the pane/history and the existing per-target failure contract.
|
|
396
|
+
// Choosing a fresh versus resumed conversation belongs to the person. Stopping closes the pane, so
|
|
397
|
+
// stop-then-launch is offered as a resume only when this snapshot can resume the seat; otherwise the
|
|
398
|
+
// message says what that launch would do instead. The command pins the snapshot that was checked.
|
|
399
|
+
const outcome = snapshotLaunchOutcome(snapshot.data, node.id);
|
|
400
|
+
const launchCommand = `rig launch ${rigId} ${node.logicalId} --snapshot-id ${snapshot.id}`;
|
|
401
|
+
const relaunch = outcome.kind === "resume"
|
|
402
|
+
? `To resume its conversation: rig seat stop ${idleSession} --reason "<why>", then ${launchCommand} (this closes the pane, and launch resumes from that snapshot's resume token). `
|
|
403
|
+
: `Stopping it and launching from snapshot ${snapshot.id} won't resume this conversation: that snapshot ${outcome.why}, so launch would `
|
|
404
|
+
+ `${outcome.kind === "fresh" ? "start a fresh conversation" : outcome.kind === "decision" ? "start nothing and ask for a decision" : "fail"}. `;
|
|
405
|
+
launched.push({
|
|
406
|
+
nodeId: node.id, logicalId: node.logicalId, status: "attention_required",
|
|
407
|
+
error: `Session alive, agent not running for '${node.logicalId}': tmux session '${idleSession}' holds an idle shell, and its pane and history are preserved. `
|
|
408
|
+
+ `The person chooses how to bring the agent back. ${relaunch}`
|
|
409
|
+
+ `To start a blank occupant: rig seat launch ${idleSession} --fresh --stop --reason "<why>". `
|
|
410
|
+
+ `To keep the pane: attach to tmux session '${idleSession}' and restart the agent there by hand.`,
|
|
411
|
+
});
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
353
414
|
if (isUnknown) {
|
|
354
415
|
// OPR.0.4.3.28 correction — INVERT the fail-closed-on-unknown launch default. A failed tmux
|
|
355
416
|
// liveness probe is NOT positive evidence of a live seat (only isLive, above, is). Deny-by-
|
|
@@ -724,7 +785,39 @@ export class RestoreOrchestrator {
|
|
|
724
785
|
if (launchResult.warnings?.length) {
|
|
725
786
|
warnings?.push(...launchResult.warnings);
|
|
726
787
|
}
|
|
727
|
-
|
|
788
|
+
const restored = await this.postLaunchRestore(entry, rigId, data, launchResult.sessionName, launchResult, opts, warnings, priorState);
|
|
789
|
+
return this.checkRestoredGuidance(restored, entry.node, rigId, data, warnings);
|
|
790
|
+
}
|
|
791
|
+
/** A seat that came back running should also have its role, culture and SOP guidance. If its
|
|
792
|
+
* guidance file still lacks a managed block it should hold, the seat keeps its true status (a
|
|
793
|
+
* live resumed session is still running) and the gap is disclosed on the node and in the
|
|
794
|
+
* warnings, so the rig is reported partially_restored, not fully_restored. */
|
|
795
|
+
checkRestoredGuidance(result, node, rigId, data, warnings) {
|
|
796
|
+
// Every status with a live session; attention_required keeps its status and gains the disclosure.
|
|
797
|
+
if (!["resumed", "fresh-primed", "fresh", "rebuilt", "attention_required"].includes(result.status))
|
|
798
|
+
return result;
|
|
799
|
+
let guidance;
|
|
800
|
+
try {
|
|
801
|
+
guidance = seatGuidance(data.nodeStartupContext?.[node.id] ?? null, node.cwd, this.rigRepo.getRigClaudeManagedBlockFile(rigId), existsSync, (path) => readFileSync(path, "utf-8"));
|
|
802
|
+
}
|
|
803
|
+
catch (err) {
|
|
804
|
+
warnings?.push(`Restore: ${node.logicalId}: could not check its guidance: ${err.message}`);
|
|
805
|
+
return { ...result, guidanceGaps: ["(guidance check failed)"] };
|
|
806
|
+
}
|
|
807
|
+
if (!guidance || guidance.items.length === 0)
|
|
808
|
+
return result;
|
|
809
|
+
let missing;
|
|
810
|
+
try {
|
|
811
|
+
missing = missingGuidanceBlocks(guidance, { exists: existsSync, readFile: (path) => readFileSync(path, "utf-8") });
|
|
812
|
+
}
|
|
813
|
+
catch (err) {
|
|
814
|
+
missing = [`(could not read ${guidance.targetPath}: ${err.message})`];
|
|
815
|
+
}
|
|
816
|
+
if (missing.length === 0)
|
|
817
|
+
return result;
|
|
818
|
+
const gap = `${node.logicalId} is running without part of its guidance: ${guidance.targetPath} lacks the OpenRig blocks ${missing.join(", ")}.`;
|
|
819
|
+
warnings?.push(`Restore: ${gap}`);
|
|
820
|
+
return { ...result, guidanceGaps: missing };
|
|
728
821
|
}
|
|
729
822
|
/** OPR.0.3.4.2 (B) — roll a just-launched session back to ZERO sessions for
|
|
730
823
|
* the awaiting-decision outcome: kill the live blank session, mark its row
|
|
@@ -804,6 +897,34 @@ export class RestoreOrchestrator {
|
|
|
804
897
|
warnings?.push(`Restore activity hooks: ${error.message}`);
|
|
805
898
|
}
|
|
806
899
|
}
|
|
900
|
+
// A narrow exception to the replay containment below: before either native resume path
|
|
901
|
+
// starts the harness, put back only the MISSING managed guidance blocks from the saved
|
|
902
|
+
// startup selection. Ordinary `rig down` strips them; without this the resumed
|
|
903
|
+
// seat came back with no role, culture or SOP. Existing blocks are never refreshed; nothing
|
|
904
|
+
// reaches the conversation; no action, skill or plugin runs. Never blocks the resume.
|
|
905
|
+
if (resumeRequested && resumeToken && launchResult) {
|
|
906
|
+
let guidance = null;
|
|
907
|
+
try {
|
|
908
|
+
guidance = seatGuidance(startupCtx, node.cwd, this.rigRepo.getRigClaudeManagedBlockFile(rigId), existsSync, (path) => readFileSync(path, "utf-8"));
|
|
909
|
+
}
|
|
910
|
+
catch (err) {
|
|
911
|
+
// Guidance never blocks the exact resume; the post-launch check discloses the gap.
|
|
912
|
+
warnings?.push(`Restore guidance: ${node.logicalId}: could not read its saved guidance selection: ${err.message}`);
|
|
913
|
+
}
|
|
914
|
+
if (guidance && guidance.items.length > 0) {
|
|
915
|
+
const repair = restoreMissingGuidance(guidance, {
|
|
916
|
+
exists: existsSync,
|
|
917
|
+
readFile: (path) => readFileSync(path, "utf-8"),
|
|
918
|
+
writeFile: (path, content) => writeFileSync(path, content, "utf-8"),
|
|
919
|
+
mkdirp: (path) => mkdirSync(path, { recursive: true }),
|
|
920
|
+
});
|
|
921
|
+
if (repair.restored.length > 0) {
|
|
922
|
+
warnings?.push(`Restore guidance: ${node.logicalId}: put back missing blocks ${repair.restored.join(", ")} in ${guidance.targetPath} from their current source files.`);
|
|
923
|
+
}
|
|
924
|
+
for (const gap of repair.gaps)
|
|
925
|
+
warnings?.push(`Restore guidance: ${node.logicalId}: ${gap}`);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
807
928
|
if (resumeRequested && !isPodAware) {
|
|
808
929
|
// Legacy resume path
|
|
809
930
|
if (!resumeToken) {
|
|
@@ -815,9 +936,28 @@ export class RestoreOrchestrator {
|
|
|
815
936
|
return { nodeId: node.id, logicalId: node.logicalId, status: "awaiting-decision", error: `Original session unresumable: resume requested but no token available. No session is running. Re-run with --fresh ${node.logicalId} for a deliberate fresh-primed seat, or restore the original session manually.` };
|
|
816
937
|
}
|
|
817
938
|
else {
|
|
939
|
+
const launchedSessionId = launchResult?.session.id;
|
|
940
|
+
if (launchedSessionId && this.claudeResume.canResume(resumeType, resumeToken)) {
|
|
941
|
+
// Before the resume: Claude's SessionStart hook can land before attemptResume returns.
|
|
942
|
+
try {
|
|
943
|
+
this.sessionRegistry.recordResumeLaunch(launchedSessionId, resumeToken);
|
|
944
|
+
}
|
|
945
|
+
catch { /* best-effort: without it a rotation stays unproved, as before */ }
|
|
946
|
+
}
|
|
818
947
|
const resumeOutcome = await this.attemptResume(node.id, sessionName, resumeType, resumeToken, node.cwd ?? "/", node.codexConfigProfile, node.model, this.resolveRestorePosture(node.id, rigId), node.effort, warnings);
|
|
819
948
|
if (resumeOutcome.kind === "resumed") {
|
|
820
949
|
baseStatus = "resumed";
|
|
950
|
+
if (launchedSessionId && this.claudeResume.canResume(resumeType, resumeToken)) {
|
|
951
|
+
// The process this resume started, as the launch itself observes it (#1077): the one its
|
|
952
|
+
// identity check proved, else one observed now.
|
|
953
|
+
try {
|
|
954
|
+
const launched = resumeOutcome.launchedProcess ?? await observeClaudeResumeLaunch({ target: sessionName, tmux: this.tmuxAdapter,
|
|
955
|
+
...(this.listProcesses ? { listProcesses: this.listProcesses } : {}), token: resumeToken });
|
|
956
|
+
if (launched)
|
|
957
|
+
this.sessionRegistry.recordResumeLaunchProcess(launchedSessionId, resumeToken, launched);
|
|
958
|
+
}
|
|
959
|
+
catch { /* best-effort: without it a rotation stays unproved, as before */ }
|
|
960
|
+
}
|
|
821
961
|
}
|
|
822
962
|
else if (resumeOutcome.kind === "attention_required") {
|
|
823
963
|
// L3 Decision 2: Claude resume-selection prompt -> attention_required.
|
|
@@ -896,6 +1036,9 @@ export class RestoreOrchestrator {
|
|
|
896
1036
|
// explicit+versioned+durable+idempotent contract in the D4 operation-id
|
|
897
1037
|
// phase, where its durability primitives live. Deliberate fresh-primed
|
|
898
1038
|
// launches are new histories and keep their replay.
|
|
1039
|
+
// One narrow exception: MISSING managed guidance blocks are put back before the harness
|
|
1040
|
+
// starts (see restoreMissingGuidance above); existing blocks are still never rewritten, and
|
|
1041
|
+
// nothing else is replayed.
|
|
899
1042
|
const replayContained = resumeRequested && !!resumeToken;
|
|
900
1043
|
const startupRuntime = startupCtx?.runtime ?? node.runtime ?? null;
|
|
901
1044
|
const startupAdapter = startupRuntime ? opts?.adapters?.[startupRuntime] : undefined;
|
|
@@ -980,7 +1123,8 @@ export class RestoreOrchestrator {
|
|
|
980
1123
|
};
|
|
981
1124
|
try {
|
|
982
1125
|
const { StartupOrchestrator } = await import("./startup-orchestrator.js");
|
|
983
|
-
const startupOrch = new StartupOrchestrator({ db: this.db, sessionRegistry: this.sessionRegistry, eventBus: this.eventBus, tmuxAdapter: this.tmuxAdapter
|
|
1126
|
+
const startupOrch = new StartupOrchestrator({ db: this.db, sessionRegistry: this.sessionRegistry, eventBus: this.eventBus, tmuxAdapter: this.tmuxAdapter,
|
|
1127
|
+
...(this.listProcesses ? { listProcesses: this.listProcesses } : {}) });
|
|
984
1128
|
const replayAsRestore = baseStatus !== "fresh-primed";
|
|
985
1129
|
const shouldLaunchHarness = isPodAware;
|
|
986
1130
|
const startupResult = await startupOrch.startNode({
|
|
@@ -1140,7 +1284,10 @@ export class RestoreOrchestrator {
|
|
|
1140
1284
|
// join; a hook/operator may have changed it meanwhile. Never backfill here.
|
|
1141
1285
|
const retained = sameSession && (managedClaudeResume
|
|
1142
1286
|
? this.sessionRegistry.resumeTokenMatches(sessionId, "claude_id", resumeToken)
|
|
1287
|
+
// Claude continued the resumed conversation under a new id (its hook said so).
|
|
1288
|
+
|| this.sessionRegistry.claudeResumeRotatedFrom(sessionId, resumeToken)
|
|
1143
1289
|
: current.resume_token === resumeToken
|
|
1290
|
+
|| (node.runtime === "claude-code" && this.sessionRegistry.claudeResumeRotatedFrom(sessionId, resumeToken))
|
|
1144
1291
|
|| (!current.resume_token && this.sessionRegistry.updateResumeToken(sessionId, node.runtime === "codex" ? "codex_id" : "claude_id", resumeToken, "scrape")));
|
|
1145
1292
|
if (!retained) {
|
|
1146
1293
|
markManagedResumeAttention();
|
|
@@ -1272,7 +1419,7 @@ export class RestoreOrchestrator {
|
|
|
1272
1419
|
warnings?.push(`${sessionName}: ${notice}`);
|
|
1273
1420
|
if (result.appliedLaunch && launchGeneration)
|
|
1274
1421
|
this.appliedLaunchStore.recordGeneration(launchGeneration, result.appliedLaunch);
|
|
1275
|
-
return { kind: "resumed" };
|
|
1422
|
+
return { kind: "resumed", ...(result.launchedProcess ? { launchedProcess: result.launchedProcess } : {}) };
|
|
1276
1423
|
}
|
|
1277
1424
|
if (result.code === "retry_fresh")
|
|
1278
1425
|
return { kind: "retry_fresh" };
|
|
@@ -1412,11 +1559,15 @@ export class RestoreOrchestrator {
|
|
|
1412
1559
|
if (!sessionName) {
|
|
1413
1560
|
return { ok: false, code: "tmux_session_missing", detail: "No tmux session bound for this node." };
|
|
1414
1561
|
}
|
|
1415
|
-
const sessRow = this.db.prepare("SELECT session_name, resume_token FROM sessions WHERE node_id = ? ORDER BY created_at DESC, id DESC LIMIT 1").get(nodeId);
|
|
1562
|
+
const sessRow = this.db.prepare("SELECT session_name, resume_type, resume_token, resume_provenance, resume_rotated_from, resume_rotated_process, resume_launch_process FROM sessions WHERE node_id = ? ORDER BY created_at DESC, id DESC LIMIT 1").get(nodeId);
|
|
1416
1563
|
if (!sessRow || sessRow.session_name !== sessionName) {
|
|
1417
1564
|
return { ok: false, code: "binding_mismatch", detail: `Canonical binding ${sessionName} does not match the latest session row.` };
|
|
1418
1565
|
}
|
|
1419
1566
|
const expectedResumeToken = sessRow.resume_token;
|
|
1567
|
+
// The one alternative argv may carry: the token OpenRig launched this row to resume, when the
|
|
1568
|
+
// first hook after that launch recorded Claude continuing it as the stored token (#1077), and
|
|
1569
|
+
// only in the process that sent that hook.
|
|
1570
|
+
const rotation = sessRow.resume_type === "claude_id" ? claudeResumeRotation(sessRow) : null;
|
|
1420
1571
|
if (!expectedResumeToken) {
|
|
1421
1572
|
return { ok: false, code: "resume_token_not_used", detail: "No resume token recorded on the latest session row." };
|
|
1422
1573
|
}
|
|
@@ -1437,6 +1588,7 @@ export class RestoreOrchestrator {
|
|
|
1437
1588
|
// basename alone is never sufficient for no-input recovery.
|
|
1438
1589
|
const nodeRow = this.db.prepare("SELECT runtime FROM nodes WHERE id = ?").get(nodeId);
|
|
1439
1590
|
const runtime = nodeRow?.runtime ?? null;
|
|
1591
|
+
// One exact-lineage check per process, accepting the stored token or the recorded rotation.
|
|
1440
1592
|
const identity = await rebindAndVerifyPaneIdentity({
|
|
1441
1593
|
db: this.db,
|
|
1442
1594
|
sessionRegistry: this.sessionRegistry,
|
|
@@ -1446,6 +1598,7 @@ export class RestoreOrchestrator {
|
|
|
1446
1598
|
runtime,
|
|
1447
1599
|
expectedResumeToken,
|
|
1448
1600
|
requireExactResumeLineage: true,
|
|
1601
|
+
resumeRotation: rotation,
|
|
1449
1602
|
...(this.listProcesses ? { listProcesses: this.listProcesses } : {}),
|
|
1450
1603
|
});
|
|
1451
1604
|
if (!identity.ok) {
|
|
@@ -1457,6 +1610,7 @@ export class RestoreOrchestrator {
|
|
|
1457
1610
|
target: identity.pane,
|
|
1458
1611
|
tmux: this.tmuxAdapter,
|
|
1459
1612
|
expectedToken: expectedResumeToken,
|
|
1613
|
+
rotation,
|
|
1460
1614
|
requireResume: true,
|
|
1461
1615
|
...(this.listProcesses ? { listProcesses: this.listProcesses } : {}),
|
|
1462
1616
|
});
|