@gajae-code/coding-agent 0.11.1 → 0.11.3
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/CHANGELOG.md +64 -0
- package/dist/types/cli/config-cli.d.ts +11 -1
- package/dist/types/cli/launch-disposition.d.ts +23 -0
- package/dist/types/cli/notify-cli.d.ts +1 -0
- package/dist/types/cli/session-picker.d.ts +2 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/mcp-serve.d.ts +33 -0
- package/dist/types/commands/mcp.d.ts +1 -1
- package/dist/types/commands/notify.d.ts +0 -2
- package/dist/types/commands/sdk.d.ts +1 -1
- package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
- package/dist/types/config/file-lock.d.ts +14 -4
- package/dist/types/config/keybindings.d.ts +42 -1
- package/dist/types/config/model-auth.d.ts +3 -0
- package/dist/types/config/model-bindings-applier.d.ts +13 -0
- package/dist/types/config/model-discovery-manager.d.ts +49 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-registry.d.ts +16 -15
- package/dist/types/config/model-resolver.d.ts +28 -18
- package/dist/types/config/models-config-schema.d.ts +11 -0
- package/dist/types/config/settings-schema.d.ts +141 -11
- package/dist/types/config/settings.d.ts +14 -11
- package/dist/types/coordinator-mcp/policy.d.ts +5 -0
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/discovery/helpers.d.ts +0 -6
- package/dist/types/edit/index.d.ts +3 -0
- package/dist/types/eval/py/env.d.ts +9 -0
- package/dist/types/extensibility/extensions/loader.d.ts +2 -1
- package/dist/types/extensibility/extensions/runner.d.ts +2 -2
- package/dist/types/extensibility/extensions/types.d.ts +34 -3
- package/dist/types/extensibility/hooks/runner.d.ts +1 -1
- package/dist/types/extensibility/shared-events.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
- package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
- package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
- package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
- package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
- package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
- package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
- package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
- package/dist/types/gjc-runtime/team-store.d.ts +160 -0
- package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
- package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
- package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
- package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/goals/state.d.ts +8 -0
- package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
- package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
- package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/state.d.ts +11 -4
- package/dist/types/lsp/lspmux.d.ts +5 -3
- package/dist/types/lsp/path-trust.d.ts +1 -0
- package/dist/types/main.d.ts +4 -2
- package/dist/types/memories/storage.d.ts +1 -0
- package/dist/types/modes/action-registry.d.ts +29 -0
- package/dist/types/modes/components/chrome.d.ts +14 -0
- package/dist/types/modes/components/command-palette.d.ts +27 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
- package/dist/types/modes/components/index.d.ts +2 -1
- package/dist/types/modes/components/pet-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
- package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
- package/dist/types/modes/components/queue-pane.d.ts +12 -0
- package/dist/types/modes/components/read-tool-group.d.ts +6 -0
- package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
- package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
- package/dist/types/modes/components/settings-selector.d.ts +1 -1
- package/dist/types/modes/components/show-images-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/types.d.ts +1 -1
- package/dist/types/modes/components/status-line.d.ts +1 -94
- package/dist/types/modes/components/tasks-pane.d.ts +15 -0
- package/dist/types/modes/components/theme-selector.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +15 -0
- package/dist/types/modes/components/tool-status-header.d.ts +111 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
- package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
- package/dist/types/modes/controllers/input-controller.d.ts +8 -1
- package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
- package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
- package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
- package/dist/types/modes/interactive-mode.d.ts +19 -17
- package/dist/types/modes/jobs-observer.d.ts +2 -0
- package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
- package/dist/types/modes/tasks-aggregator.d.ts +39 -0
- package/dist/types/modes/transcript-item-registry.d.ts +60 -0
- package/dist/types/modes/types.d.ts +20 -13
- package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/sdk/broker/broker.d.ts +78 -12
- package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
- package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
- package/dist/types/sdk/broker/session-index.d.ts +0 -1
- package/dist/types/sdk/broker/state-version.d.ts +2 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
- package/dist/types/sdk/bus/config-commands.d.ts +1 -1
- package/dist/types/sdk/bus/config.d.ts +11 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/html-format.d.ts +3 -2
- package/dist/types/sdk/bus/index.d.ts +29 -0
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/notification-service.d.ts +20 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
- package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
- package/dist/types/sdk/bus/rich-document.d.ts +7 -0
- package/dist/types/sdk/bus/rich-render.d.ts +18 -41
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
- package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
- package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/session-directory.d.ts +56 -0
- package/dist/types/sdk/session.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +82 -47
- package/dist/types/session/agent-storage.d.ts +7 -0
- package/dist/types/session/fallback-chain-controller.d.ts +10 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
- package/dist/types/session/messages.d.ts +16 -0
- package/dist/types/session/session-manager-internal.d.ts +14 -0
- package/dist/types/session/session-manager.d.ts +82 -12
- package/dist/types/session/session-storage.d.ts +43 -3
- package/dist/types/session/volatile-context-pruning.d.ts +15 -0
- package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
- package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
- package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
- package/dist/types/system-prompt.d.ts +2 -11
- package/dist/types/task/executor.d.ts +3 -1
- package/dist/types/thinking.d.ts +7 -0
- package/dist/types/tool-discovery/tool-index.d.ts +1 -50
- package/dist/types/tools/ask.d.ts +64 -2
- package/dist/types/tools/bash.d.ts +3 -0
- package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
- package/dist/types/tools/cron.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -0
- package/dist/types/tools/index.d.ts +30 -15
- package/dist/types/tools/output-meta.d.ts +1 -0
- package/dist/types/tools/read.d.ts +5 -0
- package/dist/types/tools/search-tool-bm25.d.ts +3 -4
- package/dist/types/tools/subagent.d.ts +1 -0
- package/dist/types/utils/event-bus.d.ts +1 -1
- package/dist/types/utils/file-mentions.d.ts +3 -3
- package/dist/types/web/search/index.d.ts +3 -1
- package/package.json +21 -9
- package/scripts/build-sdk-package-smoke.ts +34 -1
- package/scripts/generate-hotkeys-docs.ts +74 -0
- package/scripts/generate-sdk-operation-inventory.ts +64 -20
- package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
- package/src/async/job-manager.ts +49 -6
- package/src/cli/config-cli.ts +75 -2
- package/src/cli/launch-disposition.ts +42 -0
- package/src/cli/notify-cli.ts +92 -26
- package/src/cli/session-picker.ts +20 -3
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/harness.ts +34 -106
- package/src/commands/launch.ts +6 -4
- package/src/commands/mcp-serve.ts +85 -8
- package/src/commands/mcp.ts +2 -2
- package/src/commands/notify.ts +8 -4
- package/src/commands/sdk.ts +61 -40
- package/src/commands/ultragoal.ts +4 -1
- package/src/config/atomic-yaml-patch.ts +80 -13
- package/src/config/file-lock.ts +105 -43
- package/src/config/keybindings.ts +64 -20
- package/src/config/model-auth.ts +9 -0
- package/src/config/model-bindings-applier.ts +139 -0
- package/src/config/model-discovery-manager.ts +224 -0
- package/src/config/model-equivalence.ts +66 -0
- package/src/config/model-registry.ts +169 -302
- package/src/config/model-resolver.ts +361 -369
- package/src/config/models-config-schema.ts +5 -4
- package/src/config/settings-schema.ts +214 -12
- package/src/config/settings.ts +458 -482
- package/src/coordinator-mcp/policy.ts +76 -11
- package/src/coordinator-mcp/question-gate-codec.ts +274 -0
- package/src/coordinator-mcp/question-state.ts +778 -0
- package/src/coordinator-mcp/server.ts +1702 -238
- package/src/debug/index.ts +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
- package/src/defaults/gjc/skills/team/SKILL.md +16 -0
- package/src/discovery/helpers.ts +1 -50
- package/src/edit/index.ts +64 -0
- package/src/eval/py/env.ts +26 -0
- package/src/eval/py/kernel.ts +5 -3
- package/src/extensibility/extensions/loader.ts +9 -1
- package/src/extensibility/extensions/runner.ts +12 -3
- package/src/extensibility/extensions/types.ts +39 -1
- package/src/extensibility/gjc-plugins/installer.ts +16 -16
- package/src/extensibility/hooks/runner.ts +2 -2
- package/src/extensibility/runtime-skill-discovery.ts +33 -13
- package/src/extensibility/shared-events.ts +2 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
- package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
- package/src/gjc-runtime/deep-interview-state.ts +317 -5
- package/src/gjc-runtime/goal-mode-request.ts +55 -8
- package/src/gjc-runtime/launch-tmux.ts +2 -5
- package/src/gjc-runtime/launch-worktree.ts +5 -5
- package/src/gjc-runtime/linux-proc.ts +71 -0
- package/src/gjc-runtime/ralplan-runtime.ts +74 -90
- package/src/gjc-runtime/session-resolution.ts +18 -3
- package/src/gjc-runtime/session-state-sidecar.ts +6 -107
- package/src/gjc-runtime/state-migrations.ts +1 -1
- package/src/gjc-runtime/state-runtime.ts +327 -249
- package/src/gjc-runtime/state-writer.ts +36 -40
- package/src/gjc-runtime/team-launch.ts +319 -0
- package/src/gjc-runtime/team-notify.ts +326 -0
- package/src/gjc-runtime/team-runtime.ts +1099 -1482
- package/src/gjc-runtime/team-store.ts +828 -0
- package/src/gjc-runtime/team-workers.ts +962 -0
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
- package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
- package/src/gjc-runtime/tmux-sessions.ts +4 -21
- package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
- package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
- package/src/gjc-runtime/ultragoal-guard.ts +29 -5
- package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
- package/src/gjc-runtime/workflow-cli-common.ts +30 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +18 -0
- package/src/goals/continuation-timeout-guard.ts +79 -0
- package/src/goals/runtime.ts +7 -5
- package/src/goals/state.ts +18 -0
- package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
- package/src/harness-control-plane/phase-rollup.ts +4 -7
- package/src/harness-control-plane/receipt-ingest.ts +5 -0
- package/src/harness-control-plane/receipt-spool.ts +51 -7
- package/src/harness-control-plane/session-lease.ts +12 -130
- package/src/hindsight/backend.ts +26 -27
- package/src/hindsight/state.ts +101 -32
- package/src/hooks/skill-state.ts +17 -11
- package/src/internal-urls/docs-index.generated.ts +21 -18
- package/src/lsp/client.ts +1 -1
- package/src/lsp/config.ts +145 -26
- package/src/lsp/index.ts +1 -1
- package/src/lsp/lspmux.ts +39 -10
- package/src/lsp/path-trust.ts +81 -0
- package/src/main.ts +127 -30
- package/src/memories/index.ts +1 -0
- package/src/memories/storage.ts +6 -2
- package/src/modes/action-registry.ts +165 -0
- package/src/modes/components/chrome.ts +40 -0
- package/src/modes/components/command-palette.ts +168 -0
- package/src/modes/components/custom-editor.ts +1 -1
- package/src/modes/components/custom-provider-wizard.ts +51 -14
- package/src/modes/components/index.ts +2 -1
- package/src/modes/components/pet-selector.ts +11 -17
- package/src/modes/components/plan-preview-overlay.ts +295 -0
- package/src/modes/components/queue-mode-selector.ts +10 -27
- package/src/modes/components/queue-pane.ts +79 -0
- package/src/modes/components/read-tool-group.ts +13 -0
- package/src/modes/components/session-observer-overlay.ts +207 -772
- package/src/modes/components/sessions-dashboard.ts +181 -0
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/show-images-selector.ts +10 -24
- package/src/modes/components/status-line/types.ts +1 -1
- package/src/modes/components/status-line.ts +1 -969
- package/src/modes/components/tasks-pane.ts +73 -0
- package/src/modes/components/theme-selector.ts +11 -31
- package/src/modes/components/tool-execution.ts +22 -0
- package/src/modes/components/tool-status-header.ts +1056 -0
- package/src/modes/components/transcript-viewer-overlay.ts +384 -0
- package/src/modes/controllers/btw-controller.ts +1 -0
- package/src/modes/controllers/event-controller.ts +3 -2
- package/src/modes/controllers/extension-ui-controller.ts +24 -1
- package/src/modes/controllers/goal-mode-controller.ts +474 -0
- package/src/modes/controllers/input-controller.ts +764 -229
- package/src/modes/controllers/mode-gate.ts +24 -0
- package/src/modes/controllers/plan-mode-controller.ts +517 -0
- package/src/modes/controllers/selector-controller.ts +225 -10
- package/src/modes/controllers/stt-controller.ts +125 -0
- package/src/modes/interactive-mode.ts +289 -1150
- package/src/modes/jobs-observer.ts +3 -0
- package/src/modes/prompt-action-autocomplete.ts +7 -0
- package/src/modes/runtime-init.ts +8 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
- package/src/modes/tasks-aggregator.ts +199 -0
- package/src/modes/transcript-item-registry.ts +229 -0
- package/src/modes/types.ts +45 -18
- package/src/modes/utils/ui-helpers.ts +17 -9
- package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
- package/src/prompts/agent-fragments/restricted-bash.md +1 -0
- package/src/prompts/agents/architect.md +2 -8
- package/src/prompts/agents/critic.md +2 -8
- package/src/prompts/agents/executor.md +3 -0
- package/src/prompts/agents/planner.md +4 -12
- package/src/prompts/system/custom-system-prompt.md +1 -23
- package/src/prompts/system/plan-mode-approved.md +8 -0
- package/src/prompts/system/system-prompt.md +17 -96
- package/src/prompts/tools/bash.md +4 -4
- package/src/prompts/tools/browser.md +15 -52
- package/src/prompts/tools/find.md +2 -2
- package/src/prompts/tools/hashline.md +13 -55
- package/src/prompts/tools/read.md +3 -6
- package/src/prompts/tools/search-tool-bm25.md +0 -2
- package/src/prompts/tools/search.md +2 -4
- package/src/prompts/tools/skill-discovery.md +1 -2
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-mcp/manager.ts +1 -1
- package/src/sdk/broker/broker.ts +206 -78
- package/src/sdk/broker/discovery.ts +1 -1
- package/src/sdk/broker/ensure.ts +3 -1
- package/src/sdk/broker/lifecycle-codec.ts +11 -0
- package/src/sdk/broker/lifecycle-ledger.ts +371 -74
- package/src/sdk/broker/lifecycle.ts +1399 -142
- package/src/sdk/broker/process-incarnation.ts +5 -13
- package/src/sdk/broker/session-index.ts +145 -56
- package/src/sdk/broker/state-version.ts +21 -0
- package/src/sdk/broker/transport.ts +1 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -28
- package/src/sdk/bus/chat-effect-journal.ts +10 -2
- package/src/sdk/bus/config-commands.ts +5 -4
- package/src/sdk/bus/config.ts +98 -0
- package/src/sdk/bus/conversation-store.ts +5 -29
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/html-format.ts +20 -3
- package/src/sdk/bus/index.ts +782 -94
- package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
- package/src/sdk/bus/natives-augment.d.ts +26 -1
- package/src/sdk/bus/notification-service.ts +168 -20
- package/src/sdk/bus/rate-limit-pool.ts +58 -14
- package/src/sdk/bus/recent-activity.ts +188 -74
- package/src/sdk/bus/rich-document.ts +258 -0
- package/src/sdk/bus/rich-render.ts +62 -70
- package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
- package/src/sdk/bus/telegram-daemon.ts +1389 -237
- package/src/sdk/bus/threaded-inbound.ts +8 -3
- package/src/sdk/bus/threaded-render.ts +57 -1
- package/src/sdk/bus/topic-registry.ts +120 -13
- package/src/sdk/host/control/dispatch.ts +14 -2
- package/src/sdk/host/control/operations.ts +6 -1
- package/src/sdk/host/host.ts +44 -2
- package/src/sdk/host/query/handlers.ts +20 -22
- package/src/sdk/host/query/revision-store.ts +80 -57
- package/src/sdk/index.ts +1 -0
- package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
- package/src/sdk/session-directory.ts +141 -0
- package/src/sdk/session.ts +462 -480
- package/src/session/agent-session.ts +1700 -583
- package/src/session/agent-storage.ts +18 -0
- package/src/session/cache-economics.ts +25 -8
- package/src/session/fallback-chain-controller.ts +53 -3
- package/src/session/internal/managed-session-scope.ts +2226 -0
- package/src/session/internal/managed-session-storage.ts +453 -0
- package/src/session/messages.ts +91 -2
- package/src/session/session-manager-internal.ts +33 -0
- package/src/session/session-manager.ts +1112 -333
- package/src/session/session-storage.ts +444 -39
- package/src/session/volatile-context-pruning.ts +78 -0
- package/src/setup/credential-auto-import.ts +2 -1
- package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
- package/src/setup/provider-onboarding.ts +36 -61
- package/src/setup/provider-presets.json +5 -0
- package/src/skill-state/active-state.ts +3 -13
- package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
- package/src/skill-state/workflow-state-contract.ts +6 -41
- package/src/slash-commands/builtin-registry.ts +46 -11
- package/src/system-prompt.ts +37 -44
- package/src/task/agents.ts +19 -1
- package/src/task/executor.ts +90 -6
- package/src/task/index.ts +36 -21
- package/src/thinking.ts +21 -6
- package/src/tool-discovery/tool-index.ts +2 -134
- package/src/tools/ask.ts +157 -21
- package/src/tools/ast-edit.ts +1 -1
- package/src/tools/bash.ts +38 -0
- package/src/tools/browser/dead-tab-recovery.ts +78 -0
- package/src/tools/browser/tab-supervisor.ts +282 -36
- package/src/tools/computer.ts +10 -3
- package/src/tools/cron.ts +30 -16
- package/src/tools/eval.ts +1 -2
- package/src/tools/fetch.ts +11 -4
- package/src/tools/index.ts +76 -24
- package/src/tools/output-meta.ts +19 -7
- package/src/tools/read.ts +219 -64
- package/src/tools/resource-gc.ts +2 -2
- package/src/tools/search-tool-bm25.ts +11 -74
- package/src/tools/subagent.ts +43 -2
- package/src/utils/event-bus.ts +9 -4
- package/src/utils/file-mentions.ts +4 -4
- package/src/web/search/index.ts +3 -3
- package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
- package/src/discovery/plugin-dir-roots.ts +0 -28
- package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
package/src/commands/harness.ts
CHANGED
|
@@ -25,16 +25,25 @@ import {
|
|
|
25
25
|
classifyCgroup,
|
|
26
26
|
isExactScopedBootstrapSuccessReceipt,
|
|
27
27
|
isOwnerGenerationBaselineCurrentSync,
|
|
28
|
+
isSafeServerProof,
|
|
28
29
|
type OwnerGenerationBaseline,
|
|
29
30
|
type OwnerIsolationProbe,
|
|
30
31
|
observeOwnerTerminal,
|
|
31
32
|
ownerProcessStartTime,
|
|
32
33
|
planTmuxOwnerIsolation,
|
|
33
34
|
replaceOwnerGenerationSync,
|
|
35
|
+
sameServerIdentity,
|
|
34
36
|
type TmuxServerProof,
|
|
35
37
|
} from "../gjc-runtime/tmux-owner-isolation";
|
|
36
38
|
import { classifyRecovery } from "../harness-control-plane/classifier";
|
|
37
39
|
import { callEndpoint, EndpointUnreachableError } from "../harness-control-plane/control-endpoint";
|
|
40
|
+
import {
|
|
41
|
+
type CompletedTerminalEvent,
|
|
42
|
+
isOwnerLivenessBlocker,
|
|
43
|
+
needsVanishedOwnerBlock,
|
|
44
|
+
OWNER_STARTUP_BLOCKER,
|
|
45
|
+
reconcileOwnerLifecycle,
|
|
46
|
+
} from "../harness-control-plane/lifecycle-reconciliation";
|
|
38
47
|
import { type ResolvedOwner, RuntimeOwner, resolveOwner, resolveOwnerLive } from "../harness-control-plane/owner";
|
|
39
48
|
import { preserveDirtyWorktree } from "../harness-control-plane/preserve";
|
|
40
49
|
import { RECEIPT_SPOOL_DIR_ENV } from "../harness-control-plane/receipt-spool";
|
|
@@ -252,12 +261,6 @@ function pushUnique(out: string[], value: unknown): void {
|
|
|
252
261
|
if (typeof value === "string" && !out.includes(value)) out.push(value);
|
|
253
262
|
}
|
|
254
263
|
|
|
255
|
-
interface CompletedTerminalEvent {
|
|
256
|
-
cursor: number;
|
|
257
|
-
createdAt: string;
|
|
258
|
-
kind: string;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
264
|
function completedTerminalEvent(events: EventEnvelope[]): CompletedTerminalEvent | null {
|
|
262
265
|
for (const event of [...events].reverse()) {
|
|
263
266
|
const signal = (event.evidence as { signal?: unknown } | undefined)?.signal;
|
|
@@ -461,73 +464,21 @@ function updateStateWithRestoredOwner(state: SessionState, leasePath: string, re
|
|
|
461
464
|
state.updatedAt = nowIso();
|
|
462
465
|
}
|
|
463
466
|
|
|
464
|
-
function
|
|
465
|
-
return blocker === "detached-owner-not-live" || blocker.startsWith("owner-vanished:");
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
async function reconcileCompletedOwnerExited(
|
|
467
|
+
async function reconcileLifecycle(
|
|
469
468
|
root: string,
|
|
470
469
|
state: SessionState,
|
|
471
470
|
observation: Observation,
|
|
472
471
|
completedTerminal: CompletedTerminalEvent | null,
|
|
472
|
+
startupBlocked = false,
|
|
473
473
|
): Promise<SessionState> {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
function needsVanishedOwnerBlock(
|
|
484
|
-
state: SessionState,
|
|
485
|
-
observation: Observation,
|
|
486
|
-
completedTerminal: CompletedTerminalEvent | null,
|
|
487
|
-
): boolean {
|
|
488
|
-
if (observation.ownerLive || state.lifecycle !== "observing") return false;
|
|
489
|
-
if (completedTerminal || observation.observedSignals.includes("completed")) return false;
|
|
490
|
-
return observation.observedSignals.some(
|
|
491
|
-
signal => signal === "prompt-accepted" || signal === "tool-call" || signal === "streaming",
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
async function markVanishedOwnerBlocked(
|
|
496
|
-
root: string,
|
|
497
|
-
state: SessionState,
|
|
498
|
-
observation: Observation,
|
|
499
|
-
completedTerminal: CompletedTerminalEvent | null,
|
|
500
|
-
): Promise<SessionState> {
|
|
501
|
-
if (!needsVanishedOwnerBlock(state, observation, completedTerminal)) return state;
|
|
502
|
-
const blocker = `owner-vanished:${observation.gitDelta}`;
|
|
503
|
-
state.lifecycle = "blocked";
|
|
504
|
-
state.blockers = state.blockers.includes(blocker) ? state.blockers : [...state.blockers, blocker];
|
|
505
|
-
state.updatedAt = nowIso();
|
|
506
|
-
await writeSessionState(root, state);
|
|
507
|
-
return state;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const OWNER_STARTUP_BLOCKER = "owner-died-before-first-prompt";
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* Persist an explicit startup blocker when an owner started, reported live, but died before
|
|
514
|
-
* accepting the first prompt. This makes the failure an actionable lifecycle state instead of a
|
|
515
|
-
* silent `owner-not-live` gate, so observe/recover surface it and recover can respawn the owner.
|
|
516
|
-
*/
|
|
517
|
-
async function markStartupOwnerBlocked(
|
|
518
|
-
root: string,
|
|
519
|
-
state: SessionState,
|
|
520
|
-
ownerExit: OwnerExitEvidence,
|
|
521
|
-
): Promise<SessionState> {
|
|
522
|
-
if (!ownerExit.startupBlocker) return state;
|
|
523
|
-
if (state.lifecycle === "completed" || state.lifecycle === "retired") return state;
|
|
524
|
-
state.lifecycle = "blocked";
|
|
525
|
-
state.blockers = state.blockers.includes(OWNER_STARTUP_BLOCKER)
|
|
526
|
-
? state.blockers
|
|
527
|
-
: [...state.blockers, OWNER_STARTUP_BLOCKER];
|
|
528
|
-
state.updatedAt = nowIso();
|
|
529
|
-
await writeSessionState(root, state);
|
|
530
|
-
return state;
|
|
474
|
+
return reconcileOwnerLifecycle({
|
|
475
|
+
state,
|
|
476
|
+
observation,
|
|
477
|
+
completedTerminal,
|
|
478
|
+
startupBlocked,
|
|
479
|
+
persist: async nextState => writeSessionState(root, nextState),
|
|
480
|
+
nowIso,
|
|
481
|
+
});
|
|
531
482
|
}
|
|
532
483
|
|
|
533
484
|
function resolveRetryBudget(input: Record<string, unknown>): RetryBudget {
|
|
@@ -562,29 +513,6 @@ function isBoundedNoServerDiagnostic(stderr: Uint8Array): boolean {
|
|
|
562
513
|
);
|
|
563
514
|
}
|
|
564
515
|
|
|
565
|
-
function sameServerIdentity(left: TmuxServerProof, right: TmuxServerProof): boolean {
|
|
566
|
-
return (
|
|
567
|
-
left.pid === right.pid &&
|
|
568
|
-
left.startTime === right.startTime &&
|
|
569
|
-
left.cgroup?.classification === right.cgroup?.classification &&
|
|
570
|
-
left.cgroup?.scope === right.cgroup?.scope &&
|
|
571
|
-
left.cgroup?.diagnostic === right.cgroup?.diagnostic
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function isSafeServerProof(proof: TmuxServerProof): boolean {
|
|
576
|
-
return (
|
|
577
|
-
proof.state === "safe" &&
|
|
578
|
-
typeof proof.pid === "number" &&
|
|
579
|
-
Number.isSafeInteger(proof.pid) &&
|
|
580
|
-
proof.pid > 0 &&
|
|
581
|
-
typeof proof.startTime === "string" &&
|
|
582
|
-
proof.startTime.length > 0 &&
|
|
583
|
-
(proof.cgroup?.classification === "safe" ||
|
|
584
|
-
(process.platform !== "linux" && proof.cgroup?.classification === "not_applicable"))
|
|
585
|
-
);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
516
|
function exactNativeTmuxSessionId(stdout: Uint8Array): string | null {
|
|
589
517
|
const value = new TextDecoder().decode(stdout);
|
|
590
518
|
const line = value.endsWith("\n") ? value.slice(0, -1) : value;
|
|
@@ -985,7 +913,9 @@ export default class Harness extends Command {
|
|
|
985
913
|
proof: TmuxServerProof | null,
|
|
986
914
|
probeServer: OwnerIsolationProbe["probeServer"],
|
|
987
915
|
): Promise<void> {
|
|
988
|
-
if (!nativeSessionId || !proof || !isSafeServerProof(proof
|
|
916
|
+
if (!nativeSessionId || !proof || !isSafeServerProof(proof, ownerIsolationPlatform()))
|
|
917
|
+
throw new Error("tmux-owner-cleanup_uncertain");
|
|
918
|
+
|
|
989
919
|
if (!(await this.#nativeSessionBoundToName(tmuxCommand, socketKey, nativeSessionId, sessionName)))
|
|
990
920
|
throw new Error("tmux-owner-cleanup_uncertain");
|
|
991
921
|
const current = await probeServer(socketKey, [tmuxCommand, "-L", socketKey]);
|
|
@@ -1141,7 +1071,7 @@ export default class Harness extends Command {
|
|
|
1141
1071
|
const postSpawnServer = await probeServer(socketKey, [tmuxCommand, "-L", socketKey]);
|
|
1142
1072
|
cleanupProof = postSpawnServer;
|
|
1143
1073
|
if (postSpawnServer.state === "unsafe") return fail("tmux-owner-server_unsafe");
|
|
1144
|
-
if (!isSafeServerProof(postSpawnServer)) return fail("tmux-owner-server_unverifiable");
|
|
1074
|
+
if (!isSafeServerProof(postSpawnServer, ownerIsolationPlatform())) return fail("tmux-owner-server_unverifiable");
|
|
1145
1075
|
if (
|
|
1146
1076
|
scopedReceipt &&
|
|
1147
1077
|
(scopedReceipt.sessionName !== sessionName ||
|
|
@@ -1441,14 +1371,10 @@ export default class Harness extends Command {
|
|
|
1441
1371
|
let state = await loadState(root, sessionId);
|
|
1442
1372
|
const ownerLive = ownerLiveFor(state);
|
|
1443
1373
|
const { observation, completedTerminalEvent } = await buildObservation(root, state, ownerLive);
|
|
1444
|
-
state = await reconcileCompletedOwnerExited(root, state, observation, completedTerminalEvent);
|
|
1445
1374
|
const vanishedOwnerBlock = needsVanishedOwnerBlock(state, observation, completedTerminalEvent);
|
|
1446
|
-
state = await markVanishedOwnerBlocked(root, state, observation, completedTerminalEvent);
|
|
1447
|
-
// Build owner-exit evidence whenever the owner is gone so a startup death (owner started,
|
|
1448
|
-
// reported live, then died before the first prompt) is detectable, not just vanish/completion.
|
|
1449
1375
|
const ownerExit = !ownerLive ? await buildOwnerExitEvidence(root, state) : null;
|
|
1450
1376
|
const startupBlocked = ownerExit?.startupBlocker ?? false;
|
|
1451
|
-
|
|
1377
|
+
state = await reconcileLifecycle(root, state, observation, completedTerminalEvent, startupBlocked);
|
|
1452
1378
|
const includeOwnerExit = Boolean(ownerExit && (vanishedOwnerBlock || completedTerminalEvent || startupBlocked));
|
|
1453
1379
|
writeJson(
|
|
1454
1380
|
buildResponse(state, ownerLive, {
|
|
@@ -1482,12 +1408,7 @@ export default class Harness extends Command {
|
|
|
1482
1408
|
if (!observation) {
|
|
1483
1409
|
const built = await buildObservation(root, stateView, ownerLive);
|
|
1484
1410
|
observation = built.observation;
|
|
1485
|
-
stateView = await
|
|
1486
|
-
root,
|
|
1487
|
-
stateView,
|
|
1488
|
-
built.observation,
|
|
1489
|
-
built.completedTerminalEvent,
|
|
1490
|
-
);
|
|
1411
|
+
stateView = await reconcileLifecycle(root, stateView, built.observation, built.completedTerminalEvent);
|
|
1491
1412
|
}
|
|
1492
1413
|
}
|
|
1493
1414
|
if (!observation) throw new Error("classify_requires_observation_or_session");
|
|
@@ -1548,7 +1469,14 @@ export default class Harness extends Command {
|
|
|
1548
1469
|
const ownerExit = await buildOwnerExitEvidence(root, state);
|
|
1549
1470
|
// An owner that started, reported live, then died before accepting the first prompt is a
|
|
1550
1471
|
// startup blocker, not a healthy `owner-not-live` gate — persist it and report it as such.
|
|
1551
|
-
|
|
1472
|
+
const built = await buildObservation(root, state, false);
|
|
1473
|
+
state = await reconcileLifecycle(
|
|
1474
|
+
root,
|
|
1475
|
+
state,
|
|
1476
|
+
built.observation,
|
|
1477
|
+
built.completedTerminalEvent,
|
|
1478
|
+
ownerExit.startupBlocker,
|
|
1479
|
+
);
|
|
1552
1480
|
const reason = ownerExit.startupBlocker ? ownerExit.reason : "owner-not-live";
|
|
1553
1481
|
writeJson(
|
|
1554
1482
|
buildResponse(
|
|
@@ -1614,7 +1542,7 @@ export default class Harness extends Command {
|
|
|
1614
1542
|
let state = await loadState(root, sessionId);
|
|
1615
1543
|
const beforeExit = await buildOwnerExitEvidence(root, state);
|
|
1616
1544
|
const { observation, completedTerminalEvent } = await buildObservation(root, state, false);
|
|
1617
|
-
state = await
|
|
1545
|
+
state = await reconcileLifecycle(root, state, observation, completedTerminalEvent);
|
|
1618
1546
|
const decision = classifyRecovery({
|
|
1619
1547
|
observation: { ...observation, lifecycle: state.lifecycle },
|
|
1620
1548
|
retryBudget: budget,
|
package/src/commands/launch.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { APP_NAME, setProjectDir } from "@gajae-code/utils";
|
|
|
9
9
|
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
10
10
|
import { parseArgs } from "../cli/args";
|
|
11
11
|
import { launchDefaultTmuxIfNeeded } from "../gjc-runtime/launch-tmux";
|
|
12
|
-
import { prepareLaunchWorktree } from "../gjc-runtime/launch-worktree";
|
|
12
|
+
import { type PreparedLaunchWorktree, prepareLaunchWorktree } from "../gjc-runtime/launch-worktree";
|
|
13
13
|
import {
|
|
14
14
|
GJC_COORDINATOR_SESSION_ID_ENV,
|
|
15
15
|
GJC_COORDINATOR_SESSION_STATE_FILE_ENV,
|
|
@@ -128,7 +128,8 @@ export default class Index extends Command {
|
|
|
128
128
|
description: "Resume a session (by ID prefix, path, or picker if omitted)",
|
|
129
129
|
}),
|
|
130
130
|
"session-dir": Flags.string({
|
|
131
|
-
description:
|
|
131
|
+
description:
|
|
132
|
+
"Explicit session storage directory and lookup override (default uses managed v2 workspace scope)",
|
|
132
133
|
}),
|
|
133
134
|
"no-session": Flags.boolean({
|
|
134
135
|
description: "Don't save session (ephemeral)",
|
|
@@ -199,7 +200,8 @@ export default class Index extends Command {
|
|
|
199
200
|
`# Pin a stored credential for this session\n ${APP_NAME} --credential email:me@example.com`,
|
|
200
201
|
`# Activate a model profile for this session\n ${APP_NAME} --mpreset codex-medium`,
|
|
201
202
|
`# Persist a model profile as the default\n ${APP_NAME} --mpreset opencodego --default`,
|
|
202
|
-
`# Export a session file to HTML\n ${APP_NAME} --export ~/.gjc/agent/sessions
|
|
203
|
+
`# Export a session file to HTML\n ${APP_NAME} --export ~/.gjc/agent/sessions/v2-<scope>/session.jsonl`,
|
|
204
|
+
`# Use an explicit session storage directory\n ${APP_NAME} --session-dir ./sessions`,
|
|
203
205
|
];
|
|
204
206
|
|
|
205
207
|
static strict = false;
|
|
@@ -212,7 +214,7 @@ export default class Index extends Command {
|
|
|
212
214
|
return;
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
let launch:
|
|
217
|
+
let launch: PreparedLaunchWorktree;
|
|
216
218
|
try {
|
|
217
219
|
launch = prepareLaunchWorktree(process.cwd(), args);
|
|
218
220
|
} catch (error) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAgentDir } from "@gajae-code/utils";
|
|
1
2
|
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
2
3
|
import {
|
|
3
4
|
COORDINATOR_MCP_PROTOCOL_VERSION,
|
|
@@ -5,12 +6,88 @@ import {
|
|
|
5
6
|
COORDINATOR_MCP_TOOL_NAMES,
|
|
6
7
|
} from "../coordinator/contract";
|
|
7
8
|
import { runCoordinatorMcpStdio } from "../coordinator-mcp/server";
|
|
9
|
+
import { type BrokerDiscovery, readBrokerDiscovery } from "../sdk/broker/discovery";
|
|
10
|
+
import { UnsupportedStateVersionError } from "../sdk/broker/state-version";
|
|
8
11
|
import { runSdkMcpStdio, SDK_MCP_TOOL_NAMES } from "../sdk/mcp/server";
|
|
9
12
|
|
|
10
13
|
function writeJson(value: unknown): void {
|
|
11
14
|
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
export type CoordinatorBrokerDiscoveryStatus = "ready" | "unavailable" | "error";
|
|
18
|
+
export type CoordinatorBrokerDiscoveryReason =
|
|
19
|
+
| null
|
|
20
|
+
| "absent_or_invalid"
|
|
21
|
+
| "unsupported_state_version"
|
|
22
|
+
| "discovery_access_denied"
|
|
23
|
+
| "discovery_read_failed";
|
|
24
|
+
|
|
25
|
+
export interface CoordinatorBrokerObservation {
|
|
26
|
+
discovery_status: CoordinatorBrokerDiscoveryStatus;
|
|
27
|
+
reason: CoordinatorBrokerDiscoveryReason;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CoordinatorCheckProbe {
|
|
31
|
+
agentDir?: string;
|
|
32
|
+
readBrokerDiscovery?: (agentDir: string) => Promise<BrokerDiscovery | null>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CoordinatorCheckPayload {
|
|
36
|
+
ok: true;
|
|
37
|
+
server: { name: typeof COORDINATOR_MCP_SERVER_NAME; protocolVersion: typeof COORDINATOR_MCP_PROTOCOL_VERSION };
|
|
38
|
+
readOnly: true;
|
|
39
|
+
tools: readonly string[];
|
|
40
|
+
catalog: { ready: true; reason: null };
|
|
41
|
+
broker: CoordinatorBrokerObservation & {
|
|
42
|
+
operational_ready: null;
|
|
43
|
+
bootstrap_supported: true;
|
|
44
|
+
bootstrap_attempted: false;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function discoveryErrorCode(error: unknown): unknown {
|
|
49
|
+
if (typeof error !== "object" || error === null || !("code" in error)) return undefined;
|
|
50
|
+
return error.code;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function probeCoordinatorBrokerCheck(
|
|
54
|
+
probe: CoordinatorCheckProbe = {},
|
|
55
|
+
): Promise<CoordinatorBrokerObservation> {
|
|
56
|
+
try {
|
|
57
|
+
const discovery = await (probe.readBrokerDiscovery ?? readBrokerDiscovery)(probe.agentDir ?? getAgentDir());
|
|
58
|
+
return discovery
|
|
59
|
+
? { discovery_status: "ready", reason: null }
|
|
60
|
+
: { discovery_status: "unavailable", reason: "absent_or_invalid" };
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof UnsupportedStateVersionError)
|
|
63
|
+
return { discovery_status: "error", reason: "unsupported_state_version" };
|
|
64
|
+
const code = discoveryErrorCode(error);
|
|
65
|
+
if (code === "EACCES" || code === "EPERM")
|
|
66
|
+
return { discovery_status: "error", reason: "discovery_access_denied" };
|
|
67
|
+
return { discovery_status: "error", reason: "discovery_read_failed" };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function formatCoordinatorCheckPayload(observation: CoordinatorBrokerObservation): CoordinatorCheckPayload {
|
|
72
|
+
return {
|
|
73
|
+
ok: true,
|
|
74
|
+
server: { name: COORDINATOR_MCP_SERVER_NAME, protocolVersion: COORDINATOR_MCP_PROTOCOL_VERSION },
|
|
75
|
+
readOnly: true,
|
|
76
|
+
tools: [...COORDINATOR_MCP_TOOL_NAMES],
|
|
77
|
+
catalog: { ready: true, reason: null },
|
|
78
|
+
broker: {
|
|
79
|
+
...observation,
|
|
80
|
+
operational_ready: null,
|
|
81
|
+
bootstrap_supported: true,
|
|
82
|
+
bootstrap_attempted: false,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function buildCoordinatorCheckPayload(probe?: CoordinatorCheckProbe): Promise<CoordinatorCheckPayload> {
|
|
88
|
+
return formatCoordinatorCheckPayload(await probeCoordinatorBrokerCheck(probe));
|
|
89
|
+
}
|
|
90
|
+
|
|
14
91
|
export function validateMcpServeSubcommandForTest(server: string | undefined): void {
|
|
15
92
|
if (server !== "coordinator" && server !== "hermes" && server !== "sdk")
|
|
16
93
|
throw new Error(`unknown_mcp_serve_subcommand:${server ?? ""}`);
|
|
@@ -46,17 +123,17 @@ export default class McpServe extends Command {
|
|
|
46
123
|
}
|
|
47
124
|
|
|
48
125
|
if (flags.check) {
|
|
126
|
+
if (!flags.json) {
|
|
127
|
+
const serverName = server === "sdk" ? "gjc-sdk-mcp" : COORDINATOR_MCP_SERVER_NAME;
|
|
128
|
+
const toolCount = server === "sdk" ? SDK_MCP_TOOL_NAMES.length : COORDINATOR_MCP_TOOL_NAMES.length;
|
|
129
|
+
process.stdout.write(`server: ${serverName}\ntools: ${toolCount}\n`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
49
132
|
const payload =
|
|
50
133
|
server === "sdk"
|
|
51
134
|
? { ok: true, server: { name: "gjc-sdk-mcp" }, readOnly: false, tools: [...SDK_MCP_TOOL_NAMES] }
|
|
52
|
-
:
|
|
53
|
-
|
|
54
|
-
server: { name: COORDINATOR_MCP_SERVER_NAME, protocolVersion: COORDINATOR_MCP_PROTOCOL_VERSION },
|
|
55
|
-
readOnly: true,
|
|
56
|
-
tools: [...COORDINATOR_MCP_TOOL_NAMES],
|
|
57
|
-
};
|
|
58
|
-
if (flags.json) writeJson(payload);
|
|
59
|
-
else process.stdout.write(`server: ${payload.server.name}\ntools: ${payload.tools.length}\n`);
|
|
135
|
+
: await buildCoordinatorCheckPayload();
|
|
136
|
+
writeJson(payload);
|
|
60
137
|
return;
|
|
61
138
|
}
|
|
62
139
|
|
package/src/commands/mcp.ts
CHANGED
|
@@ -53,7 +53,7 @@ export default class MCP extends Command {
|
|
|
53
53
|
|
|
54
54
|
async run(): Promise<void> {
|
|
55
55
|
if (this.argv.includes("--help") || this.argv.includes("-h")) {
|
|
56
|
-
this
|
|
56
|
+
this.#printHelp();
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -80,7 +80,7 @@ export default class MCP extends Command {
|
|
|
80
80
|
await runMCPCommand(cmd);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
#printHelp(): void {
|
|
84
84
|
process.stdout.write(`Store standalone MCP server definitions in GJC config without loading them at runtime
|
|
85
85
|
|
|
86
86
|
USAGE
|
package/src/commands/notify.ts
CHANGED
|
@@ -12,9 +12,8 @@ export default class Notify extends Command {
|
|
|
12
12
|
|
|
13
13
|
static args = {
|
|
14
14
|
action: Args.string({
|
|
15
|
-
description: "Notify action",
|
|
15
|
+
description: "Notify action (setup|status|health|test|recovery|daemon-internal)",
|
|
16
16
|
required: false,
|
|
17
|
-
options: ACTIONS,
|
|
18
17
|
}),
|
|
19
18
|
extra: Args.string({
|
|
20
19
|
description: "Provider or additional internal args",
|
|
@@ -49,7 +48,12 @@ export default class Notify extends Command {
|
|
|
49
48
|
|
|
50
49
|
async run(): Promise<void> {
|
|
51
50
|
const { args, flags } = await this.parse(Notify);
|
|
52
|
-
const action =
|
|
51
|
+
const action = args.action ?? "status";
|
|
52
|
+
if (!ACTIONS.includes(action as NotifyAction)) {
|
|
53
|
+
console.error(`Unknown notify action: ${action}`);
|
|
54
|
+
console.error(`Valid actions: ${ACTIONS.join(", ")}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
53
57
|
const extra = Array.isArray(args.extra) ? args.extra : args.extra ? [args.extra] : [];
|
|
54
58
|
const flagRec = flags as Record<string, unknown>;
|
|
55
59
|
const ownerId = flagRec["owner-id"] as string | undefined;
|
|
@@ -72,7 +76,7 @@ export default class Notify extends Command {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
const cmd: NotifyCommandArgs = {
|
|
75
|
-
action,
|
|
79
|
+
action: action as NotifyAction,
|
|
76
80
|
smoke: flags.smoke,
|
|
77
81
|
rawArgs,
|
|
78
82
|
provider: provider === "telegram" || provider === "discord" || provider === "slack" ? provider : undefined,
|
package/src/commands/sdk.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs from "node:fs/promises";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { Args, Command, Flags } from "@gajae-code/utils/cli";
|
|
5
5
|
import type { Args as ParsedArgs } from "../cli/args";
|
|
6
|
+
import { Settings } from "../config/settings";
|
|
6
7
|
import { applyStartupModelProfiles, createSessionManager } from "../main";
|
|
7
8
|
import { initializeExtensions } from "../modes/runtime-init";
|
|
8
9
|
import { Broker } from "../sdk/broker/broker";
|
|
@@ -16,20 +17,28 @@ import {
|
|
|
16
17
|
} from "../sdk/broker/lifecycle";
|
|
17
18
|
import { processIncarnation } from "../sdk/broker/process-incarnation";
|
|
18
19
|
import { type CreateLifecycleAgentSessionResult, createLifecycleAgentSession } from "../sdk/lifecycle-session";
|
|
20
|
+
import { listManagedSessionCandidates, resolveManagedSessionScope } from "../sdk/session-directory";
|
|
19
21
|
import {
|
|
20
22
|
normalizeSdkStartupFailure,
|
|
21
23
|
type SdkStartupFailure,
|
|
22
24
|
type SdkStartupRollbackResult,
|
|
23
25
|
SdkStartupRollbackTracker,
|
|
24
26
|
} from "../sdk/startup-capability";
|
|
25
|
-
|
|
26
27
|
import {
|
|
27
28
|
type CapturedSessionTranscriptSnapshot,
|
|
28
29
|
type ResumeSessionIdentity,
|
|
29
30
|
SessionManager,
|
|
30
31
|
} from "../session/session-manager";
|
|
31
32
|
|
|
32
|
-
export function lifecycleArgs(
|
|
33
|
+
export async function lifecycleArgs(
|
|
34
|
+
request: SessionLifecycleLaunchRequest,
|
|
35
|
+
cwd: string,
|
|
36
|
+
agentDir: string,
|
|
37
|
+
): Promise<ParsedArgs> {
|
|
38
|
+
const targetScope = await resolveManagedSessionScope({ cwd, agentDir });
|
|
39
|
+
if (targetScope.kind !== "resolved") throw new Error(`Lifecycle session scope is invalid: ${targetScope.message}`);
|
|
40
|
+
const forkSessionDir =
|
|
41
|
+
request.operation === "session.fork" ? SessionManager.getDefaultSessionDir(cwd, agentDir) : undefined;
|
|
33
42
|
return {
|
|
34
43
|
messages: [],
|
|
35
44
|
fileArgs: [],
|
|
@@ -39,7 +48,7 @@ export function lifecycleArgs(request: SessionLifecycleLaunchRequest, cwd: strin
|
|
|
39
48
|
...(request.operation === "session.fork"
|
|
40
49
|
? {
|
|
41
50
|
fork: request.sourceSessionPath ?? request.sourceSessionId,
|
|
42
|
-
sessionDir:
|
|
51
|
+
sessionDir: forkSessionDir,
|
|
43
52
|
}
|
|
44
53
|
: {}),
|
|
45
54
|
};
|
|
@@ -53,7 +62,7 @@ type LifecycleTranscriptSource = {
|
|
|
53
62
|
};
|
|
54
63
|
|
|
55
64
|
function sameTranscriptIdentity(
|
|
56
|
-
actual: { dev: bigint; ino: bigint; size: number; mtimeMs: number; mtimeNs: bigint },
|
|
65
|
+
actual: { dev: bigint; ino: bigint; size: number; mtimeMs: number; mtimeNs: bigint; sha256: string },
|
|
57
66
|
expected: SessionLifecycleTranscriptIdentity,
|
|
58
67
|
): boolean {
|
|
59
68
|
return (
|
|
@@ -61,7 +70,8 @@ function sameTranscriptIdentity(
|
|
|
61
70
|
actual.ino.toString() === expected.ino &&
|
|
62
71
|
actual.size === expected.size &&
|
|
63
72
|
actual.mtimeMs === expected.mtimeMs &&
|
|
64
|
-
actual.mtimeNs.toString() === expected.mtimeNs
|
|
73
|
+
actual.mtimeNs.toString() === expected.mtimeNs &&
|
|
74
|
+
actual.sha256 === expected.sha256
|
|
65
75
|
);
|
|
66
76
|
}
|
|
67
77
|
|
|
@@ -85,26 +95,38 @@ function lifecycleTranscriptSource(request: SessionLifecycleLaunchRequest, cwd:
|
|
|
85
95
|
throw new Error("A new lifecycle session has no persisted transcript authority.");
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
function
|
|
98
|
+
async function captureLifecycleTranscript(
|
|
89
99
|
request: SessionLifecycleLaunchRequest,
|
|
90
100
|
cwd: string,
|
|
91
101
|
agentDir: string,
|
|
92
|
-
|
|
102
|
+
migrationPolicy: "copy-retain" | "disabled",
|
|
103
|
+
): Promise<CapturedSessionTranscriptSnapshot> {
|
|
93
104
|
const source = lifecycleTranscriptSource(request, cwd);
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
105
|
+
const scope = await resolveManagedSessionScope({ cwd: source.cwd, agentDir });
|
|
106
|
+
if (scope.kind !== "resolved")
|
|
107
|
+
throw new Error("Lifecycle saved session storage could not be verified for the requested workspace.");
|
|
108
|
+
const inventory = await listManagedSessionCandidates({ scope: scope.scope });
|
|
97
109
|
if (inventory.kind !== "complete")
|
|
98
110
|
throw new Error("Lifecycle saved session storage could not be verified for the requested workspace.");
|
|
99
|
-
const
|
|
111
|
+
const captured = SessionManager.captureTranscriptStrict(source.path);
|
|
112
|
+
if (
|
|
113
|
+
captured.kind !== "captured" ||
|
|
114
|
+
captured.snapshot.sourcePath !== path.resolve(source.path) ||
|
|
115
|
+
captured.snapshot.identity.sessionId !== source.id ||
|
|
116
|
+
!sameTranscriptIdentity(captured.snapshot.identity, source.identity)
|
|
117
|
+
)
|
|
118
|
+
throw new Error("Lifecycle saved session authority changed before the session host consumed it.");
|
|
119
|
+
const matches = inventory.owned.filter(
|
|
100
120
|
candidate =>
|
|
101
|
-
candidate.path ===
|
|
102
|
-
candidate.
|
|
103
|
-
|
|
121
|
+
candidate.path === captured.snapshot.sourcePath &&
|
|
122
|
+
candidate.sessionId === source.id &&
|
|
123
|
+
sameLifecycleTranscriptSnapshot(candidate.identity, captured.snapshot.identity),
|
|
104
124
|
);
|
|
105
125
|
if (matches.length !== 1)
|
|
106
126
|
throw new Error("Lifecycle saved session authority changed before the session host started.");
|
|
107
|
-
|
|
127
|
+
if (matches[0]!.provenance === "legacy" && migrationPolicy === "disabled")
|
|
128
|
+
throw new Error("Lifecycle legacy session migration is disabled by policy.");
|
|
129
|
+
return captured.snapshot;
|
|
108
130
|
}
|
|
109
131
|
|
|
110
132
|
function sameLifecycleTranscriptSnapshot(left: ResumeSessionIdentity, right: ResumeSessionIdentity): boolean {
|
|
@@ -120,23 +142,6 @@ function sameLifecycleTranscriptSnapshot(left: ResumeSessionIdentity, right: Res
|
|
|
120
142
|
);
|
|
121
143
|
}
|
|
122
144
|
|
|
123
|
-
function captureLifecycleTranscript(
|
|
124
|
-
request: SessionLifecycleLaunchRequest,
|
|
125
|
-
cwd: string,
|
|
126
|
-
agentDir: string,
|
|
127
|
-
): CapturedSessionTranscriptSnapshot {
|
|
128
|
-
const source = verifyLifecycleTranscript(request, cwd, agentDir);
|
|
129
|
-
const captured = SessionManager.captureTranscriptStrict(source.path);
|
|
130
|
-
if (
|
|
131
|
-
captured.kind !== "captured" ||
|
|
132
|
-
captured.snapshot.sourcePath !== path.resolve(source.path) ||
|
|
133
|
-
captured.snapshot.identity.sessionId !== source.id ||
|
|
134
|
-
!sameTranscriptIdentity(captured.snapshot.identity, source.identity)
|
|
135
|
-
)
|
|
136
|
-
throw new Error("Lifecycle saved session authority changed before the session host consumed it.");
|
|
137
|
-
return captured.snapshot;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
145
|
async function revalidateLifecycleTranscript(snapshot: ResumeSessionIdentity): Promise<void> {
|
|
141
146
|
const inspected = await SessionManager.inspectSessionTailReadOnly(snapshot.canonicalPath);
|
|
142
147
|
if (inspected.kind === "error" || !sameLifecycleTranscriptSnapshot(snapshot, inspected.identity))
|
|
@@ -149,14 +154,22 @@ export async function openLifecycleSessionManager(
|
|
|
149
154
|
cwd: string,
|
|
150
155
|
agentDir: string,
|
|
151
156
|
): Promise<{ parsed: ParsedArgs; sessionManager: SessionManager | undefined }> {
|
|
152
|
-
const parsed = lifecycleArgs(request, cwd, agentDir);
|
|
157
|
+
const parsed = await lifecycleArgs(request, cwd, agentDir);
|
|
158
|
+
const lifecycleSettings = await Settings.loadForScope({ cwd, agentDir });
|
|
159
|
+
const migrationPolicy =
|
|
160
|
+
lifecycleSettings.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
|
|
153
161
|
if (request.operation === "session.create") {
|
|
154
|
-
return { parsed, sessionManager: await createSessionManager(parsed, cwd) };
|
|
162
|
+
return { parsed, sessionManager: await createSessionManager(parsed, cwd, lifecycleSettings) };
|
|
155
163
|
}
|
|
156
|
-
const snapshot = captureLifecycleTranscript(request, cwd, agentDir);
|
|
164
|
+
const snapshot = await captureLifecycleTranscript(request, cwd, agentDir, migrationPolicy);
|
|
157
165
|
let sessionManager: SessionManager | undefined;
|
|
158
166
|
if (request.operation === "session.resume") {
|
|
159
|
-
const opened = await SessionManager.openExistingStrict(
|
|
167
|
+
const opened = await SessionManager.openExistingStrict(
|
|
168
|
+
snapshot.identity,
|
|
169
|
+
parsed.sessionDir,
|
|
170
|
+
undefined,
|
|
171
|
+
migrationPolicy,
|
|
172
|
+
);
|
|
160
173
|
if (opened.kind === "error")
|
|
161
174
|
throw new Error("Lifecycle saved session authority changed while the session host opened it.");
|
|
162
175
|
sessionManager = opened.manager;
|
|
@@ -167,7 +180,7 @@ export async function openLifecycleSessionManager(
|
|
|
167
180
|
throw error;
|
|
168
181
|
}
|
|
169
182
|
} else {
|
|
170
|
-
const forked = await SessionManager.forkFromCaptured(snapshot, cwd, parsed.sessionDir);
|
|
183
|
+
const forked = await SessionManager.forkFromCaptured(snapshot, cwd, parsed.sessionDir, migrationPolicy);
|
|
171
184
|
if (forked.kind === "error")
|
|
172
185
|
throw new Error("Lifecycle saved session authority changed while the session host forked it.");
|
|
173
186
|
sessionManager = forked.manager;
|
|
@@ -302,21 +315,23 @@ export async function runSessionHost(
|
|
|
302
315
|
fs.readFile(transcriptPath),
|
|
303
316
|
fs.stat(transcriptPath, { bigint: true }),
|
|
304
317
|
]);
|
|
318
|
+
const digest = createHash("sha256").update(bytes).digest("hex");
|
|
305
319
|
return {
|
|
306
|
-
digest
|
|
320
|
+
digest,
|
|
307
321
|
identity: {
|
|
308
322
|
dev: stat.dev.toString(),
|
|
309
323
|
ino: stat.ino.toString(),
|
|
310
324
|
size: Number(stat.size),
|
|
311
325
|
mtimeMs: Number(stat.mtimeMs),
|
|
312
326
|
mtimeNs: stat.mtimeNs.toString(),
|
|
327
|
+
sha256: digest,
|
|
313
328
|
},
|
|
314
329
|
};
|
|
315
330
|
} catch {
|
|
316
331
|
return undefined;
|
|
317
332
|
}
|
|
318
333
|
})();
|
|
319
|
-
return disposal;
|
|
334
|
+
return disposal ?? Promise.resolve(undefined);
|
|
320
335
|
};
|
|
321
336
|
let failureRollback: Promise<void> | undefined;
|
|
322
337
|
const failAfterRollback = (failure: SdkStartupFailure): Promise<void> => {
|
|
@@ -415,7 +430,13 @@ export default class Sdk extends Command {
|
|
|
415
430
|
}
|
|
416
431
|
const agentDir = flags["agent-dir"] as string | undefined;
|
|
417
432
|
if (!agentDir) throw new Error("--agent-dir is required for sdk broker-internal.");
|
|
418
|
-
const broker = new Broker({
|
|
433
|
+
const broker = new Broker({
|
|
434
|
+
agentDir,
|
|
435
|
+
resolveDirectoryMigration: async cwd => {
|
|
436
|
+
const policy = (await Settings.loadForScope({ cwd, agentDir })).get("session.directoryMigration");
|
|
437
|
+
return policy === "disabled" ? "disabled" : "copy-retain";
|
|
438
|
+
},
|
|
439
|
+
});
|
|
419
440
|
await broker.start();
|
|
420
441
|
if (!broker.ownsDiscovery) return;
|
|
421
442
|
const stop = () => void broker.stop().finally(() => process.exit(0));
|
|
@@ -26,15 +26,18 @@ export default class Ultragoal extends Command {
|
|
|
26
26
|
if (isReviewStart && !result.createdReviewPlan && (result.reviewBlockerGoalIds?.length ?? 0) === 0) return;
|
|
27
27
|
|
|
28
28
|
const cwd = process.cwd();
|
|
29
|
-
const { objective, goalsPath } = await readUltragoalGjcObjective(cwd);
|
|
29
|
+
const { objective, goalsPath, provenance } = await readUltragoalGjcObjective(cwd);
|
|
30
|
+
|
|
30
31
|
await writeCurrentSessionGoalModeState({
|
|
31
32
|
sessionFile: process.env[GJC_SESSION_FILE_ENV],
|
|
32
33
|
objective,
|
|
34
|
+
provenance,
|
|
33
35
|
});
|
|
34
36
|
await writePendingGoalModeRequest({
|
|
35
37
|
cwd,
|
|
36
38
|
objective,
|
|
37
39
|
goalsPath,
|
|
40
|
+
provenance,
|
|
38
41
|
sessionId: process.env[GJC_SESSION_ID_ENV],
|
|
39
42
|
});
|
|
40
43
|
}
|