gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.0fdacd524
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 +8 -7
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +77 -38
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +43 -8
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +9 -13
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +30 -13
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +90 -46
- package/dist/resources/extensions/google-search/index.js +2 -6
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +5 -13
- package/dist/resources/extensions/gsd/auto/run-unit.js +26 -12
- package/dist/resources/extensions/gsd/auto/session.js +5 -6
- package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +55 -21
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +69 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +60 -13
- package/dist/resources/extensions/gsd/auto.js +39 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +112 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +45 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
- package/dist/resources/extensions/gsd/commands-config.js +3 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/commands-worktree.js +309 -0
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +10 -8
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +25 -24
- package/dist/resources/extensions/gsd/home-dir.js +16 -0
- package/dist/resources/extensions/gsd/key-manager.js +2 -1
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/migrate/command.js +3 -2
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
- package/dist/resources/extensions/gsd/worktree-root.js +124 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/gsd/worktree.js +4 -115
- package/dist/resources/extensions/mcp-client/index.js +6 -9
- package/dist/resources/extensions/ollama/index.js +15 -2
- package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
- package/dist/resources/extensions/ollama/ollama-client.js +40 -4
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/extensions/subagent/index.js +324 -178
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/skills/lint/SKILL.md +4 -0
- package/dist/resources/skills/review/SKILL.md +4 -0
- package/dist/resources/skills/test/SKILL.md +3 -0
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +13 -13
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -1
- package/dist/welcome-screen.js +27 -1
- package/dist/worktree-cli.d.ts +1 -0
- package/dist/worktree-cli.js +9 -3
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +92 -47
- package/src/resources/extensions/google-search/index.ts +2 -9
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +6 -14
- package/src/resources/extensions/gsd/auto/run-unit.ts +26 -12
- package/src/resources/extensions/gsd/auto/session.ts +5 -6
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +60 -24
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +66 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
- package/src/resources/extensions/gsd/auto.ts +37 -10
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +121 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- package/src/resources/extensions/gsd/commands-config.ts +3 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +12 -7
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +27 -26
- package/src/resources/extensions/gsd/home-dir.ts +19 -0
- package/src/resources/extensions/gsd/journal.ts +4 -1
- package/src/resources/extensions/gsd/key-manager.ts +2 -1
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +2 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +179 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +50 -27
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +25 -65
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +235 -0
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
- package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
- package/src/resources/extensions/gsd/worktree-root.ts +144 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/gsd/worktree.ts +8 -119
- package/src/resources/extensions/mcp-client/index.ts +6 -10
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/ollama/index.ts +16 -2
- package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
- package/src/resources/extensions/ollama/ollama-client.ts +41 -4
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
- package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/extensions/subagent/index.ts +165 -7
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/src/resources/skills/lint/SKILL.md +4 -0
- package/src/resources/skills/review/SKILL.md +4 -0
- package/src/resources/skills/test/SKILL.md +3 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { minimatch } from "minimatch";
|
|
4
|
+
import { logWarning } from "../workflow-logger.js";
|
|
4
5
|
/**
|
|
5
6
|
* Regex matching milestone CONTEXT.md file names in both legacy M001
|
|
6
7
|
* and unique M001-abc123 formats. Exported so regex-hardening tests
|
|
@@ -441,8 +442,67 @@ export function shouldBlockQueueExecutionInSnapshot(snapshot, toolName, input, q
|
|
|
441
442
|
};
|
|
442
443
|
}
|
|
443
444
|
// ─── Planning-unit tools-policy enforcement (#4934) ───────────────────────
|
|
445
|
+
//
|
|
446
|
+
// Runtime half of the declarative ToolsPolicy on UnitContextManifest. The
|
|
447
|
+
// manifest assigns each unit type a tools mode; this predicate is what
|
|
448
|
+
// actually rejects a tool call that violates it.
|
|
449
|
+
//
|
|
450
|
+
// Forensics: a discuss-milestone LLM turn used the host Edit tool to modify
|
|
451
|
+
// index.html in test app b23 (~/Github/test-apps/b23). With this predicate
|
|
452
|
+
// wired into the tool_call hook, the same call returns block=true with a
|
|
453
|
+
// HARD BLOCK reason that the model cannot rationalize past.
|
|
454
|
+
//
|
|
455
|
+
// Activation: the hook supplies the policy resolved from the active unit's
|
|
456
|
+
// manifest. When no unit is active (interactive sessions, unknown unit
|
|
457
|
+
// types), the hook passes null and this predicate is a no-op — falling
|
|
458
|
+
// through to the existing pendingGate / queue-execution / context-write
|
|
459
|
+
// guards.
|
|
444
460
|
const PLANNING_WRITE_TOOLS = new Set(["write", "edit", "multi_edit", "notebook_edit"]);
|
|
445
461
|
const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
|
|
462
|
+
/**
|
|
463
|
+
* Canonical registry for agents that planning-dispatch may consider. Unit
|
|
464
|
+
* manifests still declare per-unit subsets via ToolsPolicy.allowedSubagents.
|
|
465
|
+
*/
|
|
466
|
+
const PLANNING_DISPATCH_AGENT_REGISTRY = {
|
|
467
|
+
scout: { readOnlySpecialist: true },
|
|
468
|
+
planner: { readOnlySpecialist: true },
|
|
469
|
+
reviewer: { readOnlySpecialist: true },
|
|
470
|
+
security: { readOnlySpecialist: true },
|
|
471
|
+
tester: { readOnlySpecialist: true },
|
|
472
|
+
};
|
|
473
|
+
export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set(Object.entries(PLANNING_DISPATCH_AGENT_REGISTRY)
|
|
474
|
+
.filter(([, metadata]) => metadata.readOnlySpecialist)
|
|
475
|
+
.map(([agentId]) => agentId));
|
|
476
|
+
let warnedMissingPlanningDispatchAgentClasses = false;
|
|
477
|
+
function isReadOnlySpecialist(agentId) {
|
|
478
|
+
const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId];
|
|
479
|
+
return metadata?.readOnlySpecialist === true;
|
|
480
|
+
}
|
|
481
|
+
function allowedPlanningDispatchAgentsList() {
|
|
482
|
+
return [...ALLOWED_PLANNING_DISPATCH_AGENTS].join(", ");
|
|
483
|
+
}
|
|
484
|
+
function warnMissingPlanningDispatchAgentClasses(unitType, mode, toolName) {
|
|
485
|
+
if (warnedMissingPlanningDispatchAgentClasses)
|
|
486
|
+
return;
|
|
487
|
+
warnedMissingPlanningDispatchAgentClasses = true;
|
|
488
|
+
// TODO(#5060): Remove this migration shim once all subagent/task callers are verified to forward agent identities.
|
|
489
|
+
const message = `[write-gate] planning-dispatch: shouldBlockPlanningUnit called for tool "${toolName}" ` +
|
|
490
|
+
`on unit "${unitType}" without agentClasses - stale caller; blocking dispatch.`;
|
|
491
|
+
console.warn(message);
|
|
492
|
+
logWarning("intercept", message, {
|
|
493
|
+
unitType,
|
|
494
|
+
mode,
|
|
495
|
+
toolName,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Read-only / planning-safe tools that any non-"all" mode allows. Mirrors
|
|
500
|
+
* QUEUE_SAFE_TOOLS / GATE_SAFE_TOOLS but is the inclusive default for
|
|
501
|
+
* planning units (which need their full discussion + research surface).
|
|
502
|
+
*
|
|
503
|
+
* gsd_* MCP tools are passed through unconditionally — they have their own
|
|
504
|
+
* domain validation (e.g. depth-verification gate, single-writer DB).
|
|
505
|
+
*/
|
|
446
506
|
const PLANNING_SAFE_TOOLS = new Set([
|
|
447
507
|
"read", "grep", "find", "ls", "glob",
|
|
448
508
|
"ask_user_questions",
|
|
@@ -458,6 +518,7 @@ function matchesAllowedGlob(absPath, basePath, globs) {
|
|
|
458
518
|
const rel = relative(basePath, absPath);
|
|
459
519
|
if (rel.startsWith("..") || isAbsolute(rel))
|
|
460
520
|
return false;
|
|
521
|
+
// Normalize Windows separators for minimatch.
|
|
461
522
|
const posix = rel.split(sep).join("/");
|
|
462
523
|
return globs.some(g => minimatch(posix, g, { dot: false, nocase: false }));
|
|
463
524
|
}
|
|
@@ -477,17 +538,32 @@ function blockReason(unitType, mode, what) {
|
|
|
477
538
|
* - "read-only" → blocks all writes, bash, and subagent dispatch.
|
|
478
539
|
* - "planning" → blocks writes to paths outside <basePath>/.gsd/,
|
|
479
540
|
* bash that isn't read-only, and subagent dispatch.
|
|
541
|
+
* - "planning-dispatch"
|
|
542
|
+
* → like "planning", but permits subagent dispatch only
|
|
543
|
+
* when every forwarded agent class is globally allowed
|
|
544
|
+
* and listed in the policy's allowedSubagents.
|
|
480
545
|
* - "docs" → like "planning" but also allows writes to paths
|
|
481
546
|
* matching `allowedPathGlobs` relative to basePath.
|
|
482
547
|
*
|
|
483
|
-
* `
|
|
548
|
+
* `pathOrCommand` is the file path for write/edit-shaped tools and the
|
|
549
|
+
* shell command for bash. Other tools ignore this argument.
|
|
550
|
+
*
|
|
551
|
+
* `policy` of null means "no manifest resolved" — pass-through. Callers
|
|
552
|
+
* that have no active unit (interactive sessions) pass null and this
|
|
553
|
+
* predicate is a no-op.
|
|
554
|
+
*
|
|
555
|
+
* `agentClasses` is supplied by the tool hook for subagent-shaped calls. If
|
|
556
|
+
* absent, planning-dispatch fails closed so stale callers cannot silently
|
|
557
|
+
* bypass the agent allowlists. An explicitly supplied-but-empty list is
|
|
558
|
+
* allowed through so the downstream tool call can reject the malformed input.
|
|
484
559
|
*/
|
|
485
|
-
export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitType, policy) {
|
|
560
|
+
export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitType, policy, agentClasses) {
|
|
486
561
|
if (!policy)
|
|
487
562
|
return { block: false };
|
|
488
563
|
if (policy.mode === "all")
|
|
489
564
|
return { block: false };
|
|
490
565
|
const tool = toolName;
|
|
566
|
+
// Read-only mode: only Read-class tools are permitted.
|
|
491
567
|
if (policy.mode === "read-only") {
|
|
492
568
|
if (PLANNING_SAFE_TOOLS.has(tool))
|
|
493
569
|
return { block: false };
|
|
@@ -496,14 +572,51 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
496
572
|
if (PLANNING_WRITE_TOOLS.has(tool) || tool === "bash" || PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
497
573
|
return { block: true, reason: blockReason(unitType, policy.mode, `${tool} is not permitted (read-only)`) };
|
|
498
574
|
}
|
|
575
|
+
// Unknown tool in read-only mode — block by default.
|
|
499
576
|
return { block: true, reason: blockReason(unitType, policy.mode, `tool "${tool}" is not on the read-only allowlist`) };
|
|
500
577
|
}
|
|
501
|
-
// planning / docs modes
|
|
578
|
+
// planning / planning-dispatch / docs modes share the same surface for safe tools, bash, and subagent.
|
|
502
579
|
if (PLANNING_SAFE_TOOLS.has(tool))
|
|
503
580
|
return { block: false };
|
|
504
581
|
if (tool.startsWith("gsd_"))
|
|
505
582
|
return { block: false };
|
|
506
583
|
if (PLANNING_SUBAGENT_TOOLS.has(tool)) {
|
|
584
|
+
if (policy.mode === "planning-dispatch") {
|
|
585
|
+
const requested = (agentClasses ?? []).map(a => a.trim()).filter(Boolean);
|
|
586
|
+
const allowedSubagents = Array.isArray(policy.allowedSubagents) ? policy.allowedSubagents : [];
|
|
587
|
+
const allowed = new Set(allowedSubagents);
|
|
588
|
+
// When agentClasses is undefined, the caller has not been updated to extract
|
|
589
|
+
// agent identities yet. Block and warn so stale callers surface in telemetry
|
|
590
|
+
// instead of silently bypassing the gate.
|
|
591
|
+
if (agentClasses === undefined) {
|
|
592
|
+
warnMissingPlanningDispatchAgentClasses(unitType, policy.mode, tool);
|
|
593
|
+
return {
|
|
594
|
+
block: true,
|
|
595
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch blocked: stale caller did not supply agent identities for "${tool}"; update extractSubagentAgentClasses to handle this input shape`),
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
// agentClasses was explicitly provided but resolved to an empty list (for
|
|
599
|
+
// example, a bare tool call with no agent field). Pass through; no agents
|
|
600
|
+
// to validate means the downstream tool call itself will fail.
|
|
601
|
+
if (requested.length === 0) {
|
|
602
|
+
return { block: false };
|
|
603
|
+
}
|
|
604
|
+
const globallyDisallowed = requested.find(a => !isReadOnlySpecialist(a));
|
|
605
|
+
if (globallyDisallowed) {
|
|
606
|
+
return {
|
|
607
|
+
block: true,
|
|
608
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch of "${globallyDisallowed}" not permitted; only read-only specialists (${allowedPlanningDispatchAgentsList()}) may be dispatched from planning-dispatch units`),
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
const disallowedByPolicy = requested.find(a => !allowed.has(a));
|
|
612
|
+
if (disallowedByPolicy) {
|
|
613
|
+
return {
|
|
614
|
+
block: true,
|
|
615
|
+
reason: blockReason(unitType, policy.mode, `subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`),
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return { block: false };
|
|
619
|
+
}
|
|
507
620
|
return { block: true, reason: blockReason(unitType, policy.mode, `subagent dispatch is not permitted in planning units`) };
|
|
508
621
|
}
|
|
509
622
|
if (tool === "bash") {
|
|
@@ -519,8 +632,10 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
519
632
|
return { block: true, reason: blockReason(unitType, policy.mode, `${tool} called with empty path`) };
|
|
520
633
|
}
|
|
521
634
|
const absPath = isAbsolute(pathOrCommand) ? pathOrCommand : resolve(basePath, pathOrCommand);
|
|
635
|
+
// Always allow .gsd/ writes — that's where planning artifacts live.
|
|
522
636
|
if (isPathUnderGsd(absPath, basePath))
|
|
523
637
|
return { block: false };
|
|
638
|
+
// docs mode additionally allows the manifest's allowedPathGlobs.
|
|
524
639
|
if (policy.mode === "docs" && matchesAllowedGlob(absPath, basePath, policy.allowedPathGlobs)) {
|
|
525
640
|
return { block: false };
|
|
526
641
|
}
|
|
@@ -529,5 +644,8 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
529
644
|
reason: blockReason(unitType, policy.mode, `cannot ${tool} "${pathOrCommand}" — writes are restricted to .gsd/${policy.mode === "docs" ? " and " + policy.allowedPathGlobs.join(", ") : ""}`),
|
|
530
645
|
};
|
|
531
646
|
}
|
|
647
|
+
// Unknown tool name — pass through. Other layers (queue, pending-gate,
|
|
648
|
+
// CONTEXT.md write) catch known mutating shapes; defaulting to allow here
|
|
649
|
+
// avoids breaking gsd_* MCP tools or future safe additions.
|
|
532
650
|
return { block: false };
|
|
533
651
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
4
|
import { loadRegistry } from "../workflow-templates.js";
|
|
5
|
-
import { resolveProjectRoot } from "../worktree.js";
|
|
6
5
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
7
|
-
export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|fast|mcp|rethink|codebase|notifications|ship|do|session-report|backlog|pr-branch|add-tests|scan|language";
|
|
6
|
+
export const GSD_COMMAND_DESCRIPTION = "GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|model|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|debug|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|onboarding|inspect|extensions|update|fast|mcp|rethink|workflow|codebase|notifications|ship|do|session-report|backlog|pr-branch|add-tests|scan|language|worktree";
|
|
8
7
|
export const TOP_LEVEL_SUBCOMMANDS = [
|
|
9
8
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
10
9
|
{ cmd: "next", desc: "Explicit step mode (same as /gsd)" },
|
|
@@ -72,6 +71,7 @@ export const TOP_LEVEL_SUBCOMMANDS = [
|
|
|
72
71
|
{ cmd: "add-tests", desc: "Generate tests for completed slices" },
|
|
73
72
|
{ cmd: "scan", desc: "Rapid codebase assessment — lightweight alternative to full map (--focus tech|arch|quality|concerns|tech+arch)" },
|
|
74
73
|
{ cmd: "language", desc: "Set or clear the global response language (e.g. /gsd language Chinese)" },
|
|
74
|
+
{ cmd: "worktree", desc: "Manage worktrees from the TUI (list, merge, clean, remove)" },
|
|
75
75
|
];
|
|
76
76
|
const NESTED_COMPLETIONS = {
|
|
77
77
|
auto: [
|
|
@@ -287,6 +287,12 @@ const NESTED_COMPLETIONS = {
|
|
|
287
287
|
{ cmd: "off", desc: "Clear the language preference (revert to default)" },
|
|
288
288
|
{ cmd: "clear", desc: "Alias for off — clear the language preference" },
|
|
289
289
|
],
|
|
290
|
+
worktree: [
|
|
291
|
+
{ cmd: "list", desc: "Show all worktrees with status" },
|
|
292
|
+
{ cmd: "merge", desc: "Merge a worktree into main and clean up" },
|
|
293
|
+
{ cmd: "clean", desc: "Remove all merged/empty worktrees" },
|
|
294
|
+
{ cmd: "remove", desc: "Remove a worktree (--force to skip safety checks)" },
|
|
295
|
+
],
|
|
290
296
|
};
|
|
291
297
|
function filterOptions(partial, options, prefix = "") {
|
|
292
298
|
const normalizedPrefix = prefix ? `${prefix} ` : "";
|
|
@@ -330,6 +336,71 @@ function getExtensionCompletions(prefix, action) {
|
|
|
330
336
|
return [];
|
|
331
337
|
}
|
|
332
338
|
}
|
|
339
|
+
function normalizePathForCompare(path) {
|
|
340
|
+
return path.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
341
|
+
}
|
|
342
|
+
function findWorktreeSegment(normalizedPath) {
|
|
343
|
+
const directMarker = "/.gsd/worktrees/";
|
|
344
|
+
const directIdx = normalizedPath.indexOf(directMarker);
|
|
345
|
+
if (directIdx !== -1) {
|
|
346
|
+
return { gsdIdx: directIdx, afterWorktrees: directIdx + directMarker.length };
|
|
347
|
+
}
|
|
348
|
+
const symlinkMatch = normalizedPath.match(/\/\.gsd\/projects\/[a-f0-9]+\/worktrees\//);
|
|
349
|
+
if (symlinkMatch?.index !== undefined) {
|
|
350
|
+
return { gsdIdx: symlinkMatch.index, afterWorktrees: symlinkMatch.index + symlinkMatch[0].length };
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
function resolveProjectRootFromGitFile(worktreePath) {
|
|
355
|
+
try {
|
|
356
|
+
let dir = worktreePath;
|
|
357
|
+
for (let i = 0; i < 30; i++) {
|
|
358
|
+
const gitPath = join(dir, ".git");
|
|
359
|
+
if (existsSync(gitPath)) {
|
|
360
|
+
const content = readFileSync(gitPath, "utf8").trim();
|
|
361
|
+
if (content.startsWith("gitdir: ")) {
|
|
362
|
+
const gitDir = resolve(dir, content.slice(8));
|
|
363
|
+
const dotGitDir = resolve(gitDir, "..", "..");
|
|
364
|
+
if (dotGitDir.endsWith(".git") || dotGitDir.endsWith(".git/") || dotGitDir.endsWith(".git\\")) {
|
|
365
|
+
return resolve(dotGitDir, "..");
|
|
366
|
+
}
|
|
367
|
+
const commonDirPath = join(gitDir, "commondir");
|
|
368
|
+
if (existsSync(commonDirPath)) {
|
|
369
|
+
const commonDir = readFileSync(commonDirPath, "utf8").trim();
|
|
370
|
+
return resolve(resolve(gitDir, commonDir), "..");
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
const parent = resolve(dir, "..");
|
|
376
|
+
if (parent === dir)
|
|
377
|
+
break;
|
|
378
|
+
dir = parent;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// Completion must stay best-effort.
|
|
383
|
+
}
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
function resolveProjectRootForCompletion(basePath) {
|
|
387
|
+
if (process.env.GSD_PROJECT_ROOT)
|
|
388
|
+
return process.env.GSD_PROJECT_ROOT;
|
|
389
|
+
const normalizedPath = normalizePathForCompare(basePath);
|
|
390
|
+
const segment = findWorktreeSegment(normalizedPath);
|
|
391
|
+
if (!segment)
|
|
392
|
+
return basePath;
|
|
393
|
+
const separator = basePath.includes("\\") ? "\\" : "/";
|
|
394
|
+
const gsdMarker = `${separator}.gsd${separator}`;
|
|
395
|
+
const gsdIdx = basePath.indexOf(gsdMarker);
|
|
396
|
+
const candidate = gsdIdx !== -1 ? basePath.slice(0, gsdIdx) : basePath.slice(0, segment.gsdIdx);
|
|
397
|
+
const normalizedGsdHome = normalizePathForCompare(gsdHome);
|
|
398
|
+
const candidateGsdPath = normalizePathForCompare(join(candidate, ".gsd"));
|
|
399
|
+
if (candidateGsdPath === normalizedGsdHome || candidateGsdPath.startsWith(`${normalizedGsdHome}/`)) {
|
|
400
|
+
return resolveProjectRootFromGitFile(basePath) ?? basePath;
|
|
401
|
+
}
|
|
402
|
+
return candidate;
|
|
403
|
+
}
|
|
333
404
|
export function getGsdArgumentCompletions(prefix) {
|
|
334
405
|
const hasTrailingSpace = prefix.endsWith(" ");
|
|
335
406
|
const parts = prefix.trim().split(/\s+/);
|
|
@@ -384,7 +455,7 @@ export function getGsdArgumentCompletions(prefix) {
|
|
|
384
455
|
// Workflow definition-name completion for `workflow run <name>` and `workflow validate <name>`
|
|
385
456
|
if (command === "workflow" && (subcommand === "run" || subcommand === "validate") && parts.length <= 3) {
|
|
386
457
|
try {
|
|
387
|
-
const defsDir = join(
|
|
458
|
+
const defsDir = join(resolveProjectRootForCompletion(process.cwd()), ".gsd", "workflow-defs");
|
|
388
459
|
if (existsSync(defsDir)) {
|
|
389
460
|
return readdirSync(defsDir)
|
|
390
461
|
.filter((f) => f.endsWith(".yaml") && f.startsWith(third))
|
|
@@ -426,7 +497,7 @@ export function getGsdArgumentCompletions(prefix) {
|
|
|
426
497
|
catch { /* ignore */ }
|
|
427
498
|
};
|
|
428
499
|
try {
|
|
429
|
-
const base =
|
|
500
|
+
const base = resolveProjectRootForCompletion(process.cwd());
|
|
430
501
|
scanDir(join(base, ".gsd", "workflows"), "project");
|
|
431
502
|
scanDir(join(base, ".gsd", "workflow-defs"), "project-legacy");
|
|
432
503
|
scanDir(join(gsdHome, "workflows"), "global");
|
|
@@ -58,16 +58,21 @@ export function showHelp(ctx, args = "") {
|
|
|
58
58
|
" /gsd pause Pause auto-mode (preserves state, /gsd auto to resume)",
|
|
59
59
|
" /gsd discuss Start guided milestone/slice discussion",
|
|
60
60
|
" /gsd new-milestone Create milestone from headless context (used by gsd headless)",
|
|
61
|
+
" /gsd quick Execute a quick task without full planning overhead",
|
|
62
|
+
" /gsd dispatch Dispatch a specific phase directly [research|plan|execute|complete|uat|replan]",
|
|
63
|
+
" /gsd parallel Parallel milestone orchestration [start|status|stop|pause|resume|merge|watch]",
|
|
64
|
+
" /gsd workflow Custom workflow lifecycle [new|run|list|validate|pause|resume]",
|
|
61
65
|
"",
|
|
62
66
|
"VISIBILITY",
|
|
63
67
|
` /gsd status Show progress dashboard (${formattedShortcutPair("dashboard")})`,
|
|
64
68
|
` /gsd parallel watch Open parallel worker monitor (${formattedShortcutPair("parallel")})`,
|
|
69
|
+
" /gsd widget Cycle status widget [full|small|min|off]",
|
|
65
70
|
" /gsd visualize Interactive 10-tab TUI (progress, timeline, deps, metrics, health, agent, changes, knowledge, captures, export)",
|
|
66
71
|
" /gsd queue Show queued/dispatched units and execution order",
|
|
67
72
|
" /gsd history View execution history [--cost] [--phase] [--model] [N]",
|
|
68
73
|
" /gsd changelog Show categorized release notes [version]",
|
|
69
74
|
` /gsd notifications View persistent notification history [clear|tail|filter] (${formattedShortcutPair("notifications")})`,
|
|
70
|
-
" /gsd logs Browse activity logs, debug logs, and metrics",
|
|
75
|
+
" /gsd logs Browse activity logs, debug logs, and metrics [debug|tail|clear]",
|
|
71
76
|
" /gsd debug Create/list/continue persistent debug sessions",
|
|
72
77
|
"",
|
|
73
78
|
"COURSE CORRECTION",
|
|
@@ -76,6 +81,9 @@ export function showHelp(ctx, args = "") {
|
|
|
76
81
|
" /gsd triage Classify and route pending captures",
|
|
77
82
|
" /gsd skip <unit> Prevent a unit from auto-mode dispatch",
|
|
78
83
|
" /gsd undo Revert last completed unit [--force]",
|
|
84
|
+
" /gsd undo-task Reset a specific task's completion state [DB + markdown]",
|
|
85
|
+
" /gsd reset-slice Reset a slice and all its tasks [DB + markdown]",
|
|
86
|
+
" /gsd rate Rate last unit's model tier [over|ok|under]",
|
|
79
87
|
" /gsd rethink Conversational project reorganization — reorder, park, discard, add milestones",
|
|
80
88
|
" /gsd park [id] Park a milestone — skip without deleting [reason]",
|
|
81
89
|
" /gsd unpark [id] Reactivate a parked milestone",
|
|
@@ -84,6 +92,15 @@ export function showHelp(ctx, args = "") {
|
|
|
84
92
|
" /gsd knowledge <type> <text> Add rule, pattern, or lesson to KNOWLEDGE.md",
|
|
85
93
|
" /gsd codebase [generate|update|stats] Manage the CODEBASE.md cache used in prompt context",
|
|
86
94
|
"",
|
|
95
|
+
"SHIPPING & BACKLOG",
|
|
96
|
+
" /gsd ship Create a PR from milestone artifacts [--dry-run|--draft|--base|--force]",
|
|
97
|
+
" /gsd do <text> Route freeform text to the right GSD command",
|
|
98
|
+
" /gsd session-report Show session cost, tokens, and work summary [--json|--save]",
|
|
99
|
+
" /gsd backlog Manage backlog items [add|promote|remove|list]",
|
|
100
|
+
" /gsd pr-branch Create a clean PR branch filtering .gsd/ commits [--dry-run|--name]",
|
|
101
|
+
" /gsd add-tests Generate tests for completed slices",
|
|
102
|
+
" /gsd scan Rapid codebase assessment [--focus tech|arch|quality|concerns|tech+arch]",
|
|
103
|
+
"",
|
|
87
104
|
"SETUP & CONFIGURATION",
|
|
88
105
|
" /gsd onboarding Re-run setup wizard [--resume|--reset|--step <name>]",
|
|
89
106
|
" /gsd setup Configuration hub [llm|model|search|remote|keys|prefs|onboarding]",
|
|
@@ -96,18 +113,23 @@ export function showHelp(ctx, args = "") {
|
|
|
96
113
|
" /gsd config (deprecated) Set tool API keys — use /gsd keys instead",
|
|
97
114
|
" /gsd show-config Show effective configuration (models, routing, toggles)",
|
|
98
115
|
" /gsd hooks Show post-unit hook configuration",
|
|
116
|
+
" /gsd run-hook Manually trigger a specific hook",
|
|
117
|
+
" /gsd skill-health Skill lifecycle dashboard",
|
|
99
118
|
" /gsd extensions Manage extensions [list|enable|disable|info]",
|
|
100
119
|
" /gsd fast Toggle OpenAI service tier [on|off|flex|status]",
|
|
101
120
|
" /gsd mcp MCP server status and connectivity [status|check <server>|init [dir]]",
|
|
102
121
|
"",
|
|
103
122
|
"MAINTENANCE",
|
|
104
123
|
" /gsd doctor Diagnose and repair .gsd/ state [audit|fix|heal] [scope]",
|
|
124
|
+
" /gsd forensics Examine execution logs and post-mortem analysis",
|
|
105
125
|
" /gsd export Export milestone/slice results [--json|--markdown|--html] [--all]",
|
|
106
126
|
" /gsd cleanup Remove merged branches or snapshots [branches|snapshots]",
|
|
127
|
+
" /gsd worktree Manage worktrees from the TUI [list|merge|clean|remove]",
|
|
107
128
|
" /gsd migrate Migrate .planning/ (v1) to .gsd/ (v2) format",
|
|
108
129
|
" /gsd remote Control remote auto-mode [slack|discord|status|disconnect]",
|
|
109
130
|
" /gsd inspect Show SQLite DB diagnostics (schema, row counts, recent entries)",
|
|
110
131
|
" /gsd update Update GSD to the latest version via npm",
|
|
132
|
+
" /gsd language Set or clear the global response language [off|clear|<language>]",
|
|
111
133
|
];
|
|
112
134
|
const full = ["full", "--full", "all"].includes(args.trim().toLowerCase());
|
|
113
135
|
ctx.ui.notify((full ? fullLines : summaryLines).join("\n"), "info");
|
|
@@ -259,5 +259,13 @@ Examples:
|
|
|
259
259
|
await handleScan(trimmed.replace(/^scan\s*/, "").trim(), ctx, pi);
|
|
260
260
|
return true;
|
|
261
261
|
}
|
|
262
|
+
if (trimmed === "worktree" ||
|
|
263
|
+
trimmed.startsWith("worktree ") ||
|
|
264
|
+
trimmed === "wt" ||
|
|
265
|
+
trimmed.startsWith("wt ")) {
|
|
266
|
+
const { handleWorktree } = await import("../../commands-worktree.js");
|
|
267
|
+
await handleWorktree(trimmed.replace(/^(worktree|wt)\s*/, "").trim(), ctx);
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
262
270
|
return false;
|
|
263
271
|
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { AuthStorage } from "@gsd/pi-coding-agent";
|
|
7
7
|
import { existsSync, mkdirSync } from "node:fs";
|
|
8
8
|
import { join, dirname } from "node:path";
|
|
9
|
+
import { getHomeDir } from "./home-dir.js";
|
|
9
10
|
/**
|
|
10
11
|
* Tool API key configurations.
|
|
11
12
|
* This is the source of truth for tool credentials - used by both the config wizard
|
|
@@ -29,7 +30,7 @@ function getStoredToolKey(auth, providerId) {
|
|
|
29
30
|
*/
|
|
30
31
|
export function loadToolApiKeys() {
|
|
31
32
|
try {
|
|
32
|
-
const authPath = join(
|
|
33
|
+
const authPath = join(getHomeDir(), ".gsd", "agent", "auth.json");
|
|
33
34
|
if (!existsSync(authPath))
|
|
34
35
|
return;
|
|
35
36
|
const auth = AuthStorage.create(authPath);
|
|
@@ -45,7 +46,7 @@ export function loadToolApiKeys() {
|
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
export function getConfigAuthStorage() {
|
|
48
|
-
const authPath = join(
|
|
49
|
+
const authPath = join(getHomeDir(), ".gsd", "agent", "auth.json");
|
|
49
50
|
mkdirSync(dirname(authPath), { recursive: true });
|
|
50
51
|
return AuthStorage.create(authPath);
|
|
51
52
|
}
|
|
@@ -10,7 +10,50 @@ import { dirname, join, resolve } from "node:path";
|
|
|
10
10
|
import { homedir, tmpdir } from "node:os";
|
|
11
11
|
import { execFileSync } from "node:child_process";
|
|
12
12
|
import { lockSync, unlockSync } from "proper-lockfile";
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Strict numeric comparison of two npm-style version strings.
|
|
15
|
+
*
|
|
16
|
+
* Returns true when `a` is strictly greater than `b`. Compares the dotted
|
|
17
|
+
* release components numerically (so `1.10.0` > `1.9.0`) and treats any
|
|
18
|
+
* prerelease suffix (`-beta.1`, `-rc.2`) as less than the equivalent
|
|
19
|
+
* release version (`1.0.0` > `1.0.0-beta.1`). Sufficient for npm package
|
|
20
|
+
* version comparison in the extension installer; we don't need the full
|
|
21
|
+
* semver range/intersect machinery here.
|
|
22
|
+
*
|
|
23
|
+
* Replaces the earlier `import semver from "semver"` — that import broke
|
|
24
|
+
* `tsc -p tsconfig.json` whenever `@types/semver` failed to install
|
|
25
|
+
* (Issue #4946) because the file is pulled in transitively despite being
|
|
26
|
+
* under the `src/resources` exclude.
|
|
27
|
+
*/
|
|
28
|
+
export function isVersionGreater(a, b) {
|
|
29
|
+
const split = (v) => {
|
|
30
|
+
const dash = v.indexOf("-");
|
|
31
|
+
const release = (dash === -1 ? v : v.slice(0, dash))
|
|
32
|
+
.split(".")
|
|
33
|
+
.map(part => Number.parseInt(part, 10) || 0);
|
|
34
|
+
const pre = dash === -1 ? null : v.slice(dash + 1);
|
|
35
|
+
return { release, pre };
|
|
36
|
+
};
|
|
37
|
+
const sa = split(a);
|
|
38
|
+
const sb = split(b);
|
|
39
|
+
const len = Math.max(sa.release.length, sb.release.length);
|
|
40
|
+
for (let i = 0; i < len; i++) {
|
|
41
|
+
const ai = sa.release[i] ?? 0;
|
|
42
|
+
const bi = sb.release[i] ?? 0;
|
|
43
|
+
if (ai !== bi)
|
|
44
|
+
return ai > bi;
|
|
45
|
+
}
|
|
46
|
+
// Release components equal — a release version beats any prerelease,
|
|
47
|
+
// and prerelease strings are compared lexicographically (good enough
|
|
48
|
+
// for `beta.1` vs `beta.2`, the only realistic case here).
|
|
49
|
+
if (sa.pre === null && sb.pre !== null)
|
|
50
|
+
return true;
|
|
51
|
+
if (sa.pre !== null && sb.pre === null)
|
|
52
|
+
return false;
|
|
53
|
+
if (sa.pre !== null && sb.pre !== null)
|
|
54
|
+
return sa.pre > sb.pre;
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
14
57
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
15
58
|
// ─── Registry I/O ───────────────────────────────────────────────────────────
|
|
16
59
|
function getRegistryPath() {
|
|
@@ -413,7 +456,7 @@ async function updateSingleExtension(id, registry, ctx) {
|
|
|
413
456
|
ctx.ui.notify(`Could not fetch latest version for "${id}".`, "warning");
|
|
414
457
|
return;
|
|
415
458
|
}
|
|
416
|
-
if (
|
|
459
|
+
if (isVersionGreater(latest, current)) {
|
|
417
460
|
ctx.ui.notify(`Updating "${id}": v${current} → v${latest}...`, "info");
|
|
418
461
|
await handleInstall(packageName, ctx);
|
|
419
462
|
}
|
|
@@ -464,7 +507,7 @@ async function updateAllExtensions(registry, ctx) {
|
|
|
464
507
|
skipped++;
|
|
465
508
|
continue;
|
|
466
509
|
}
|
|
467
|
-
if (
|
|
510
|
+
if (isVersionGreater(latest, current)) {
|
|
468
511
|
ctx.ui.notify(` ${entry.id}: v${current} → v${latest} (updating)`, "info");
|
|
469
512
|
await handleInstall(packageName, ctx);
|
|
470
513
|
updated++;
|
|
@@ -9,6 +9,7 @@ import { join, resolve as resolvePath, sep } from "node:path";
|
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { deriveState } from "./state.js";
|
|
11
11
|
import { gsdRoot } from "./paths.js";
|
|
12
|
+
import { getHomeDir } from "./home-dir.js";
|
|
12
13
|
import { appendCapture, hasPendingCaptures, loadPendingCaptures } from "./captures.js";
|
|
13
14
|
import { appendOverride, appendKnowledge } from "./files.js";
|
|
14
15
|
import { formatDoctorIssuesForPrompt, formatDoctorReport, formatDoctorReportJson, runGSDDoctor, selectDoctorScope, filterDoctorIssues, } from "./doctor.js";
|
|
@@ -60,7 +61,7 @@ async function fetchLatestVersionForCommand() {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
export function dispatchDoctorHeal(pi, scope, reportText, structuredIssues) {
|
|
63
|
-
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(
|
|
64
|
+
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(getHomeDir(), ".gsd", "agent", "GSD-WORKFLOW.md");
|
|
64
65
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
65
66
|
const prompt = loadPrompt("doctor-heal", {
|
|
66
67
|
doctorSummary: reportText,
|
|
@@ -210,7 +211,7 @@ export async function handleTriage(ctx, pi, basePath) {
|
|
|
210
211
|
currentPlan: currentPlan || "(no active slice plan)",
|
|
211
212
|
roadmapContext: roadmapContext || "(no active roadmap)",
|
|
212
213
|
});
|
|
213
|
-
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(
|
|
214
|
+
const workflowPath = process.env.GSD_WORKFLOW_PATH ?? join(getHomeDir(), ".gsd", "agent", "GSD-WORKFLOW.md");
|
|
214
215
|
const workflow = readFileSync(workflowPath, "utf-8");
|
|
215
216
|
pi.sendMessage({
|
|
216
217
|
customType: "gsd-triage",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* /gsd mcp init [dir] — Write project-local GSD workflow MCP config
|
|
11
11
|
*/
|
|
12
12
|
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { homedir } from "node:os";
|
|
13
14
|
import { join, resolve } from "node:path";
|
|
14
15
|
import { ensureProjectWorkflowMcpConfig } from "./mcp-project-config.js";
|
|
15
16
|
export function formatMcpInitResult(status, configPath, targetPath) {
|
|
@@ -33,6 +34,7 @@ function readMcpConfigs() {
|
|
|
33
34
|
const configPaths = [
|
|
34
35
|
join(process.cwd(), ".mcp.json"),
|
|
35
36
|
join(process.cwd(), ".gsd", "mcp.json"),
|
|
37
|
+
join(process.env.GSD_HOME || join(homedir(), ".gsd"), "mcp.json"),
|
|
36
38
|
];
|
|
37
39
|
for (const configPath of configPaths) {
|
|
38
40
|
try {
|
|
@@ -77,7 +79,7 @@ export function formatMcpStatusReport(servers) {
|
|
|
77
79
|
return [
|
|
78
80
|
"No MCP servers configured.",
|
|
79
81
|
"",
|
|
80
|
-
"Add servers to .mcp.json or .gsd/mcp.json to enable MCP integrations.",
|
|
82
|
+
"Add servers to .mcp.json, .gsd/mcp.json, or $GSD_HOME/mcp.json (default: ~/.gsd/mcp.json) to enable MCP integrations.",
|
|
81
83
|
"Tip: run /gsd mcp init . to write the local GSD workflow MCP config.",
|
|
82
84
|
"See: https://modelcontextprotocol.io/quickstart",
|
|
83
85
|
].join("\n");
|
|
@@ -1481,6 +1481,13 @@ async function configureAdvanced(ctx, prefs) {
|
|
|
1481
1481
|
const tokenCost = await promptBoolean(ctx, "Show token cost in footer", prefs.show_token_cost, false);
|
|
1482
1482
|
if (tokenCost !== undefined)
|
|
1483
1483
|
prefs.show_token_cost = tokenCost;
|
|
1484
|
+
const minRequestInterval = await promptInteger(ctx, "Minimum interval between auto-mode LLM requests (ms, 0 to disable)", prefs.min_request_interval_ms, "0");
|
|
1485
|
+
if (minRequestInterval === "clear") {
|
|
1486
|
+
delete prefs.min_request_interval_ms;
|
|
1487
|
+
}
|
|
1488
|
+
else if (minRequestInterval !== undefined) {
|
|
1489
|
+
prefs.min_request_interval_ms = minRequestInterval;
|
|
1490
|
+
}
|
|
1484
1491
|
const widget = await promptEnum(ctx, "Auto-mode widget display", prefs.widget_mode, ["full", "small", "min", "off"], "full");
|
|
1485
1492
|
if (widget !== undefined)
|
|
1486
1493
|
prefs.widget_mode = widget;
|
|
@@ -1668,8 +1675,10 @@ export function serializePreferencesToFrontmatter(prefs) {
|
|
|
1668
1675
|
"budget_ceiling", "budget_enforcement", "context_pause_threshold",
|
|
1669
1676
|
"notifications", "cmux", "remote_questions", "git",
|
|
1670
1677
|
"stale_commit_threshold_minutes",
|
|
1678
|
+
"min_request_interval_ms",
|
|
1671
1679
|
"post_unit_hooks", "pre_dispatch_hooks",
|
|
1672
|
-
"dynamic_routing", "
|
|
1680
|
+
"dynamic_routing", "disabled_model_providers", "uok", "token_profile",
|
|
1681
|
+
"service_tier", "flat_rate_providers",
|
|
1673
1682
|
"phases", "parallel", "slice_parallel",
|
|
1674
1683
|
"reactive_execution", "gate_evaluation",
|
|
1675
1684
|
"auto_visualize", "auto_report",
|