@opengsd/gsd-pi 1.0.2-dev.e70300c → 1.0.2-dev.fb7ddf1
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 +63 -12
- package/dist/headless-answers.js +2 -1
- package/dist/headless-events.d.ts +1 -0
- package/dist/headless-events.js +8 -1
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +44 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +81 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +38 -1
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +34 -1
- package/dist/resources/extensions/gsd/auto.js +40 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +7 -2
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
- package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +3 -20
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repo-identity.js +36 -6
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/extensions/subagent/index.js +8 -15
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/resources/skills/agent-browser/SKILL.md +1 -1
- package/dist/resources/skills/api-design/SKILL.md +1 -1
- package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
- package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/dist/resources/skills/forensics/SKILL.md +2 -2
- package/dist/resources/skills/grill-me/SKILL.md +1 -1
- package/dist/resources/skills/handoff/SKILL.md +1 -1
- package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/dist/resources/skills/observability/SKILL.md +1 -1
- package/dist/resources/skills/security-review/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/dist/resources/skills/tdd/SKILL.md +1 -1
- package/dist/resources/skills/write-docs/SKILL.md +1 -1
- package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.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/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-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/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.test.js +5 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +15 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/dist/workflow.test.js +1 -0
- package/packages/contracts/dist/workflow.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +7 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +47 -8
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +16 -14
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +48 -206
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +67 -220
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -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/tests/tool-search-shim.test.js +29 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
- package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +96 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +47 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +45 -1
- package/src/resources/extensions/gsd/auto.ts +50 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +7 -2
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
- package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +3 -20
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repo-identity.ts +35 -7
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/extensions/subagent/index.ts +8 -15
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/src/resources/skills/agent-browser/SKILL.md +1 -1
- package/src/resources/skills/api-design/SKILL.md +1 -1
- package/src/resources/skills/code-optimizer/SKILL.md +6 -11
- package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/src/resources/skills/forensics/SKILL.md +2 -2
- package/src/resources/skills/grill-me/SKILL.md +1 -1
- package/src/resources/skills/handoff/SKILL.md +1 -1
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/src/resources/skills/observability/SKILL.md +1 -1
- package/src/resources/skills/security-review/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/src/resources/skills/tdd/SKILL.md +1 -1
- package/src/resources/skills/write-docs/SKILL.md +1 -1
- package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
- /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
nativeBranchDelete,
|
|
49
49
|
nativeWorktreeRemove,
|
|
50
50
|
nativeCommitCountBetween,
|
|
51
|
+
nativeHasChanges,
|
|
51
52
|
} from "./native-git-bridge.js";
|
|
52
53
|
import { GitServiceImpl } from "./git-service.js";
|
|
53
54
|
import {
|
|
@@ -242,24 +243,126 @@ export function resolveSurvivorRecoveryIsolationMode(
|
|
|
242
243
|
return isolationMode;
|
|
243
244
|
}
|
|
244
245
|
|
|
246
|
+
export type StrandedWorkRecoveryMode = "worktree" | "branch";
|
|
247
|
+
|
|
248
|
+
export type OrphanAuditActionKind =
|
|
249
|
+
| "in-progress-stranded-work"
|
|
250
|
+
| "complete-merged-branch"
|
|
251
|
+
| "complete-merged-worktree"
|
|
252
|
+
| "complete-unmerged-branch"
|
|
253
|
+
| "complete-branchless-worktree";
|
|
254
|
+
|
|
255
|
+
export interface OrphanAuditAction {
|
|
256
|
+
kind: OrphanAuditActionKind;
|
|
257
|
+
milestoneId: string;
|
|
258
|
+
message: string;
|
|
259
|
+
severity: "info" | "warning";
|
|
260
|
+
branch?: string;
|
|
261
|
+
commitsAhead?: number;
|
|
262
|
+
dirtyWorktree?: boolean;
|
|
263
|
+
worktreeDirExists?: boolean;
|
|
264
|
+
recoveryMode?: StrandedWorkRecoveryMode;
|
|
265
|
+
blocksAuto: boolean;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface OrphanAuditResult {
|
|
269
|
+
recovered: string[];
|
|
270
|
+
warnings: string[];
|
|
271
|
+
actions: OrphanAuditAction[];
|
|
272
|
+
blockingStrandedWork: OrphanAuditAction | null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function isBlockingStrandedWorkAction(action: OrphanAuditAction): boolean {
|
|
276
|
+
return action.kind === "in-progress-stranded-work" && action.blocksAuto;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function detectWorktreeEvidence(
|
|
280
|
+
basePath: string,
|
|
281
|
+
milestoneId: string,
|
|
282
|
+
hasChanges: typeof nativeHasChanges,
|
|
283
|
+
): { path: string | null; dirExists: boolean; dirty: boolean } {
|
|
284
|
+
const wtDir = getWorktreeDir(basePath, milestoneId);
|
|
285
|
+
const wtPath = getAutoWorktreePath(basePath, milestoneId);
|
|
286
|
+
let dirty = false;
|
|
287
|
+
if (wtPath) {
|
|
288
|
+
try {
|
|
289
|
+
dirty = hasChanges(wtPath);
|
|
290
|
+
} catch {
|
|
291
|
+
dirty = false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
path: wtPath,
|
|
296
|
+
dirExists: existsSync(wtDir),
|
|
297
|
+
dirty,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function strandedWorkMessage(args: {
|
|
302
|
+
milestoneId: string;
|
|
303
|
+
branch?: string;
|
|
304
|
+
commitsAhead: number;
|
|
305
|
+
mainBranch: string;
|
|
306
|
+
dirtyWorktree: boolean;
|
|
307
|
+
worktreeDirExists: boolean;
|
|
308
|
+
recoveryMode: StrandedWorkRecoveryMode;
|
|
309
|
+
}): string {
|
|
310
|
+
const evidence: string[] = [];
|
|
311
|
+
if (args.branch && args.commitsAhead > 0) {
|
|
312
|
+
evidence.push(
|
|
313
|
+
`branch ${args.branch} has ${args.commitsAhead} commit(s) ahead of ${args.mainBranch}`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
if (args.dirtyWorktree) {
|
|
317
|
+
evidence.push("the worktree has uncommitted changes");
|
|
318
|
+
}
|
|
319
|
+
if (evidence.length === 0) {
|
|
320
|
+
evidence.push("physical git evidence exists");
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const wtSuffix = args.worktreeDirExists
|
|
324
|
+
? ` Worktree directory at .gsd/worktrees/${args.milestoneId}/ holds live work.`
|
|
325
|
+
: "";
|
|
326
|
+
const recovery = args.recoveryMode === "worktree"
|
|
327
|
+
? "Recovering will adopt the existing worktree."
|
|
328
|
+
: "Recovering will adopt the milestone branch.";
|
|
329
|
+
|
|
330
|
+
return (
|
|
331
|
+
`Stranded work for in-progress milestone ${args.milestoneId}: ${evidence.join("; ")}.` +
|
|
332
|
+
wtSuffix +
|
|
333
|
+
` ${recovery} Park or discard explicitly if abandoning.`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
245
337
|
export function auditOrphanedMilestoneBranches(
|
|
246
338
|
basePath: string,
|
|
247
|
-
|
|
339
|
+
_isolationMode: "worktree" | "branch" | "none",
|
|
248
340
|
gitDeps: {
|
|
249
341
|
branchList?: typeof nativeBranchList;
|
|
250
342
|
branchExists?: typeof nativeBranchExists;
|
|
343
|
+
hasChanges?: typeof nativeHasChanges;
|
|
251
344
|
} = {},
|
|
252
|
-
):
|
|
345
|
+
): OrphanAuditResult {
|
|
253
346
|
const recovered: string[] = [];
|
|
254
347
|
const warnings: string[] = [];
|
|
348
|
+
const actions: OrphanAuditAction[] = [];
|
|
255
349
|
const branchList = gitDeps.branchList ?? nativeBranchList;
|
|
256
350
|
const branchExists = gitDeps.branchExists ?? nativeBranchExists;
|
|
351
|
+
const hasChanges = gitDeps.hasChanges ?? nativeHasChanges;
|
|
257
352
|
|
|
258
|
-
|
|
259
|
-
|
|
353
|
+
const pushAction = (action: OrphanAuditAction): void => {
|
|
354
|
+
actions.push(action);
|
|
355
|
+
if (action.severity === "info") {
|
|
356
|
+
recovered.push(action.message);
|
|
357
|
+
} else {
|
|
358
|
+
warnings.push(action.message);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
260
361
|
|
|
261
362
|
// Skip if DB not available — can't determine completion status
|
|
262
|
-
if (!isDbAvailable())
|
|
363
|
+
if (!isDbAvailable()) {
|
|
364
|
+
return { recovered, warnings, actions, blockingStrandedWork: null };
|
|
365
|
+
}
|
|
263
366
|
|
|
264
367
|
let milestoneBranches: string[];
|
|
265
368
|
let milestoneBranchListAvailable = true;
|
|
@@ -295,6 +398,7 @@ export function auditOrphanedMilestoneBranches(
|
|
|
295
398
|
if (!milestone) continue;
|
|
296
399
|
|
|
297
400
|
const isMerged = mergedBranches.has(branch);
|
|
401
|
+
const worktreeEvidence = detectWorktreeEvidence(basePath, milestoneId, hasChanges);
|
|
298
402
|
|
|
299
403
|
// #4762 — in-progress milestone branch with unmerged commits ahead of
|
|
300
404
|
// main. This is the pre-completion orphan case: auto-mode exited without
|
|
@@ -307,33 +411,45 @@ export function auditOrphanedMilestoneBranches(
|
|
|
307
411
|
// Parked/other closed statuses go through the legacy complete/unmerged
|
|
308
412
|
// path below where appropriate.
|
|
309
413
|
if (!isClosedStatus(milestone.status)) {
|
|
310
|
-
if (isMerged) continue; // nothing to recover
|
|
311
414
|
let commitsAhead = 0;
|
|
312
415
|
try {
|
|
313
416
|
commitsAhead = nativeCommitCountBetween(basePath, mainBranch, branch);
|
|
314
417
|
} catch {
|
|
315
|
-
|
|
316
|
-
continue;
|
|
418
|
+
commitsAhead = 0;
|
|
317
419
|
}
|
|
318
|
-
if (commitsAhead === 0) continue;
|
|
319
|
-
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
420
|
+
if ((isMerged || commitsAhead === 0) && !worktreeEvidence.dirty) continue;
|
|
421
|
+
|
|
422
|
+
const recoveryMode: StrandedWorkRecoveryMode = worktreeEvidence.path
|
|
423
|
+
? "worktree"
|
|
424
|
+
: "branch";
|
|
425
|
+
const message = strandedWorkMessage({
|
|
426
|
+
milestoneId,
|
|
427
|
+
branch,
|
|
428
|
+
commitsAhead,
|
|
429
|
+
mainBranch,
|
|
430
|
+
dirtyWorktree: worktreeEvidence.dirty,
|
|
431
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
432
|
+
recoveryMode,
|
|
433
|
+
});
|
|
434
|
+
pushAction({
|
|
435
|
+
kind: "in-progress-stranded-work",
|
|
436
|
+
milestoneId,
|
|
437
|
+
branch,
|
|
438
|
+
commitsAhead,
|
|
439
|
+
dirtyWorktree: worktreeEvidence.dirty,
|
|
440
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
441
|
+
recoveryMode,
|
|
442
|
+
message,
|
|
443
|
+
severity: "warning",
|
|
444
|
+
blocksAuto: true,
|
|
445
|
+
});
|
|
330
446
|
|
|
331
447
|
// #4764 telemetry
|
|
332
448
|
try {
|
|
333
449
|
emitWorktreeOrphaned(basePath, milestoneId, {
|
|
334
450
|
reason: "in-progress-unmerged",
|
|
335
451
|
commitsAhead,
|
|
336
|
-
worktreeDirExists:
|
|
452
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
337
453
|
});
|
|
338
454
|
} catch (err) {
|
|
339
455
|
logWarning("engine", `worktree-orphaned telemetry failed for ${milestoneId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -351,7 +467,14 @@ export function auditOrphanedMilestoneBranches(
|
|
|
351
467
|
// Branch is merged — safe to delete branch and clean up worktree dir
|
|
352
468
|
try {
|
|
353
469
|
nativeBranchDelete(basePath, branch, true);
|
|
354
|
-
|
|
470
|
+
pushAction({
|
|
471
|
+
kind: "complete-merged-branch",
|
|
472
|
+
milestoneId,
|
|
473
|
+
branch,
|
|
474
|
+
message: `Deleted merged branch ${branch} for completed milestone ${milestoneId}.`,
|
|
475
|
+
severity: "info",
|
|
476
|
+
blocksAuto: false,
|
|
477
|
+
});
|
|
355
478
|
} catch (err) {
|
|
356
479
|
warnings.push(`Failed to delete merged branch ${branch}: ${err instanceof Error ? err.message : String(err)}`);
|
|
357
480
|
}
|
|
@@ -374,7 +497,15 @@ export function auditOrphanedMilestoneBranches(
|
|
|
374
497
|
if (isInsideWorktreesDir(basePath, wtDir)) {
|
|
375
498
|
try {
|
|
376
499
|
rmSync(wtDir, { recursive: true, force: true });
|
|
377
|
-
|
|
500
|
+
pushAction({
|
|
501
|
+
kind: "complete-merged-worktree",
|
|
502
|
+
milestoneId,
|
|
503
|
+
branch,
|
|
504
|
+
worktreeDirExists: true,
|
|
505
|
+
message: `Removed orphaned worktree directory for ${milestoneId}.`,
|
|
506
|
+
severity: "info",
|
|
507
|
+
blocksAuto: false,
|
|
508
|
+
});
|
|
378
509
|
} catch (err2) {
|
|
379
510
|
warnings.push(`Failed to remove worktree directory for ${milestoneId}: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
380
511
|
}
|
|
@@ -382,15 +513,30 @@ export function auditOrphanedMilestoneBranches(
|
|
|
382
513
|
warnings.push(`Orphaned worktree directory for ${milestoneId} is outside .gsd/worktrees/ — skipping removal for safety.`);
|
|
383
514
|
}
|
|
384
515
|
} else {
|
|
385
|
-
|
|
516
|
+
pushAction({
|
|
517
|
+
kind: "complete-merged-worktree",
|
|
518
|
+
milestoneId,
|
|
519
|
+
branch,
|
|
520
|
+
worktreeDirExists: true,
|
|
521
|
+
message: `Removed orphaned worktree directory for ${milestoneId}.`,
|
|
522
|
+
severity: "info",
|
|
523
|
+
blocksAuto: false,
|
|
524
|
+
});
|
|
386
525
|
}
|
|
387
526
|
}
|
|
388
527
|
} else {
|
|
389
528
|
// Branch is NOT merged — preserve for safety, warn the user
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
529
|
+
pushAction({
|
|
530
|
+
kind: "complete-unmerged-branch",
|
|
531
|
+
milestoneId,
|
|
532
|
+
branch,
|
|
533
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
534
|
+
message:
|
|
535
|
+
`Branch ${branch} exists for completed milestone ${milestoneId} but is NOT merged into ${mainBranch}. ` +
|
|
536
|
+
`This may contain unmerged work. Merge manually or run \`/gsd doctor fix\` to resolve.`,
|
|
537
|
+
severity: "warning",
|
|
538
|
+
blocksAuto: false,
|
|
539
|
+
});
|
|
394
540
|
|
|
395
541
|
// #4764 telemetry
|
|
396
542
|
try {
|
|
@@ -428,6 +574,41 @@ export function auditOrphanedMilestoneBranches(
|
|
|
428
574
|
completedMilestones = [];
|
|
429
575
|
}
|
|
430
576
|
for (const m of completedMilestones) {
|
|
577
|
+
if (!isClosedStatus(m.status)) {
|
|
578
|
+
if (seenMilestoneIds.has(m.id)) continue;
|
|
579
|
+
const worktreeEvidence = detectWorktreeEvidence(basePath, m.id, hasChanges);
|
|
580
|
+
if (!worktreeEvidence.dirty) continue;
|
|
581
|
+
const message = strandedWorkMessage({
|
|
582
|
+
milestoneId: m.id,
|
|
583
|
+
commitsAhead: 0,
|
|
584
|
+
mainBranch,
|
|
585
|
+
dirtyWorktree: true,
|
|
586
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
587
|
+
recoveryMode: "worktree",
|
|
588
|
+
});
|
|
589
|
+
pushAction({
|
|
590
|
+
kind: "in-progress-stranded-work",
|
|
591
|
+
milestoneId: m.id,
|
|
592
|
+
commitsAhead: 0,
|
|
593
|
+
dirtyWorktree: true,
|
|
594
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
595
|
+
recoveryMode: "worktree",
|
|
596
|
+
message,
|
|
597
|
+
severity: "warning",
|
|
598
|
+
blocksAuto: true,
|
|
599
|
+
});
|
|
600
|
+
try {
|
|
601
|
+
emitWorktreeOrphaned(basePath, m.id, {
|
|
602
|
+
reason: "in-progress-unmerged",
|
|
603
|
+
commitsAhead: 0,
|
|
604
|
+
worktreeDirExists: worktreeEvidence.dirExists,
|
|
605
|
+
});
|
|
606
|
+
} catch (err) {
|
|
607
|
+
logWarning("engine", `worktree-orphaned telemetry failed for ${m.id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
608
|
+
}
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
|
|
431
612
|
if (m.status !== "complete") continue;
|
|
432
613
|
if (seenMilestoneIds.has(m.id)) continue; // already processed in the branch loop
|
|
433
614
|
if (!milestoneBranchListAvailable) {
|
|
@@ -461,18 +642,37 @@ export function auditOrphanedMilestoneBranches(
|
|
|
461
642
|
if (existsSync(wtDir)) {
|
|
462
643
|
try {
|
|
463
644
|
rmSync(wtDir, { recursive: true, force: true });
|
|
464
|
-
|
|
645
|
+
pushAction({
|
|
646
|
+
kind: "complete-branchless-worktree",
|
|
647
|
+
milestoneId: m.id,
|
|
648
|
+
worktreeDirExists: true,
|
|
649
|
+
message: `Removed orphaned worktree directory for ${m.id} (branch already deleted).`,
|
|
650
|
+
severity: "info",
|
|
651
|
+
blocksAuto: false,
|
|
652
|
+
});
|
|
465
653
|
} catch (err) {
|
|
466
654
|
warnings.push(
|
|
467
655
|
`Failed to remove orphaned worktree directory for ${m.id}: ${err instanceof Error ? err.message : String(err)}`,
|
|
468
656
|
);
|
|
469
657
|
}
|
|
470
658
|
} else {
|
|
471
|
-
|
|
659
|
+
pushAction({
|
|
660
|
+
kind: "complete-branchless-worktree",
|
|
661
|
+
milestoneId: m.id,
|
|
662
|
+
worktreeDirExists: true,
|
|
663
|
+
message: `Removed orphaned worktree directory for ${m.id} (branch already deleted).`,
|
|
664
|
+
severity: "info",
|
|
665
|
+
blocksAuto: false,
|
|
666
|
+
});
|
|
472
667
|
}
|
|
473
668
|
}
|
|
474
669
|
|
|
475
|
-
return {
|
|
670
|
+
return {
|
|
671
|
+
recovered,
|
|
672
|
+
warnings,
|
|
673
|
+
actions,
|
|
674
|
+
blockingStrandedWork: actions.find(isBlockingStrandedWorkAction) ?? null,
|
|
675
|
+
};
|
|
476
676
|
}
|
|
477
677
|
|
|
478
678
|
/**
|
|
@@ -894,17 +1094,27 @@ export async function bootstrapAutoSession(
|
|
|
894
1094
|
// was lost due to session ending between completion and teardown.
|
|
895
1095
|
// Must run after DB open and before worktree entry.
|
|
896
1096
|
let orphanAuditRecovered = false;
|
|
1097
|
+
let strandedRecoveryActions: OrphanAuditAction[] = [];
|
|
1098
|
+
let strandedRecoveryAction: OrphanAuditAction | null = null;
|
|
897
1099
|
try {
|
|
898
1100
|
const auditResult = auditOrphanedMilestoneBranches(base, getIsolationMode(base));
|
|
1101
|
+
strandedRecoveryActions = auditResult.actions.filter(isBlockingStrandedWorkAction);
|
|
1102
|
+
strandedRecoveryAction = strandedRecoveryActions[0] ?? null;
|
|
899
1103
|
for (const msg of auditResult.recovered) {
|
|
900
1104
|
ctx.ui.notify(`Orphan audit: ${msg}`, "info");
|
|
901
1105
|
}
|
|
902
1106
|
for (const msg of auditResult.warnings) {
|
|
903
|
-
|
|
1107
|
+
const prefix = msg.startsWith("Stranded work") ? "" : "Orphan audit: ";
|
|
1108
|
+
ctx.ui.notify(`${prefix}${msg}`, "warning");
|
|
904
1109
|
}
|
|
905
1110
|
if (auditResult.recovered.length > 0) {
|
|
906
1111
|
orphanAuditRecovered = true;
|
|
907
|
-
debugLog("orphan-audit", {
|
|
1112
|
+
debugLog("orphan-audit", {
|
|
1113
|
+
recovered: auditResult.recovered,
|
|
1114
|
+
warnings: auditResult.warnings,
|
|
1115
|
+
strandedRecoveryAction,
|
|
1116
|
+
strandedRecoveryActions,
|
|
1117
|
+
});
|
|
908
1118
|
}
|
|
909
1119
|
} catch (err) {
|
|
910
1120
|
// Non-fatal — the audit is defensive, never block bootstrap
|
|
@@ -946,6 +1156,46 @@ export async function bootstrapAutoSession(
|
|
|
946
1156
|
|
|
947
1157
|
let state = await deriveState(base);
|
|
948
1158
|
|
|
1159
|
+
// Stale worktree state recovery (#654)
|
|
1160
|
+
if (
|
|
1161
|
+
state.activeMilestone &&
|
|
1162
|
+
shouldUseWorktreeIsolation(base) &&
|
|
1163
|
+
!detectWorktreeName(base)
|
|
1164
|
+
) {
|
|
1165
|
+
const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
|
|
1166
|
+
if (wtPath) {
|
|
1167
|
+
state = await deriveState(wtPath);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const blockingStrandedRecoveryAction = state.activeMilestone
|
|
1172
|
+
? strandedRecoveryActions.find(
|
|
1173
|
+
(action) => action.milestoneId !== state.activeMilestone?.id,
|
|
1174
|
+
) ?? strandedRecoveryAction
|
|
1175
|
+
: strandedRecoveryAction;
|
|
1176
|
+
|
|
1177
|
+
if (blockingStrandedRecoveryAction) {
|
|
1178
|
+
if (!state.activeMilestone) {
|
|
1179
|
+
ctx.ui.notify(
|
|
1180
|
+
`Stranded work for ${blockingStrandedRecoveryAction.milestoneId} blocks auto-mode, but that milestone is not active in project state. Park or discard it explicitly before continuing.`,
|
|
1181
|
+
"error",
|
|
1182
|
+
);
|
|
1183
|
+
return releaseLockAndReturn();
|
|
1184
|
+
}
|
|
1185
|
+
if (state.activeMilestone.id !== blockingStrandedRecoveryAction.milestoneId) {
|
|
1186
|
+
ctx.ui.notify(
|
|
1187
|
+
`Stranded work for ${blockingStrandedRecoveryAction.milestoneId} blocks auto-mode before ${state.activeMilestone.id}. Recover, park, or discard ${blockingStrandedRecoveryAction.milestoneId} explicitly before continuing.`,
|
|
1188
|
+
"error",
|
|
1189
|
+
);
|
|
1190
|
+
return releaseLockAndReturn();
|
|
1191
|
+
}
|
|
1192
|
+
strandedRecoveryAction = blockingStrandedRecoveryAction;
|
|
1193
|
+
ctx.ui.notify(
|
|
1194
|
+
`Recovering stranded work for ${strandedRecoveryAction.milestoneId} before dispatching new units.`,
|
|
1195
|
+
"info",
|
|
1196
|
+
);
|
|
1197
|
+
}
|
|
1198
|
+
|
|
949
1199
|
if (
|
|
950
1200
|
process.env.GSD_HEADLESS === "1" &&
|
|
951
1201
|
orphanAuditRecovered &&
|
|
@@ -959,18 +1209,6 @@ export async function bootstrapAutoSession(
|
|
|
959
1209
|
return releaseLockAndReturn();
|
|
960
1210
|
}
|
|
961
1211
|
|
|
962
|
-
// Stale worktree state recovery (#654)
|
|
963
|
-
if (
|
|
964
|
-
state.activeMilestone &&
|
|
965
|
-
shouldUseWorktreeIsolation(base) &&
|
|
966
|
-
!detectWorktreeName(base)
|
|
967
|
-
) {
|
|
968
|
-
const wtPath = getAutoWorktreePath(base, state.activeMilestone.id);
|
|
969
|
-
if (wtPath) {
|
|
970
|
-
state = await deriveState(wtPath);
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
|
|
974
1212
|
// Milestone branch recovery (#601, #2358)
|
|
975
1213
|
// Detect survivor milestone branches in both pre-planning and complete phases.
|
|
976
1214
|
// In phase=complete, the milestone artifacts exist but finalization (merge,
|
|
@@ -1005,7 +1243,10 @@ export async function bootstrapAutoSession(
|
|
|
1005
1243
|
// The worktree/branch was created but the milestone only has CONTEXT-DRAFT.md.
|
|
1006
1244
|
// Route to the interactive discussion handler instead of falling through to
|
|
1007
1245
|
// auto-mode, which would immediately stop with "needs discussion".
|
|
1008
|
-
if (
|
|
1246
|
+
if (
|
|
1247
|
+
!strandedRecoveryAction &&
|
|
1248
|
+
decideSurvivorAction(hasSurvivorBranch, state.phase) === "discuss"
|
|
1249
|
+
) {
|
|
1009
1250
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
1010
1251
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
1011
1252
|
|
|
@@ -1101,7 +1342,7 @@ export async function bootstrapAutoSession(
|
|
|
1101
1342
|
{ hasSurvivorBranch },
|
|
1102
1343
|
);
|
|
1103
1344
|
|
|
1104
|
-
if (deepProjectStagePending) {
|
|
1345
|
+
if (deepProjectStagePending && !strandedRecoveryAction) {
|
|
1105
1346
|
// Deep project-level setup runs before the first milestone exists. Let
|
|
1106
1347
|
// the auto loop dispatch workflow-preferences / project / requirements
|
|
1107
1348
|
// units instead of recursing back through showSmartEntry while this
|
|
@@ -1109,7 +1350,7 @@ export async function bootstrapAutoSession(
|
|
|
1109
1350
|
s.currentMilestoneId = null;
|
|
1110
1351
|
}
|
|
1111
1352
|
|
|
1112
|
-
if (!hasSurvivorBranch && !deepProjectStagePending) {
|
|
1353
|
+
if (!hasSurvivorBranch && !deepProjectStagePending && !strandedRecoveryAction) {
|
|
1113
1354
|
// No active work — start a new milestone via discuss flow
|
|
1114
1355
|
if (!state.activeMilestone || state.phase === "complete") {
|
|
1115
1356
|
// Guard against recursive dialog loop (#1348):
|
|
@@ -1185,7 +1426,7 @@ export async function bootstrapAutoSession(
|
|
|
1185
1426
|
}
|
|
1186
1427
|
|
|
1187
1428
|
// Unreachable safety check
|
|
1188
|
-
if (!state.activeMilestone && !deepProjectStagePending) {
|
|
1429
|
+
if (!state.activeMilestone && !deepProjectStagePending && !strandedRecoveryAction) {
|
|
1189
1430
|
const { showSmartEntry } = await import("./guided-flow.js");
|
|
1190
1431
|
await showSmartEntry(ctx, pi, base, { step: requestedStepMode });
|
|
1191
1432
|
return releaseLockAndReturn();
|
|
@@ -1222,7 +1463,9 @@ export async function bootstrapAutoSession(
|
|
|
1222
1463
|
s.resourceVersionOnStart = readResourceVersion();
|
|
1223
1464
|
s.pendingQuickTasks = [];
|
|
1224
1465
|
s.currentUnit = null;
|
|
1225
|
-
s.currentMilestoneId ??=
|
|
1466
|
+
s.currentMilestoneId ??=
|
|
1467
|
+
strandedRecoveryAction?.milestoneId ??
|
|
1468
|
+
(deepProjectStagePending ? null : state.activeMilestone?.id ?? null);
|
|
1226
1469
|
s.originalModelId = startModelSnapshot?.id ?? ctx.model?.id ?? null;
|
|
1227
1470
|
s.originalModelProvider = startModelSnapshot?.provider ?? ctx.model?.provider ?? null;
|
|
1228
1471
|
s.originalThinkingLevel = startThinkingSnapshot ?? null;
|
|
@@ -1232,7 +1475,7 @@ export async function bootstrapAutoSession(
|
|
|
1232
1475
|
|
|
1233
1476
|
// Capture integration branch
|
|
1234
1477
|
if (s.currentMilestoneId) {
|
|
1235
|
-
if (getIsolationMode(base) !== "none") {
|
|
1478
|
+
if (getIsolationMode(base) !== "none" || strandedRecoveryAction) {
|
|
1236
1479
|
captureIntegrationBranch(base, s.currentMilestoneId);
|
|
1237
1480
|
}
|
|
1238
1481
|
setActiveMilestoneId(base, s.currentMilestoneId);
|
|
@@ -1243,7 +1486,7 @@ export async function bootstrapAutoSession(
|
|
|
1243
1486
|
// milestone/<MID>. Auto-checkout back to the integration branch.
|
|
1244
1487
|
const isolationMode = getIsolationMode(base);
|
|
1245
1488
|
const isRepo = nativeIsRepo(base);
|
|
1246
|
-
if (isolationMode === "none" && isRepo) {
|
|
1489
|
+
if (isolationMode === "none" && isRepo && !strandedRecoveryAction) {
|
|
1247
1490
|
try {
|
|
1248
1491
|
const currentBranch = nativeGetCurrentBranch(base);
|
|
1249
1492
|
const integrationBranch = nativeDetectMainBranch(base);
|
|
@@ -1282,13 +1525,21 @@ export async function bootstrapAutoSession(
|
|
|
1282
1525
|
|
|
1283
1526
|
if (
|
|
1284
1527
|
s.currentMilestoneId &&
|
|
1285
|
-
getIsolationMode(base) !== "none" &&
|
|
1528
|
+
(getIsolationMode(base) !== "none" || strandedRecoveryAction?.recoveryMode) &&
|
|
1286
1529
|
!detectWorktreeName(base) &&
|
|
1287
1530
|
!isUnderGsdWorktrees(base)
|
|
1288
1531
|
) {
|
|
1289
|
-
const
|
|
1290
|
-
|
|
1291
|
-
|
|
1532
|
+
const lifecycle = buildLifecycle();
|
|
1533
|
+
const enterResult = strandedRecoveryAction?.recoveryMode
|
|
1534
|
+
? lifecycle.adoptStrandedMilestone(
|
|
1535
|
+
s.currentMilestoneId,
|
|
1536
|
+
base,
|
|
1537
|
+
{ notify: ctx.ui.notify.bind(ctx.ui) },
|
|
1538
|
+
{ mode: strandedRecoveryAction.recoveryMode },
|
|
1539
|
+
)
|
|
1540
|
+
: lifecycle.enterMilestone(s.currentMilestoneId, {
|
|
1541
|
+
notify: ctx.ui.notify.bind(ctx.ui),
|
|
1542
|
+
});
|
|
1292
1543
|
if (!enterResult.ok) {
|
|
1293
1544
|
s.active = false;
|
|
1294
1545
|
if (enterResult.reason === "lease-conflict") {
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* can distinguish "waiting for tool completion" from "truly idle".
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { stripMcpToolPrefix } from "@gsd/pi-ai";
|
|
8
|
+
|
|
7
9
|
interface InFlightTool {
|
|
8
10
|
startedAt: number;
|
|
9
11
|
toolName: string;
|
|
@@ -24,7 +26,7 @@ const INTERACTIVE_TOOLS = new Set(["ask_user_questions", "secure_env_collect"]);
|
|
|
24
26
|
*/
|
|
25
27
|
export function markToolStart(toolCallId: string, isActive: boolean, toolName?: string): void {
|
|
26
28
|
if (!isActive) return;
|
|
27
|
-
inFlightTools.set(toolCallId, { startedAt: Date.now(), toolName: toolName ?? "unknown" });
|
|
29
|
+
inFlightTools.set(toolCallId, { startedAt: Date.now(), toolName: stripMcpToolPrefix(toolName ?? "unknown") });
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -601,6 +601,7 @@ export async function runPostUnitVerification(
|
|
|
601
601
|
// ── Post-execution checks (run after main verification passes for execute-task units) ──
|
|
602
602
|
let postExecChecks: PostExecutionCheckJSON[] | undefined;
|
|
603
603
|
let postExecBlockingFailure = false;
|
|
604
|
+
let postExecFailureSummary: string | null = null;
|
|
604
605
|
|
|
605
606
|
if (result.passed && mid && sid && tid) {
|
|
606
607
|
// Check preferences — respect enhanced_verification and enhanced_verification_post
|
|
@@ -697,6 +698,13 @@ export async function runPostUnitVerification(
|
|
|
697
698
|
const blockingCount = postExecResult.checks.filter(
|
|
698
699
|
(c) => !c.passed && c.blocking
|
|
699
700
|
).length;
|
|
701
|
+
const firstBlockingFailure = postExecResult.checks.find(
|
|
702
|
+
(c) => !c.passed && c.blocking
|
|
703
|
+
);
|
|
704
|
+
if (firstBlockingFailure) {
|
|
705
|
+
postExecFailureSummary =
|
|
706
|
+
`[${firstBlockingFailure.category}] ${firstBlockingFailure.target}: ${firstBlockingFailure.message}`;
|
|
707
|
+
}
|
|
700
708
|
ctx.ui.notify(
|
|
701
709
|
`Post-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`,
|
|
702
710
|
"error"
|
|
@@ -709,6 +717,13 @@ export async function runPostUnitVerification(
|
|
|
709
717
|
// Strict mode: treat warnings as blocking
|
|
710
718
|
if (prefs?.enhanced_verification_strict === true) {
|
|
711
719
|
postExecBlockingFailure = true;
|
|
720
|
+
const firstWarning = postExecResult.checks.find(
|
|
721
|
+
(c) => (!c.passed && !c.blocking) || (c.passed && c.category === "pattern")
|
|
722
|
+
);
|
|
723
|
+
if (firstWarning) {
|
|
724
|
+
postExecFailureSummary =
|
|
725
|
+
`[${firstWarning.category}] ${firstWarning.target}: ${firstWarning.message}`;
|
|
726
|
+
}
|
|
712
727
|
}
|
|
713
728
|
}
|
|
714
729
|
}
|
|
@@ -811,12 +826,13 @@ export async function runPostUnitVerification(
|
|
|
811
826
|
s.verificationRetryCount.delete(retryKey);
|
|
812
827
|
s.verificationRetryFailureHashes.delete(retryKey);
|
|
813
828
|
s.pendingVerificationRetry = null;
|
|
829
|
+
const failureDetail = postExecFailureSummary ?? "unknown post-execution check failure";
|
|
814
830
|
ctx.ui.notify(
|
|
815
|
-
`Post-execution checks failed —
|
|
831
|
+
`Post-execution checks failed (${failureDetail}) — pausing for human review`,
|
|
816
832
|
"error",
|
|
817
833
|
);
|
|
818
834
|
await pauseAuto(ctx, pi, {
|
|
819
|
-
message:
|
|
835
|
+
message: `Post-execution checks failed: ${failureDetail}.`,
|
|
820
836
|
category: "unknown",
|
|
821
837
|
});
|
|
822
838
|
return "pause";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
unlinkSync,
|
|
21
21
|
lstatSync as lstatSyncFn,
|
|
22
22
|
} from "node:fs";
|
|
23
|
-
import { isAbsolute, join, relative, resolve, sep as pathSep } from "node:path";
|
|
23
|
+
import { dirname, isAbsolute, join, relative, resolve, sep as pathSep } from "node:path";
|
|
24
24
|
import { GSDError, GSD_IO_ERROR, GSD_GIT_ERROR } from "./errors.js";
|
|
25
25
|
import {
|
|
26
26
|
reconcileWorktreeDb,
|
|
@@ -60,6 +60,7 @@ import { logWarning, logError } from "./workflow-logger.js";
|
|
|
60
60
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
61
61
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
62
62
|
import { runWorktreePostCreateHook } from "./worktree-post-create-hook.js";
|
|
63
|
+
import { classifyProject } from "./detection.js";
|
|
63
64
|
import {
|
|
64
65
|
nativeGetCurrentBranch,
|
|
65
66
|
nativeDetectMainBranch,
|
|
@@ -259,6 +260,47 @@ export function _resolveAutoWorktreeStartPoint(
|
|
|
259
260
|
: undefined;
|
|
260
261
|
}
|
|
261
262
|
|
|
263
|
+
function importUntrackedProjectRootContentIntoEmptyWorktree(
|
|
264
|
+
projectRoot: string,
|
|
265
|
+
worktreeRoot: string,
|
|
266
|
+
milestoneId: string,
|
|
267
|
+
): number {
|
|
268
|
+
const worktreeClassification = classifyProject(worktreeRoot);
|
|
269
|
+
if (worktreeClassification.kind !== "greenfield") return 0;
|
|
270
|
+
|
|
271
|
+
const projectRootClassification = classifyProject(projectRoot);
|
|
272
|
+
if (
|
|
273
|
+
projectRootClassification.kind === "greenfield" ||
|
|
274
|
+
projectRootClassification.kind === "invalid-repo" ||
|
|
275
|
+
projectRootClassification.untrackedFiles.length === 0
|
|
276
|
+
) {
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let copied = 0;
|
|
281
|
+
for (const relPath of projectRootClassification.untrackedFiles) {
|
|
282
|
+
const src = join(projectRoot, relPath);
|
|
283
|
+
if (!existsSync(src)) continue;
|
|
284
|
+
|
|
285
|
+
const dst = join(worktreeRoot, relPath);
|
|
286
|
+
if (existsSync(dst)) continue;
|
|
287
|
+
|
|
288
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
289
|
+
cpSync(src, dst, { recursive: true, force: false });
|
|
290
|
+
copied++;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (copied > 0) {
|
|
294
|
+
debugLog("createAutoWorktree", {
|
|
295
|
+
phase: "import-untracked-project-content",
|
|
296
|
+
milestoneId,
|
|
297
|
+
copied,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return copied;
|
|
302
|
+
}
|
|
303
|
+
|
|
262
304
|
export function _shouldReconcileWorktreeDb(
|
|
263
305
|
worktreeDbPath: string,
|
|
264
306
|
mainDbPath: string,
|
|
@@ -1333,6 +1375,8 @@ export function createAutoWorktree(
|
|
|
1333
1375
|
// The original concerns (#759, #778) no longer apply because there is
|
|
1334
1376
|
// no second copy to drift.
|
|
1335
1377
|
|
|
1378
|
+
importUntrackedProjectRootContentIntoEmptyWorktree(basePath, info.path, milestoneId);
|
|
1379
|
+
|
|
1336
1380
|
// Run user-configured post-create hook (#597) — e.g. copy .env, symlink assets
|
|
1337
1381
|
const hookError = runWorktreePostCreateHook(basePath, info.path);
|
|
1338
1382
|
if (hookError) {
|