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
|
@@ -22,6 +22,29 @@ let sessionSwitchGeneration = 0;
|
|
|
22
22
|
*/
|
|
23
23
|
export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
24
24
|
debugLog("runUnit", { phase: "start", unitType, unitId });
|
|
25
|
+
// Ensure cwd matches basePath BEFORE newSession() captures it. The new
|
|
26
|
+
// session reads process.cwd() during construction to anchor its tool
|
|
27
|
+
// runtime and system prompt; if cwd has drifted (async_bash, background
|
|
28
|
+
// jobs, prior unit cleanup), the session would otherwise be rooted to
|
|
29
|
+
// the wrong directory. Must be synchronous — no awaits between chdir
|
|
30
|
+
// and newSession (#1389, #4762 follow-up).
|
|
31
|
+
try {
|
|
32
|
+
if (process.cwd() !== s.basePath) {
|
|
33
|
+
process.chdir(s.basePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
const msg = `Failed to chdir to basePath before newSession (basePath: ${s.basePath}): ${String(e)}`;
|
|
38
|
+
logWarning("engine", msg, { basePath: s.basePath, error: String(e) });
|
|
39
|
+
return {
|
|
40
|
+
status: "cancelled",
|
|
41
|
+
errorContext: {
|
|
42
|
+
message: msg,
|
|
43
|
+
category: "session-failed",
|
|
44
|
+
isTransient: true,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
25
48
|
// ── Session creation with timeout ──
|
|
26
49
|
debugLog("runUnit", { phase: "session-create", unitType, unitId });
|
|
27
50
|
let sessionResult;
|
|
@@ -91,17 +114,6 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
91
114
|
const unitPromise = new Promise((resolve) => {
|
|
92
115
|
_setCurrentResolve(resolve);
|
|
93
116
|
});
|
|
94
|
-
// Ensure cwd matches basePath before dispatch (#1389).
|
|
95
|
-
// async_bash and background jobs can drift cwd away from the worktree.
|
|
96
|
-
// Realigning here prevents commits from landing on the wrong branch.
|
|
97
|
-
try {
|
|
98
|
-
if (process.cwd() !== s.basePath) {
|
|
99
|
-
process.chdir(s.basePath);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch (e) {
|
|
103
|
-
logWarning("engine", "Failed to chdir to basePath before dispatch", { basePath: s.basePath, error: String(e) });
|
|
104
|
-
}
|
|
105
117
|
// ── Provider request-readiness pre-check (#4555) ──
|
|
106
118
|
// Verify the provider can accept requests before dispatching. If the token
|
|
107
119
|
// has expired since bootstrap, return cancelled immediately so the unit is
|
|
@@ -138,6 +150,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
138
150
|
const capturedTurnGen = getCurrentTurnGeneration();
|
|
139
151
|
// ── Send the prompt ──
|
|
140
152
|
debugLog("runUnit", { phase: "send-message", unitType, unitId });
|
|
153
|
+
const requestDispatchedAt = Date.now();
|
|
141
154
|
pi.sendMessage({ customType: "gsd-auto", content: prompt, display: s.verbose }, { triggerTurn: true });
|
|
142
155
|
// ── Await agent_end with absolute timeout (H4 fix) ──
|
|
143
156
|
// If supervision fails to resolve unitPromise within 30s, treat as cancelled.
|
|
@@ -160,6 +173,7 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
160
173
|
unitId,
|
|
161
174
|
status: result.status,
|
|
162
175
|
});
|
|
176
|
+
const finalResult = { ...result, requestDispatchedAt };
|
|
163
177
|
// Discard trailing follow-up messages (e.g. async_job_result notifications)
|
|
164
178
|
// from the completed unit. Without this, queued follow-ups trigger wasteful
|
|
165
179
|
// LLM turns before the next session can start (#1642).
|
|
@@ -174,5 +188,5 @@ export async function runUnit(ctx, pi, s, unitType, unitId, prompt) {
|
|
|
174
188
|
catch (e) {
|
|
175
189
|
logWarning("engine", "clearQueue failed after unit completion", { error: String(e) });
|
|
176
190
|
}
|
|
177
|
-
return
|
|
191
|
+
return finalResult;
|
|
178
192
|
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* auto-session-encapsulation.test.ts enforce that auto.ts has no module-level
|
|
16
16
|
* `let` or `var` declarations.
|
|
17
17
|
*/
|
|
18
|
+
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
18
19
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
19
20
|
export const STUB_RECOVERY_THRESHOLD = 2;
|
|
20
21
|
export const NEW_SESSION_TIMEOUT_MS = 120_000;
|
|
@@ -118,6 +119,8 @@ export class AutoSession {
|
|
|
118
119
|
lastPromptCharCount;
|
|
119
120
|
lastBaselineCharCount;
|
|
120
121
|
pendingQuickTasks = [];
|
|
122
|
+
/** Timestamp of the last LLM request dispatch (ms since epoch). Used for proactive rate limiting. */
|
|
123
|
+
lastRequestTimestamp = 0;
|
|
121
124
|
// ── Safety harness ───────────────────────────────────────────────────────
|
|
122
125
|
/** SHA of the pre-unit git checkpoint ref. Cleared on success or rollback. */
|
|
123
126
|
checkpointSha = null;
|
|
@@ -153,12 +156,7 @@ export class AutoSession {
|
|
|
153
156
|
this.unitLifetimeDispatches.clear();
|
|
154
157
|
}
|
|
155
158
|
get lockBasePath() {
|
|
156
|
-
|
|
157
|
-
// Strip /.gsd/worktrees/ suffix if basePath is itself a worktree path
|
|
158
|
-
// to avoid reading/writing the lock inside the worktree (#3729).
|
|
159
|
-
const resolved = this.originalBasePath || this.basePath;
|
|
160
|
-
const markerIdx = resolved.indexOf("/.gsd/worktrees/");
|
|
161
|
-
return markerIdx !== -1 ? resolved.slice(0, markerIdx) : resolved;
|
|
159
|
+
return resolveWorktreeProjectRoot(this.basePath, this.originalBasePath);
|
|
162
160
|
}
|
|
163
161
|
reset() {
|
|
164
162
|
this.clearTimers();
|
|
@@ -215,6 +213,7 @@ export class AutoSession {
|
|
|
215
213
|
this.lastPromptCharCount = undefined;
|
|
216
214
|
this.lastBaselineCharCount = undefined;
|
|
217
215
|
this.pendingQuickTasks = [];
|
|
216
|
+
this.lastRequestTimestamp = 0;
|
|
218
217
|
this.sidecarQueue = [];
|
|
219
218
|
this.rewriteAttemptCount = 0;
|
|
220
219
|
this.consecutiveCompleteBootstraps = 0;
|
|
@@ -10,6 +10,7 @@ import { getActiveHook } from "./post-unit-hooks.js";
|
|
|
10
10
|
import { getLedger, getProjectTotals } from "./metrics.js";
|
|
11
11
|
import { getErrorMessage } from "./error-utils.js";
|
|
12
12
|
import { nativeIsRepo } from "./native-git-bridge.js";
|
|
13
|
+
import { getHomeDir } from "./home-dir.js";
|
|
13
14
|
import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
14
15
|
import { readFileSync, writeFileSync, existsSync } from "node:fs";
|
|
15
16
|
import { execFileSync } from "node:child_process";
|
|
@@ -461,8 +462,8 @@ export function updateProgressWidget(ctx, unitType, unitId, state, accessors, ti
|
|
|
461
462
|
let widgetPwd;
|
|
462
463
|
{
|
|
463
464
|
let fullPwd = process.cwd();
|
|
464
|
-
const widgetHome =
|
|
465
|
-
if (widgetHome && fullPwd.startsWith(widgetHome)) {
|
|
465
|
+
const widgetHome = getHomeDir();
|
|
466
|
+
if (widgetHome && (fullPwd === widgetHome || fullPwd.startsWith(widgetHome + "/") || fullPwd.startsWith(widgetHome + "\\"))) {
|
|
466
467
|
fullPwd = `~${fullPwd.slice(widgetHome.length)}`;
|
|
467
468
|
}
|
|
468
469
|
const parts = fullPwd.split("/");
|
|
@@ -10,6 +10,8 @@ import { resolveMilestoneFile, resolveSliceFile, relSliceFile, } from "./paths.j
|
|
|
10
10
|
import { buildResearchSlicePrompt, buildResearchMilestonePrompt, buildPlanSlicePrompt, buildPlanMilestonePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildReassessRoadmapPrompt, buildRunUatPrompt, buildReplanSlicePrompt, } from "./auto-prompts.js";
|
|
11
11
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
12
12
|
import { pauseAuto } from "./auto.js";
|
|
13
|
+
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
14
|
+
import { logWarning } from "./workflow-logger.js";
|
|
13
15
|
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, } from "./workflow-mcp.js";
|
|
14
16
|
export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
15
17
|
const state = await deriveState(base);
|
|
@@ -19,6 +21,12 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
19
21
|
ctx.ui.notify("Cannot dispatch: no active milestone.", "warning");
|
|
20
22
|
return;
|
|
21
23
|
}
|
|
24
|
+
const projectRoot = base;
|
|
25
|
+
// Switch the dispatch base to the canonical milestone worktree if one
|
|
26
|
+
// exists. Without this, /gsd dispatch invoked from the project root would
|
|
27
|
+
// build prompts and create a session anchored to the project root even
|
|
28
|
+
// though the milestone's actual code lives in the worktree.
|
|
29
|
+
const dispatchBase = resolveCanonicalMilestoneRoot(base, mid);
|
|
22
30
|
const normalized = phase.toLowerCase();
|
|
23
31
|
let unitType;
|
|
24
32
|
let unitId;
|
|
@@ -37,7 +45,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
37
45
|
}
|
|
38
46
|
// When require_slice_discussion is enabled, pause auto-mode before
|
|
39
47
|
// each new slice so the user can discuss requirements first (#789).
|
|
40
|
-
const sliceContextFile = resolveSliceFile(
|
|
48
|
+
const sliceContextFile = resolveSliceFile(dispatchBase, mid, sid, "CONTEXT");
|
|
41
49
|
const requireDiscussion = loadEffectiveGSDPreferences()?.preferences?.phases?.require_slice_discussion;
|
|
42
50
|
if (requireDiscussion && !sliceContextFile) {
|
|
43
51
|
ctx.ui.notify(`Slice ${sid} requires discussion before planning. Run /gsd discuss to discuss this slice, then /gsd auto to resume.`, "info");
|
|
@@ -46,12 +54,12 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
46
54
|
}
|
|
47
55
|
unitType = "research-slice";
|
|
48
56
|
unitId = `${mid}/${sid}`;
|
|
49
|
-
prompt = await buildResearchSlicePrompt(mid, midTitle, sid, sTitle,
|
|
57
|
+
prompt = await buildResearchSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
50
58
|
}
|
|
51
59
|
else {
|
|
52
60
|
unitType = "research-milestone";
|
|
53
61
|
unitId = mid;
|
|
54
|
-
prompt = await buildResearchMilestonePrompt(mid, midTitle,
|
|
62
|
+
prompt = await buildResearchMilestonePrompt(mid, midTitle, dispatchBase);
|
|
55
63
|
}
|
|
56
64
|
break;
|
|
57
65
|
}
|
|
@@ -68,7 +76,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
68
76
|
}
|
|
69
77
|
unitType = "plan-slice";
|
|
70
78
|
unitId = `${mid}/${sid}`;
|
|
71
|
-
prompt = await buildPlanSlicePrompt(mid, midTitle, sid, sTitle,
|
|
79
|
+
prompt = await buildPlanSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase, undefined, {
|
|
72
80
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
73
81
|
modelRegistry: ctx.modelRegistry,
|
|
74
82
|
});
|
|
@@ -76,7 +84,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
76
84
|
else {
|
|
77
85
|
unitType = "plan-milestone";
|
|
78
86
|
unitId = mid;
|
|
79
|
-
prompt = await buildPlanMilestonePrompt(mid, midTitle,
|
|
87
|
+
prompt = await buildPlanMilestonePrompt(mid, midTitle, dispatchBase);
|
|
80
88
|
}
|
|
81
89
|
break;
|
|
82
90
|
}
|
|
@@ -96,7 +104,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
96
104
|
}
|
|
97
105
|
unitType = "execute-task";
|
|
98
106
|
unitId = `${mid}/${sid}/${tid}`;
|
|
99
|
-
prompt = await buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle,
|
|
107
|
+
prompt = await buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, dispatchBase, {
|
|
100
108
|
sessionContextWindow: ctx.model?.contextWindow,
|
|
101
109
|
modelRegistry: ctx.modelRegistry,
|
|
102
110
|
});
|
|
@@ -115,12 +123,12 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
115
123
|
}
|
|
116
124
|
unitType = "complete-slice";
|
|
117
125
|
unitId = `${mid}/${sid}`;
|
|
118
|
-
prompt = await buildCompleteSlicePrompt(mid, midTitle, sid, sTitle,
|
|
126
|
+
prompt = await buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
119
127
|
}
|
|
120
128
|
else {
|
|
121
129
|
unitType = "complete-milestone";
|
|
122
130
|
unitId = mid;
|
|
123
|
-
prompt = await buildCompleteMilestonePrompt(mid, midTitle,
|
|
131
|
+
prompt = await buildCompleteMilestonePrompt(mid, midTitle, dispatchBase);
|
|
124
132
|
}
|
|
125
133
|
break;
|
|
126
134
|
}
|
|
@@ -133,7 +141,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
133
141
|
}
|
|
134
142
|
if (completedSliceIds.length === 0) {
|
|
135
143
|
// File-based fallback: parse roadmap checkboxes
|
|
136
|
-
const roadmapPath = resolveMilestoneFile(
|
|
144
|
+
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
137
145
|
if (roadmapPath) {
|
|
138
146
|
const roadmapContent = await loadFile(roadmapPath);
|
|
139
147
|
if (roadmapContent) {
|
|
@@ -148,7 +156,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
148
156
|
const completedSliceId = completedSliceIds[completedSliceIds.length - 1];
|
|
149
157
|
unitType = "reassess-roadmap";
|
|
150
158
|
unitId = `${mid}/${completedSliceId}`;
|
|
151
|
-
prompt = await buildReassessRoadmapPrompt(mid, midTitle, completedSliceId,
|
|
159
|
+
prompt = await buildReassessRoadmapPrompt(mid, midTitle, completedSliceId, dispatchBase);
|
|
152
160
|
break;
|
|
153
161
|
}
|
|
154
162
|
case "uat":
|
|
@@ -163,7 +171,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
163
171
|
}
|
|
164
172
|
if (uatCompletedSliceIds.length === 0) {
|
|
165
173
|
// File-based fallback: parse roadmap checkboxes
|
|
166
|
-
const roadmapPath = resolveMilestoneFile(
|
|
174
|
+
const roadmapPath = resolveMilestoneFile(dispatchBase, mid, "ROADMAP");
|
|
167
175
|
if (roadmapPath) {
|
|
168
176
|
const roadmapContent = await loadFile(roadmapPath);
|
|
169
177
|
if (roadmapContent) {
|
|
@@ -176,7 +184,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
176
184
|
return;
|
|
177
185
|
}
|
|
178
186
|
const sid = uatCompletedSliceIds[uatCompletedSliceIds.length - 1];
|
|
179
|
-
const uatFile = resolveSliceFile(
|
|
187
|
+
const uatFile = resolveSliceFile(dispatchBase, mid, sid, "UAT");
|
|
180
188
|
if (!uatFile) {
|
|
181
189
|
ctx.ui.notify("Cannot dispatch run-uat: no UAT file found.", "warning");
|
|
182
190
|
return;
|
|
@@ -186,10 +194,10 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
186
194
|
ctx.ui.notify("Cannot dispatch run-uat: UAT file is empty.", "warning");
|
|
187
195
|
return;
|
|
188
196
|
}
|
|
189
|
-
const uatPath = relSliceFile(
|
|
197
|
+
const uatPath = relSliceFile(dispatchBase, mid, sid, "UAT");
|
|
190
198
|
unitType = "run-uat";
|
|
191
199
|
unitId = `${mid}/${sid}`;
|
|
192
|
-
prompt = await buildRunUatPrompt(mid, sid, uatPath, uatContent,
|
|
200
|
+
prompt = await buildRunUatPrompt(mid, sid, uatPath, uatContent, dispatchBase);
|
|
193
201
|
break;
|
|
194
202
|
}
|
|
195
203
|
case "replan":
|
|
@@ -202,7 +210,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
202
210
|
}
|
|
203
211
|
unitType = "replan-slice";
|
|
204
212
|
unitId = `${mid}/${sid}`;
|
|
205
|
-
prompt = await buildReplanSlicePrompt(mid, midTitle, sid, sTitle,
|
|
213
|
+
prompt = await buildReplanSlicePrompt(mid, midTitle, sid, sTitle, dispatchBase);
|
|
206
214
|
break;
|
|
207
215
|
}
|
|
208
216
|
default:
|
|
@@ -210,7 +218,7 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
210
218
|
return;
|
|
211
219
|
}
|
|
212
220
|
const compatibilityError = getWorkflowTransportSupportError(ctx.model?.provider, getRequiredWorkflowToolsForAutoUnit(unitType), {
|
|
213
|
-
projectRoot
|
|
221
|
+
projectRoot,
|
|
214
222
|
surface: "direct phase dispatch",
|
|
215
223
|
unitType,
|
|
216
224
|
authMode: ctx.model?.provider ? ctx.modelRegistry.getProviderAuthMode(ctx.model.provider) : undefined,
|
|
@@ -221,10 +229,36 @@ export async function dispatchDirectPhase(ctx, pi, phase, base) {
|
|
|
221
229
|
return;
|
|
222
230
|
}
|
|
223
231
|
ctx.ui.notify(`Dispatching ${unitType} for ${unitId}...`, "info");
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
const originalCwd = process.cwd();
|
|
233
|
+
try {
|
|
234
|
+
// Ensure cwd matches dispatchBase BEFORE newSession() captures it. Synchronous —
|
|
235
|
+
// no awaits between chdir and newSession.
|
|
236
|
+
try {
|
|
237
|
+
if (process.cwd() !== dispatchBase) {
|
|
238
|
+
process.chdir(dispatchBase);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
const msg = `Failed to chdir before direct-dispatch newSession (basePath: ${dispatchBase}): ${err instanceof Error ? err.message : String(err)}`;
|
|
243
|
+
logWarning("engine", msg, { file: "auto-direct-dispatch.ts", basePath: dispatchBase, error: err instanceof Error ? err.message : String(err) });
|
|
244
|
+
ctx.ui.notify(`${msg}. Cancelling dispatch to avoid running in the wrong directory.`, "error");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const result = await ctx.newSession();
|
|
248
|
+
if (result.cancelled) {
|
|
249
|
+
ctx.ui.notify("Session creation cancelled.", "warning");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
pi.sendMessage({ customType: "gsd-dispatch", content: prompt, display: false }, { triggerTurn: true });
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
try {
|
|
256
|
+
if (process.cwd() !== originalCwd) {
|
|
257
|
+
process.chdir(originalCwd);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
logWarning("engine", `Failed to restore cwd after direct dispatch: ${err instanceof Error ? err.message : String(err)}`, { file: "auto-direct-dispatch.ts", basePath: originalCwd });
|
|
262
|
+
}
|
|
228
263
|
}
|
|
229
|
-
pi.sendMessage({ customType: "gsd-dispatch", content: prompt, display: false }, { triggerTurn: true });
|
|
230
264
|
}
|
|
@@ -655,14 +655,25 @@ export const DISPATCH_RULES = [
|
|
|
655
655
|
return null;
|
|
656
656
|
if (!state.activeSlice)
|
|
657
657
|
return null; // fall through
|
|
658
|
-
//
|
|
658
|
+
// Reactive dispatch is on by default when there are enough ready tasks to
|
|
659
|
+
// benefit from parallelism. Users opt out explicitly via
|
|
660
|
+
// `reactive_execution.enabled: false`. The downstream safety checks
|
|
661
|
+
// (graph ambiguity, ready-task count, conflict-free selection) still gate
|
|
662
|
+
// every actual dispatch, so the worst-case "default-on" outcome is the
|
|
663
|
+
// same fall-through to sequential execution as before.
|
|
659
664
|
const reactiveConfig = prefs?.reactive_execution;
|
|
660
|
-
if (
|
|
665
|
+
if (reactiveConfig?.enabled === false)
|
|
661
666
|
return null;
|
|
662
667
|
const sid = state.activeSlice.id;
|
|
663
668
|
const sTitle = state.activeSlice.title;
|
|
664
|
-
const maxParallel = reactiveConfig
|
|
665
|
-
const subagentModel = reactiveConfig
|
|
669
|
+
const maxParallel = reactiveConfig?.max_parallel ?? 2;
|
|
670
|
+
const subagentModel = reactiveConfig?.subagent_model ?? resolveModelWithFallbacksForUnit("subagent")?.primary;
|
|
671
|
+
// Default-on safety threshold: only activate reactive dispatch when at
|
|
672
|
+
// least N tasks are ready. Users who explicitly enabled reactive_execution
|
|
673
|
+
// keep the legacy threshold of 2 (matches the prior "any parallelism is
|
|
674
|
+
// better than none" intent). Default-on installs require >=3 to avoid
|
|
675
|
+
// surprising users with parallelism on small slices.
|
|
676
|
+
const minReadyTasksForReactive = reactiveConfig?.enabled === true ? 2 : 3;
|
|
666
677
|
// Dry-run mode: max_parallel=1 means graph is derived and logged but
|
|
667
678
|
// execution remains sequential
|
|
668
679
|
if (maxParallel <= 1)
|
|
@@ -678,8 +689,9 @@ export const DISPATCH_RULES = [
|
|
|
678
689
|
return null;
|
|
679
690
|
const completed = new Set(graph.filter((n) => n.done).map((n) => n.id));
|
|
680
691
|
const readyIds = getReadyTasks(graph, completed, new Set());
|
|
681
|
-
// Only activate reactive dispatch when
|
|
682
|
-
|
|
692
|
+
// Only activate reactive dispatch when enough tasks are ready.
|
|
693
|
+
// Threshold is 2 when explicitly opted in, 3 when default-on.
|
|
694
|
+
if (readyIds.length < minReadyTasksForReactive)
|
|
683
695
|
return null;
|
|
684
696
|
const uokFlags = resolveUokFlags(prefs);
|
|
685
697
|
const selected = uokFlags.executionGraph
|
|
@@ -23,7 +23,7 @@ import { composeInlinedContext } from "./unit-context-composer.js";
|
|
|
23
23
|
import { logWarning } from "./workflow-logger.js";
|
|
24
24
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
25
25
|
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
26
|
-
import { warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
26
|
+
import { resolveSkillManifest, warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
27
27
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
28
28
|
/**
|
|
29
29
|
* Historical static ceiling for the preamble cap. Kept as an upper bound even
|
|
@@ -675,6 +675,26 @@ function formatSkillActivationBlock(skillNames) {
|
|
|
675
675
|
const calls = safe.map(name => `Call Skill({ skill: '${name}' })`).join('. ');
|
|
676
676
|
return `<skill_activation>${calls}.</skill_activation>`;
|
|
677
677
|
}
|
|
678
|
+
/**
|
|
679
|
+
* Manifest-driven recommendations block — informational only, does NOT
|
|
680
|
+
* auto-invoke. Lists per-unit-type skills that are installed but not already
|
|
681
|
+
* activated by explicit user intent (always_use_skills / prefer_skills /
|
|
682
|
+
* skill_rules / task-plan skills_used). Surfaces relevant skills to the
|
|
683
|
+
* model so they can be invoked when the model judges them useful.
|
|
684
|
+
*
|
|
685
|
+
* This is the additive complement to the existing activation directive:
|
|
686
|
+
* activation force-invokes (explicit intent), recommendations remind
|
|
687
|
+
* (manifest defaults). User intent is preserved as the stronger signal
|
|
688
|
+
* (RFC #4779 design principle); this block only adds visibility.
|
|
689
|
+
*/
|
|
690
|
+
function formatSkillRecommendationsBlock(unitType, skillNames) {
|
|
691
|
+
if (!unitType)
|
|
692
|
+
return "";
|
|
693
|
+
const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
|
|
694
|
+
if (safe.length === 0)
|
|
695
|
+
return "";
|
|
696
|
+
return `<skill_recommendations unit="${unitType}">For this unit type, also consider invoking: ${safe.join(", ")}. Use Skill({ skill: 'name' }) when relevant — these are recommendations, not requirements.</skill_recommendations>`;
|
|
697
|
+
}
|
|
678
698
|
export function buildSkillActivationBlock(params) {
|
|
679
699
|
const prefs = params.preferences ?? loadEffectiveGSDPreferences(params.base)?.preferences;
|
|
680
700
|
const contextTokens = tokenizeSkillContext(params.milestoneId, params.milestoneTitle, params.sliceId, params.sliceTitle, params.taskId, params.taskTitle);
|
|
@@ -717,10 +737,51 @@ export function buildSkillActivationBlock(params) {
|
|
|
717
737
|
logWarning("prompt", `parseTaskPlanFile failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
718
738
|
}
|
|
719
739
|
}
|
|
740
|
+
// Heuristic auto-match (gated on skill_discovery: "auto").
|
|
741
|
+
// For each installed skill, check if its name or description appears in the
|
|
742
|
+
// unit's context tokens (milestone/slice/task titles). Only consider skills
|
|
743
|
+
// already on the unit-type manifest allowlist — this keeps the heuristic
|
|
744
|
+
// narrow and avoids wildly off-topic activations.
|
|
745
|
+
// Users who set `skill_discovery: "off"` or "suggest" do not get
|
|
746
|
+
// auto-matched skills (the recommendations block still surfaces manifest
|
|
747
|
+
// skills passively); only "auto" actually adds them to the activation
|
|
748
|
+
// directive set. Default `skill_discovery` is "suggest", so this is opt-in.
|
|
749
|
+
if ((prefs?.skill_discovery ?? "suggest") === "auto") {
|
|
750
|
+
const manifestAllow = resolveSkillManifest(params.unitType);
|
|
751
|
+
const allowSet = manifestAllow ? new Set(manifestAllow) : null;
|
|
752
|
+
for (const skill of visibleSkills) {
|
|
753
|
+
const normalized = normalizeSkillReference(skill.name);
|
|
754
|
+
if (matched.has(normalized) || avoided.has(normalized))
|
|
755
|
+
continue;
|
|
756
|
+
// Respect the manifest allowlist when present; wildcard (null) lets all
|
|
757
|
+
// installed skills compete for keyword match.
|
|
758
|
+
if (allowSet && !allowSet.has(normalized))
|
|
759
|
+
continue;
|
|
760
|
+
if (skillMatchesContext(skill, contextTokens)) {
|
|
761
|
+
matched.add(normalized);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
720
765
|
const ordered = [...matched]
|
|
721
766
|
.filter(name => installedNames.has(name) && !avoided.has(name))
|
|
722
767
|
.sort();
|
|
723
|
-
|
|
768
|
+
const activationBlock = formatSkillActivationBlock(ordered);
|
|
769
|
+
// Manifest-driven recommendations (additive, does not override explicit intent).
|
|
770
|
+
// Only surface skills the manifest declares for this unit type that are
|
|
771
|
+
// installed and not already in matched/avoided.
|
|
772
|
+
const matchedSet = new Set(ordered);
|
|
773
|
+
const manifestList = resolveSkillManifest(params.unitType);
|
|
774
|
+
const recommendations = (manifestList ?? [])
|
|
775
|
+
.filter(name => installedNames.has(name) && !avoided.has(name) && !matchedSet.has(name))
|
|
776
|
+
.sort();
|
|
777
|
+
const recommendationsBlock = formatSkillRecommendationsBlock(params.unitType, recommendations);
|
|
778
|
+
if (!activationBlock && !recommendationsBlock)
|
|
779
|
+
return "";
|
|
780
|
+
if (!activationBlock)
|
|
781
|
+
return recommendationsBlock;
|
|
782
|
+
if (!recommendationsBlock)
|
|
783
|
+
return activationBlock;
|
|
784
|
+
return `${activationBlock}\n${recommendationsBlock}`;
|
|
724
785
|
}
|
|
725
786
|
/**
|
|
726
787
|
* Build the skill discovery template variables for research prompts.
|
|
@@ -1059,6 +1120,7 @@ export async function checkNeedsRunUat(base, mid, state, prefs) {
|
|
|
1059
1120
|
export async function buildDiscussMilestonePrompt(mid, midTitle, base, structuredQuestionsAvailable = "false") {
|
|
1060
1121
|
const discussTemplates = inlineTemplate("context", "Context");
|
|
1061
1122
|
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1123
|
+
workingDirectory: base,
|
|
1062
1124
|
milestoneId: mid,
|
|
1063
1125
|
milestoneTitle: midTitle,
|
|
1064
1126
|
inlinedTemplates: discussTemplates,
|
|
@@ -2262,6 +2324,7 @@ export async function buildParallelResearchSlicesPrompt(mid, midTitle, slices, b
|
|
|
2262
2324
|
].join("\n"));
|
|
2263
2325
|
}
|
|
2264
2326
|
return loadPrompt("parallel-research-slices", {
|
|
2327
|
+
workingDirectory: basePath,
|
|
2265
2328
|
mid,
|
|
2266
2329
|
midTitle,
|
|
2267
2330
|
sliceCount: String(slices.length),
|
|
@@ -2289,11 +2352,14 @@ export async function buildGateEvaluatePrompt(mid, midTitle, sid, sTitle, base,
|
|
|
2289
2352
|
const gateDefs = getGatesForTurn("gate-evaluate").filter((def) => pendingIds.has(def.id));
|
|
2290
2353
|
const subagentSections = [];
|
|
2291
2354
|
const gateListLines = [];
|
|
2355
|
+
const normalizedBase = base.replaceAll("\\", "/");
|
|
2292
2356
|
for (const def of gateDefs) {
|
|
2293
2357
|
gateListLines.push(`- **${def.id}**: ${def.question}`);
|
|
2294
2358
|
const subPrompt = [
|
|
2295
2359
|
`You are evaluating quality gate **${def.id}** for slice ${sid} (${sTitle}).`,
|
|
2296
2360
|
"",
|
|
2361
|
+
`**Working directory:** \`${normalizedBase}\`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT \`cd\` to any other directory.`,
|
|
2362
|
+
"",
|
|
2297
2363
|
`## Question: ${def.question}`,
|
|
2298
2364
|
"",
|
|
2299
2365
|
def.guidance,
|
|
@@ -2401,6 +2467,7 @@ export async function buildRewriteDocsPrompt(mid, midTitle, activeSlice, base, o
|
|
|
2401
2467
|
].join("\n")).join("\n\n");
|
|
2402
2468
|
const documentList = docList.length > 0 ? docList.join("\n") : "- No active plan documents found.";
|
|
2403
2469
|
return loadPrompt("rewrite-docs", {
|
|
2470
|
+
workingDirectory: base,
|
|
2404
2471
|
milestoneId: mid,
|
|
2405
2472
|
milestoneTitle: midTitle,
|
|
2406
2473
|
sliceId: sid ?? "none",
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* globals or AutoContext dependency.
|
|
8
8
|
*/
|
|
9
9
|
import { parseUnitId } from "./unit-id.js";
|
|
10
|
+
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
10
11
|
import { appendEvent } from "./workflow-events.js";
|
|
11
12
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
12
13
|
import { clearParseCache } from "./files.js";
|
|
@@ -168,8 +169,35 @@ function getChangedFilesSinceBranch(basePath, targetBranch) {
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
function getChangedFilesFromMilestoneTaggedCommits(basePath, milestoneId) {
|
|
172
|
+
// Primary: path-scoped log against .gsd/milestones/<id>. Fast and unbounded
|
|
173
|
+
// by depth when .gsd/ is tracked in git.
|
|
174
|
+
const scoped = scanGsdTaggedCommits(basePath, milestoneId, [
|
|
175
|
+
"log", "--format=%H%x1f%B%x1e", "HEAD", "--", `.gsd/milestones/${milestoneId}`,
|
|
176
|
+
]);
|
|
177
|
+
if (!scoped.ok)
|
|
178
|
+
return scoped;
|
|
179
|
+
if (scoped.matched)
|
|
180
|
+
return scoped;
|
|
181
|
+
// Fallback (#5033): when .gsd/ is gitignored / external / untracked, the
|
|
182
|
+
// path-scoped scan matches no commits even though GSD-tagged commits
|
|
183
|
+
// referencing the milestone exist on the integration branch. Re-scan all
|
|
184
|
+
// of HEAD's history and rely on commitMatchesMilestone to bind by
|
|
185
|
+
// explicit milestone mention in the message body.
|
|
186
|
+
//
|
|
187
|
+
// Intentionally unbounded — symmetric with the primary scan, and avoids
|
|
188
|
+
// reintroducing the rolling-depth failure class removed in #4699 where
|
|
189
|
+
// milestone evidence aged out behind unrelated activity.
|
|
190
|
+
return scanGsdTaggedCommits(basePath, milestoneId, [
|
|
191
|
+
"log", "--format=%H%x1f%B%x1e", "HEAD",
|
|
192
|
+
]);
|
|
193
|
+
}
|
|
194
|
+
function scanGsdTaggedCommits(basePath, milestoneId, gitArgs) {
|
|
171
195
|
try {
|
|
172
|
-
const logOutput = execFileSync("git", [
|
|
196
|
+
const logOutput = execFileSync("git", [...gitArgs], {
|
|
197
|
+
cwd: basePath,
|
|
198
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
199
|
+
encoding: "utf-8",
|
|
200
|
+
});
|
|
173
201
|
const records = logOutput
|
|
174
202
|
.split("\x1e")
|
|
175
203
|
.map((record) => record.trim())
|
|
@@ -213,13 +241,24 @@ function commitMatchesMilestone(message, milestoneId, files) {
|
|
|
213
241
|
if (commitTrailerStartsWithMilestone(message, milestoneId))
|
|
214
242
|
return true;
|
|
215
243
|
// Meaningful execute-task commits currently store task scope as Sxx/Tyy
|
|
216
|
-
// rather than Mxx/Sxx/Tyy. Bind those commits back to the milestone
|
|
217
|
-
//
|
|
244
|
+
// rather than Mxx/Sxx/Tyy. Bind those commits back to the milestone when
|
|
245
|
+
// either the commit touched this milestone's artifacts, or — for projects
|
|
246
|
+
// where .gsd/ is gitignored/external (#5033) — the message explicitly
|
|
247
|
+
// names the milestone.
|
|
218
248
|
if (/^GSD-Task:\s*S[^/\s]+\/T\S+/m.test(message)) {
|
|
219
|
-
|
|
249
|
+
if (files.some((file) => isMilestoneArtifactPath(file, milestoneId)))
|
|
250
|
+
return true;
|
|
251
|
+
if (commitMessageMentionsMilestone(message, milestoneId))
|
|
252
|
+
return true;
|
|
220
253
|
}
|
|
221
254
|
return false;
|
|
222
255
|
}
|
|
256
|
+
function commitMessageMentionsMilestone(message, milestoneId) {
|
|
257
|
+
if (!MILESTONE_ID_RE.test(milestoneId))
|
|
258
|
+
return false;
|
|
259
|
+
const escapedMilestone = milestoneId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
260
|
+
return new RegExp(`\\b${escapedMilestone}\\b`).test(message);
|
|
261
|
+
}
|
|
223
262
|
function commitTrailerStartsWithMilestone(message, milestoneId) {
|
|
224
263
|
const escapedMilestone = milestoneId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
225
264
|
const trailerPattern = new RegExp(`^GSD-(?:Task|Unit):\\s*${escapedMilestone}(?:$|[\\s/])`, "m");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// GSD auto-mode runtime state
|
|
2
|
+
import { AutoSession } from "./auto/session.js";
|
|
3
|
+
import { isDeterministicPolicyError, isQueuedUserMessageSkip, isToolInvocationError, markToolEnd as markTrackedToolEnd, markToolStart as markTrackedToolStart, } from "./auto-tool-tracking.js";
|
|
4
|
+
export const autoSession = new AutoSession();
|
|
5
|
+
export function getAutoRuntimeSnapshot() {
|
|
6
|
+
return {
|
|
7
|
+
active: autoSession.active,
|
|
8
|
+
paused: autoSession.paused,
|
|
9
|
+
currentUnit: autoSession.currentUnit ? { ...autoSession.currentUnit } : null,
|
|
10
|
+
basePath: autoSession.basePath,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function isAutoActive() {
|
|
14
|
+
return autoSession.active;
|
|
15
|
+
}
|
|
16
|
+
export function isAutoPaused() {
|
|
17
|
+
return autoSession.paused;
|
|
18
|
+
}
|
|
19
|
+
export function markToolStart(toolCallId, toolName) {
|
|
20
|
+
markTrackedToolStart(toolCallId, autoSession.active, toolName);
|
|
21
|
+
}
|
|
22
|
+
export function markToolEnd(toolCallId) {
|
|
23
|
+
markTrackedToolEnd(toolCallId);
|
|
24
|
+
}
|
|
25
|
+
export function recordToolInvocationError(toolName, errorMsg) {
|
|
26
|
+
if (!autoSession.active)
|
|
27
|
+
return;
|
|
28
|
+
if (isToolInvocationError(errorMsg) || isQueuedUserMessageSkip(errorMsg) || isDeterministicPolicyError(errorMsg)) {
|
|
29
|
+
autoSession.lastToolInvocationError = `${toolName}: ${errorMsg}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -208,7 +208,7 @@ export function auditOrphanedMilestoneBranches(basePath, isolationMode) {
|
|
|
208
208
|
else {
|
|
209
209
|
// Branch is NOT merged — preserve for safety, warn the user
|
|
210
210
|
warnings.push(`Branch ${branch} exists for completed milestone ${milestoneId} but is NOT merged into ${mainBranch}. ` +
|
|
211
|
-
`This may contain unmerged work. Merge manually or run \`/gsd
|
|
211
|
+
`This may contain unmerged work. Merge manually or run \`/gsd doctor fix\` to resolve.`);
|
|
212
212
|
// #4764 telemetry
|
|
213
213
|
try {
|
|
214
214
|
emitWorktreeOrphaned(basePath, milestoneId, {
|
|
@@ -139,6 +139,6 @@ export const DETERMINISTIC_POLICY_ERROR_STRINGS = [
|
|
|
139
139
|
export function isDeterministicPolicyError(errorMsg) {
|
|
140
140
|
if (!errorMsg)
|
|
141
141
|
return false;
|
|
142
|
-
return
|
|
143
|
-
DETERMINISTIC_POLICY_ERROR_STRINGS.some(s => errorMsg.includes(s))
|
|
142
|
+
return DETERMINISTIC_POLICY_ERROR_RE.test(errorMsg)
|
|
143
|
+
|| DETERMINISTIC_POLICY_ERROR_STRINGS.some(s => errorMsg.includes(s));
|
|
144
144
|
}
|