gsd-pi 2.57.0-dev.f22a903 → 2.58.0-dev.778d6ac
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 +1 -1
- package/dist/cli.js +49 -35
- package/dist/headless-ui.d.ts +17 -0
- package/dist/headless-ui.js +97 -3
- package/dist/headless.js +67 -6
- package/dist/help-text.js +1 -0
- package/dist/onboarding.js +44 -0
- package/dist/resource-loader.js +16 -1
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/ask-user-questions.js +16 -3
- package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
- package/dist/resources/extensions/context7/extension-manifest.json +1 -1
- package/dist/resources/extensions/get-secrets-from-user.js +8 -5
- package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
- package/dist/resources/extensions/google-search/index.js +2 -1
- package/dist/resources/extensions/gsd/auto/phases.js +25 -21
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -2
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
- package/dist/resources/extensions/gsd/auto-start.js +35 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +196 -12
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -8
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
- package/dist/resources/extensions/gsd/captures.js +56 -4
- package/dist/resources/extensions/gsd/db-writer.js +116 -8
- package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
- package/dist/resources/extensions/gsd/doctor.js +3 -1
- package/dist/resources/extensions/gsd/error-classifier.js +13 -10
- package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
- package/dist/resources/extensions/gsd/forensics.js +123 -20
- package/dist/resources/extensions/gsd/git-service.js +23 -1
- package/dist/resources/extensions/gsd/gitignore.js +33 -0
- package/dist/resources/extensions/gsd/gsd-db.js +36 -9
- package/dist/resources/extensions/gsd/guided-flow.js +106 -44
- package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
- package/dist/resources/extensions/gsd/health-widget.js +17 -0
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
- package/dist/resources/extensions/gsd/migrate-external.js +8 -1
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
- package/dist/resources/extensions/gsd/model-router.js +35 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
- package/dist/resources/extensions/gsd/notifications.js +16 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
- package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
- package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
- package/dist/resources/extensions/gsd/paths.js +43 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -1
- package/dist/resources/extensions/gsd/preferences-types.js +2 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -16
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/dist/resources/extensions/gsd/repo-identity.js +205 -11
- package/dist/resources/extensions/gsd/rethink.js +5 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
- package/dist/resources/extensions/gsd/state.js +85 -27
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +14 -3
- package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
- package/dist/resources/extensions/gsd/undo.js +2 -2
- package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
- package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
- package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
- package/dist/resources/extensions/gsd/workspace-index.js +24 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
- package/dist/resources/extensions/mcp-client/index.js +11 -7
- package/dist/resources/extensions/ollama/index.js +112 -0
- package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
- package/dist/resources/extensions/ollama/ollama-client.js +168 -0
- package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
- package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
- package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
- package/dist/resources/extensions/ollama/types.js +2 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/dist/resources/extensions/shared/interview-ui.js +11 -1
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/startup-model-validation.d.ts +39 -0
- package/dist/startup-model-validation.js +50 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
- 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 +1 -1
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.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 +1 -1
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- 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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- package/dist/web-mode.js +2 -1
- package/package.json +2 -2
- package/packages/daemon/src/cli.ts +49 -0
- package/packages/daemon/src/daemon.test.ts +104 -1
- package/packages/daemon/src/daemon.ts +24 -1
- package/packages/daemon/src/discord-bot.ts +73 -3
- package/packages/daemon/src/event-bridge.ts +15 -9
- package/packages/daemon/src/event-formatter.ts +30 -2
- package/packages/daemon/src/index.ts +9 -0
- package/packages/daemon/src/launchd.test.ts +356 -0
- package/packages/daemon/src/launchd.ts +242 -0
- package/packages/daemon/src/message-batcher.test.ts +2 -2
- package/packages/daemon/src/message-batcher.ts +9 -3
- package/packages/daemon/src/orchestrator.test.ts +1 -0
- package/packages/daemon/src/orchestrator.ts +106 -2
- package/packages/native/dist/ast/index.js +9 -5
- package/packages/native/dist/ast/types.js +2 -1
- package/packages/native/dist/clipboard/index.js +12 -7
- package/packages/native/dist/clipboard/types.js +2 -1
- package/packages/native/dist/diff/index.js +12 -7
- package/packages/native/dist/diff/types.js +2 -1
- package/packages/native/dist/fd/index.js +6 -3
- package/packages/native/dist/fd/types.js +2 -1
- package/packages/native/dist/glob/index.js +9 -5
- package/packages/native/dist/glob/types.js +2 -1
- package/packages/native/dist/grep/index.js +9 -5
- package/packages/native/dist/grep/types.js +2 -1
- package/packages/native/dist/gsd-parser/index.js +18 -11
- package/packages/native/dist/gsd-parser/types.js +2 -1
- package/packages/native/dist/highlight/index.js +12 -7
- package/packages/native/dist/highlight/types.js +2 -1
- package/packages/native/dist/html/index.js +6 -3
- package/packages/native/dist/html/types.js +2 -1
- package/packages/native/dist/image/index.js +10 -5
- package/packages/native/dist/image/types.js +7 -4
- package/packages/native/dist/index.js +70 -17
- package/packages/native/dist/json-parse/index.js +13 -8
- package/packages/native/dist/native.js +47 -10
- package/packages/native/dist/ps/index.js +15 -9
- package/packages/native/dist/ps/types.js +2 -1
- package/packages/native/dist/stream-process/index.js +12 -7
- package/packages/native/dist/text/index.js +24 -14
- package/packages/native/dist/text/types.js +5 -2
- package/packages/native/dist/truncate/index.js +12 -7
- package/packages/native/dist/ttsr/index.js +12 -7
- package/packages/native/dist/ttsr/types.js +2 -1
- package/packages/native/dist/xxhash/index.js +9 -5
- package/packages/native/package.json +19 -19
- package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
- package/packages/native/src/native.ts +9 -8
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/proxy.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
- package/packages/pi-agent-core/src/agent-loop.ts +3 -2
- package/packages/pi-agent-core/src/proxy.ts +1 -1
- package/packages/pi-ai/dist/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +3 -3
- 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/json-parse.d.ts +3 -0
- package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.js +24 -1
- package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
- package/packages/pi-ai/src/types.ts +3 -2
- package/packages/pi-ai/src/utils/json-parse.ts +28 -1
- package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/exec.js +3 -1
- package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.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 +31 -2
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +2 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
- package/packages/pi-coding-agent/src/core/exec.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +29 -2
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
- package/packages/pi-coding-agent/src/index.ts +6 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +9 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/terminal.ts +14 -0
- package/packages/pi-tui/src/tui.ts +8 -0
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -14
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/ask-user-questions.ts +21 -3
- package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
- package/src/resources/extensions/context7/extension-manifest.json +1 -1
- package/src/resources/extensions/get-secrets-from-user.ts +8 -5
- package/src/resources/extensions/google-search/extension-manifest.json +1 -1
- package/src/resources/extensions/google-search/index.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +43 -34
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -2
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-start.ts +35 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +190 -9
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +85 -8
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
- package/src/resources/extensions/gsd/captures.ts +63 -3
- package/src/resources/extensions/gsd/db-writer.ts +140 -7
- package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +14 -11
- package/src/resources/extensions/gsd/extension-manifest.json +16 -1
- package/src/resources/extensions/gsd/forensics.ts +144 -20
- package/src/resources/extensions/gsd/git-service.ts +26 -3
- package/src/resources/extensions/gsd/gitignore.ts +33 -0
- package/src/resources/extensions/gsd/gsd-db.ts +43 -7
- package/src/resources/extensions/gsd/guided-flow.ts +114 -45
- package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
- package/src/resources/extensions/gsd/health-widget.ts +17 -0
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
- package/src/resources/extensions/gsd/migrate-external.ts +9 -1
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
- package/src/resources/extensions/gsd/model-router.ts +35 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
- package/src/resources/extensions/gsd/notifications.ts +16 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
- package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
- package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
- package/src/resources/extensions/gsd/paths.ts +42 -0
- package/src/resources/extensions/gsd/preferences-models.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -15
- package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/src/resources/extensions/gsd/repo-identity.ts +186 -11
- package/src/resources/extensions/gsd/rethink.ts +6 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
- package/src/resources/extensions/gsd/state.ts +84 -32
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +20 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
- package/src/resources/extensions/gsd/types.ts +4 -2
- package/src/resources/extensions/gsd/undo.ts +2 -2
- package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
- package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
- package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
- package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
- package/src/resources/extensions/gsd/workspace-index.ts +30 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
- package/src/resources/extensions/mcp-client/index.ts +13 -7
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
- package/src/resources/extensions/ollama/index.ts +130 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
- package/src/resources/extensions/ollama/ollama-client.ts +196 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
- package/src/resources/extensions/ollama/types.ts +130 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/src/resources/extensions/shared/interview-ui.ts +12 -1
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/web/standalone/.next/static/chunks/6502.8b732f67a11b11b4.js +0 -9
- package/dist/web/standalone/.next/static/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { describe, it } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const gsdDir = join(__dirname, "..");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Regression tests for #2826: hook/* completed-unit keys were parsed
|
|
12
|
+
* incorrectly by forensics + doctor, causing false-positive missing-artifact
|
|
13
|
+
* errors for all hook units.
|
|
14
|
+
*
|
|
15
|
+
* The root cause: `key.indexOf("/")` splits "hook/telegram-progress/M007/S01"
|
|
16
|
+
* into unitType="hook" + unitId="telegram-progress/M007/S01" instead of
|
|
17
|
+
* unitType="hook/telegram-progress" + unitId="M007/S01".
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
describe("splitCompletedKey (#2826)", () => {
|
|
21
|
+
it("is exported from forensics.ts", () => {
|
|
22
|
+
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
23
|
+
assert.ok(
|
|
24
|
+
source.includes("export function splitCompletedKey"),
|
|
25
|
+
"forensics.ts must export splitCompletedKey helper",
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("splits simple unit types correctly", async () => {
|
|
30
|
+
const { splitCompletedKey } = await import("../forensics.ts");
|
|
31
|
+
const result = splitCompletedKey("execute-task/M007/S01/T01");
|
|
32
|
+
assert.deepStrictEqual(result, {
|
|
33
|
+
unitType: "execute-task",
|
|
34
|
+
unitId: "M007/S01/T01",
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("splits hook unit types preserving the compound hook/<hookName> prefix", async () => {
|
|
39
|
+
const { splitCompletedKey } = await import("../forensics.ts");
|
|
40
|
+
const result = splitCompletedKey("hook/telegram-progress/M007/S01");
|
|
41
|
+
assert.deepStrictEqual(result, {
|
|
42
|
+
unitType: "hook/telegram-progress",
|
|
43
|
+
unitId: "M007/S01",
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("splits hook unit types with task-level unitId", async () => {
|
|
48
|
+
const { splitCompletedKey } = await import("../forensics.ts");
|
|
49
|
+
const result = splitCompletedKey("hook/telegram-progress/M007/S02/T01");
|
|
50
|
+
assert.deepStrictEqual(result, {
|
|
51
|
+
unitType: "hook/telegram-progress",
|
|
52
|
+
unitId: "M007/S02/T01",
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("returns null for malformed keys without a slash", async () => {
|
|
57
|
+
const { splitCompletedKey } = await import("../forensics.ts");
|
|
58
|
+
assert.strictEqual(splitCompletedKey("noslash"), null);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns null for malformed hook keys with only 'hook/' and no more segments", async () => {
|
|
62
|
+
const { splitCompletedKey } = await import("../forensics.ts");
|
|
63
|
+
// "hook/someName" has no unitId segment after the hook name
|
|
64
|
+
assert.strictEqual(splitCompletedKey("hook/someName"), null);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe("forensics detectMissingArtifacts uses splitCompletedKey (#2826)", () => {
|
|
69
|
+
it("does not use indexOf for key splitting", () => {
|
|
70
|
+
const source = readFileSync(join(gsdDir, "forensics.ts"), "utf-8");
|
|
71
|
+
// Extract only the detectMissingArtifacts function body
|
|
72
|
+
const fnStart = source.indexOf("function detectMissingArtifacts");
|
|
73
|
+
assert.ok(fnStart !== -1, "detectMissingArtifacts must exist");
|
|
74
|
+
const fnBody = source.slice(fnStart, source.indexOf("\n}\n", fnStart) + 3);
|
|
75
|
+
|
|
76
|
+
assert.ok(
|
|
77
|
+
!fnBody.includes('key.indexOf("/")'),
|
|
78
|
+
"detectMissingArtifacts must not use key.indexOf('/') — use splitCompletedKey instead",
|
|
79
|
+
);
|
|
80
|
+
assert.ok(
|
|
81
|
+
fnBody.includes("splitCompletedKey"),
|
|
82
|
+
"detectMissingArtifacts must use splitCompletedKey helper",
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("doctor-runtime-checks uses splitCompletedKey (#2826)", () => {
|
|
88
|
+
it("does not use indexOf for key splitting in orphaned-key check", () => {
|
|
89
|
+
const source = readFileSync(
|
|
90
|
+
join(gsdDir, "doctor-runtime-checks.ts"),
|
|
91
|
+
"utf-8",
|
|
92
|
+
);
|
|
93
|
+
// Find the orphaned completed-units section
|
|
94
|
+
const sectionStart = source.indexOf("Orphaned completed-units");
|
|
95
|
+
assert.ok(sectionStart !== -1, "orphaned completed-units section must exist");
|
|
96
|
+
const sectionBody = source.slice(sectionStart, source.indexOf("} catch", sectionStart));
|
|
97
|
+
|
|
98
|
+
assert.ok(
|
|
99
|
+
!sectionBody.includes('key.indexOf("/")'),
|
|
100
|
+
"doctor orphaned-key check must not use key.indexOf('/') — use splitCompletedKey instead",
|
|
101
|
+
);
|
|
102
|
+
assert.ok(
|
|
103
|
+
sectionBody.includes("splitCompletedKey"),
|
|
104
|
+
"doctor orphaned-key check must use splitCompletedKey helper",
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -111,7 +111,51 @@ test("resolveExpectedArtifactPath returns correct path for all slice-level types
|
|
|
111
111
|
|
|
112
112
|
const uatResult = resolveExpectedArtifactPath("run-uat", "M001/S01", base);
|
|
113
113
|
assert.ok(uatResult);
|
|
114
|
-
assert.ok(uatResult!.includes("
|
|
114
|
+
assert.ok(uatResult!.includes("ASSESSMENT"));
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ─── run-uat artifact path contract (#2873) ──────────────────────────────
|
|
118
|
+
|
|
119
|
+
test("resolveExpectedArtifactPath for run-uat returns ASSESSMENT path, not UAT (#2873)", (t) => {
|
|
120
|
+
// The run-uat prompt instructs the agent to call gsd_summary_save with
|
|
121
|
+
// artifact_type: "ASSESSMENT", which writes S##-ASSESSMENT.md. The artifact
|
|
122
|
+
// verification path must match — otherwise verification fails and auto-mode
|
|
123
|
+
// retries the unit in an infinite loop.
|
|
124
|
+
const base = makeTmpBase();
|
|
125
|
+
t.after(() => cleanup(base));
|
|
126
|
+
|
|
127
|
+
const result = resolveExpectedArtifactPath("run-uat", "M001/S01", base);
|
|
128
|
+
assert.ok(result, "run-uat should resolve to a non-null artifact path");
|
|
129
|
+
assert.ok(
|
|
130
|
+
result!.endsWith("S01-ASSESSMENT.md"),
|
|
131
|
+
`run-uat artifact path should end with S01-ASSESSMENT.md, got: ${result}`,
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("diagnoseExpectedArtifact for run-uat references ASSESSMENT (#2873)", (t) => {
|
|
136
|
+
const base = makeTmpBase();
|
|
137
|
+
t.after(() => cleanup(base));
|
|
138
|
+
|
|
139
|
+
const diag = diagnoseExpectedArtifact("run-uat", "M001/S01", base);
|
|
140
|
+
assert.ok(diag, "run-uat should have a diagnostic message");
|
|
141
|
+
assert.ok(
|
|
142
|
+
diag!.includes("ASSESSMENT"),
|
|
143
|
+
`run-uat diagnostic should reference ASSESSMENT, got: ${diag}`,
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("verifyExpectedArtifact passes for run-uat when ASSESSMENT file exists (#2873)", (t) => {
|
|
148
|
+
// Regression test: run-uat writes S##-ASSESSMENT.md via gsd_summary_save,
|
|
149
|
+
// but verification looked for S##-UAT.md, causing false stuck retries.
|
|
150
|
+
const base = makeTmpBase();
|
|
151
|
+
t.after(() => cleanup(base));
|
|
152
|
+
|
|
153
|
+
// Write the ASSESSMENT file (what gsd_summary_save actually produces)
|
|
154
|
+
const assessPath = join(base, ".gsd", "milestones", "M001", "slices", "S01", "S01-ASSESSMENT.md");
|
|
155
|
+
writeFileSync(assessPath, "---\nverdict: PASS\n---\n# UAT Assessment\n");
|
|
156
|
+
|
|
157
|
+
const verified = verifyExpectedArtifact("run-uat", "M001/S01", base);
|
|
158
|
+
assert.ok(verified, "verifyExpectedArtifact should pass when ASSESSMENT file exists");
|
|
115
159
|
});
|
|
116
160
|
|
|
117
161
|
// ─── diagnoseExpectedArtifact ─────────────────────────────────────────────
|
|
@@ -697,6 +741,72 @@ test("verifyExpectedArtifact complete-milestone fails with only .gsd/ files (#17
|
|
|
697
741
|
assert.equal(result, false, "complete-milestone should fail verification when only .gsd/ files present");
|
|
698
742
|
});
|
|
699
743
|
|
|
744
|
+
// ─── reconcileMergeState: silent nativeCommit failure (#2542) ─────────────
|
|
745
|
+
|
|
746
|
+
import { reconcileMergeState } from "../../auto-recovery.ts";
|
|
747
|
+
import { chmodSync } from "node:fs";
|
|
748
|
+
|
|
749
|
+
function makeMockCtx(): { ctx: any; notifications: Array<{ msg: string; level: string }> } {
|
|
750
|
+
const notifications: Array<{ msg: string; level: string }> = [];
|
|
751
|
+
const ctx = {
|
|
752
|
+
ui: {
|
|
753
|
+
notify(msg: string, level: string) {
|
|
754
|
+
notifications.push({ msg, level });
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
};
|
|
758
|
+
return { ctx, notifications };
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
test("reconcileMergeState returns false and notifies error when nativeCommit fails (#2542)", (t) => {
|
|
762
|
+
const base = makeGitBase();
|
|
763
|
+
t.after(() => cleanup(base));
|
|
764
|
+
|
|
765
|
+
// Create a second branch with a commit, then start a merge on main
|
|
766
|
+
execFileSync("git", ["checkout", "-b", "feature"], { cwd: base, stdio: "ignore" });
|
|
767
|
+
writeFileSync(join(base, "feature.txt"), "feature content");
|
|
768
|
+
execFileSync("git", ["add", "."], { cwd: base, stdio: "ignore" });
|
|
769
|
+
execFileSync("git", ["commit", "-m", "add feature"], { cwd: base, stdio: "ignore" });
|
|
770
|
+
execFileSync("git", ["checkout", "main"], { cwd: base, stdio: "ignore" });
|
|
771
|
+
|
|
772
|
+
// Start merge (no conflicts — fast path with MERGE_HEAD)
|
|
773
|
+
execFileSync("git", ["merge", "--no-ff", "--no-commit", "feature"], { cwd: base, stdio: "ignore" });
|
|
774
|
+
|
|
775
|
+
// Verify MERGE_HEAD exists
|
|
776
|
+
assert.ok(existsSync(join(base, ".git", "MERGE_HEAD")), "MERGE_HEAD should exist");
|
|
777
|
+
|
|
778
|
+
// Make .git/objects read-only so git cannot write the commit object,
|
|
779
|
+
// causing nativeCommit to throw a non-"nothing to commit" error.
|
|
780
|
+
const objectsDir = join(base, ".git", "objects");
|
|
781
|
+
chmodSync(objectsDir, 0o444);
|
|
782
|
+
t.after(() => { try { chmodSync(objectsDir, 0o755); } catch { /* cleanup */ } });
|
|
783
|
+
|
|
784
|
+
const { ctx, notifications } = makeMockCtx();
|
|
785
|
+
const result = reconcileMergeState(base, ctx);
|
|
786
|
+
|
|
787
|
+
// The function should return false to signal reconciliation failure
|
|
788
|
+
// (Currently it silently swallows the error and returns true — this test should FAIL before the fix)
|
|
789
|
+
assert.equal(result, false, "reconcileMergeState should return false when nativeCommit fails");
|
|
790
|
+
const errorNotifications = notifications.filter(n => n.level === "error");
|
|
791
|
+
assert.ok(errorNotifications.length > 0, "should notify an error when nativeCommit fails");
|
|
792
|
+
assert.ok(
|
|
793
|
+
errorNotifications[0].msg.includes("Failed to finalize"),
|
|
794
|
+
"error notification should describe the commit failure",
|
|
795
|
+
);
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
test("reconcileMergeState returns true when no merge state present", (t) => {
|
|
799
|
+
// When there's no MERGE_HEAD or SQUASH_MSG, reconcileMergeState returns false (no dirty state)
|
|
800
|
+
const base = makeGitBase();
|
|
801
|
+
t.after(() => cleanup(base));
|
|
802
|
+
|
|
803
|
+
const { ctx, notifications } = makeMockCtx();
|
|
804
|
+
const result = reconcileMergeState(base, ctx);
|
|
805
|
+
|
|
806
|
+
assert.equal(result, false, "should return false when no merge state exists");
|
|
807
|
+
assert.equal(notifications.length, 0, "should not notify when no merge state present");
|
|
808
|
+
});
|
|
809
|
+
|
|
700
810
|
test("verifyExpectedArtifact complete-milestone passes with impl files (#1703)", (t) => {
|
|
701
811
|
const base = makeGitBase();
|
|
702
812
|
t.after(() => cleanup(base));
|
package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts
CHANGED
|
@@ -638,6 +638,107 @@ describe("auto-worktree-milestone-merge", { timeout: 300_000 }, () => {
|
|
|
638
638
|
"#1906: codeFilesChanged must be false when only .gsd/ files were merged");
|
|
639
639
|
});
|
|
640
640
|
|
|
641
|
+
test("#2912: MERGE_HEAD cleaned up after squash-merge conflict", () => {
|
|
642
|
+
const repo = freshRepo();
|
|
643
|
+
const wtPath = createAutoWorktree(repo, "M291");
|
|
644
|
+
|
|
645
|
+
// Create a file on main that will conflict with the milestone branch
|
|
646
|
+
run("git checkout main", repo);
|
|
647
|
+
writeFileSync(join(repo, "conflict.ts"), "// main version\nexport const x = 1;\n");
|
|
648
|
+
run("git add .", repo);
|
|
649
|
+
run("git commit -m 'add conflict.ts on main'", repo);
|
|
650
|
+
|
|
651
|
+
// Switch back to milestone branch and create conflicting content
|
|
652
|
+
run("git checkout milestone/M291", wtPath);
|
|
653
|
+
writeFileSync(join(wtPath, "conflict.ts"), "// milestone version\nexport const x = 2;\n");
|
|
654
|
+
run("git add .", wtPath);
|
|
655
|
+
run("git commit -m 'add conflict.ts on milestone'", wtPath);
|
|
656
|
+
|
|
657
|
+
const roadmap = makeRoadmap("M291", "Conflict milestone", [
|
|
658
|
+
{ id: "S01", title: "Conflict test" },
|
|
659
|
+
]);
|
|
660
|
+
|
|
661
|
+
// The merge should throw MergeConflictError due to conflict.ts
|
|
662
|
+
let threw = false;
|
|
663
|
+
try {
|
|
664
|
+
mergeMilestoneToMain(repo, "M291", roadmap);
|
|
665
|
+
} catch (err: unknown) {
|
|
666
|
+
threw = true;
|
|
667
|
+
// Verify it's a merge conflict error
|
|
668
|
+
assert.ok(
|
|
669
|
+
err instanceof Error && err.message.includes("conflict"),
|
|
670
|
+
"should throw a conflict-related error",
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
assert.ok(threw, "mergeMilestoneToMain must throw on code conflict");
|
|
674
|
+
|
|
675
|
+
// BUG #2912: MERGE_HEAD must NOT be left on disk after the error
|
|
676
|
+
const mergeHeadPath = join(repo, ".git", "MERGE_HEAD");
|
|
677
|
+
assert.ok(
|
|
678
|
+
!existsSync(mergeHeadPath),
|
|
679
|
+
"#2912: MERGE_HEAD must be cleaned up after merge conflict error",
|
|
680
|
+
);
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test("#2912: stale MERGE_HEAD from native merge is cleaned after successful commit", () => {
|
|
684
|
+
const repo = freshRepo();
|
|
685
|
+
const wtPath = createAutoWorktree(repo, "M292");
|
|
686
|
+
|
|
687
|
+
addSliceToMilestone(repo, wtPath, "M292", "S01", "Feature A", [
|
|
688
|
+
{ file: "feature-a.ts", content: "export const a = true;\n", message: "add feature a" },
|
|
689
|
+
]);
|
|
690
|
+
|
|
691
|
+
const roadmap = makeRoadmap("M292", "Clean merge", [
|
|
692
|
+
{ id: "S01", title: "Feature A" },
|
|
693
|
+
]);
|
|
694
|
+
|
|
695
|
+
// Simulate what libgit2's merge implementation does: it creates MERGE_HEAD
|
|
696
|
+
// even for squash merges (unlike CLI git). We plant MERGE_HEAD before calling
|
|
697
|
+
// mergeMilestoneToMain to verify the success path cleans it up.
|
|
698
|
+
// We cannot plant it before the call because the function manages checkout
|
|
699
|
+
// internally, so instead we verify after the call.
|
|
700
|
+
mergeMilestoneToMain(repo, "M292", roadmap);
|
|
701
|
+
|
|
702
|
+
// After successful merge+commit, MERGE_HEAD must not linger
|
|
703
|
+
const mergeHeadPath = join(repo, ".git", "MERGE_HEAD");
|
|
704
|
+
assert.ok(
|
|
705
|
+
!existsSync(mergeHeadPath),
|
|
706
|
+
"#2912: MERGE_HEAD must be cleaned up after successful merge",
|
|
707
|
+
);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("#2912: planted MERGE_HEAD is cleaned up in success path", () => {
|
|
711
|
+
// This test directly verifies the cleanup code handles a MERGE_HEAD file
|
|
712
|
+
// left by the native (libgit2) merge path. We hook into the merge by
|
|
713
|
+
// planting MERGE_HEAD right after nativeMergeSquash would create it.
|
|
714
|
+
const repo = freshRepo();
|
|
715
|
+
const wtPath = createAutoWorktree(repo, "M293");
|
|
716
|
+
|
|
717
|
+
addSliceToMilestone(repo, wtPath, "M293", "S01", "Feature B", [
|
|
718
|
+
{ file: "feature-b.ts", content: "export const b = true;\n", message: "add feature b" },
|
|
719
|
+
]);
|
|
720
|
+
|
|
721
|
+
const roadmap = makeRoadmap("M293", "Planted MERGE_HEAD", [
|
|
722
|
+
{ id: "S01", title: "Feature B" },
|
|
723
|
+
]);
|
|
724
|
+
|
|
725
|
+
// Plant a fake MERGE_HEAD in the git dir to simulate libgit2 behavior.
|
|
726
|
+
// We need to do this after the function checks out main but before it
|
|
727
|
+
// commits. Since we can't intercept mid-function, we plant it before
|
|
728
|
+
// the call. If the function cleans it up, the test passes.
|
|
729
|
+
const gitDir = join(repo, ".git");
|
|
730
|
+
const fakeHead = run("git rev-parse HEAD", repo);
|
|
731
|
+
writeFileSync(join(gitDir, "MERGE_HEAD"), fakeHead + "\n");
|
|
732
|
+
|
|
733
|
+
mergeMilestoneToMain(repo, "M293", roadmap);
|
|
734
|
+
|
|
735
|
+
// The planted MERGE_HEAD must be cleaned up
|
|
736
|
+
assert.ok(
|
|
737
|
+
!existsSync(join(gitDir, "MERGE_HEAD")),
|
|
738
|
+
"#2912: planted MERGE_HEAD must be removed by success-path cleanup",
|
|
739
|
+
);
|
|
740
|
+
});
|
|
741
|
+
|
|
641
742
|
test("#1906: codeFilesChanged=true when real code is merged", () => {
|
|
642
743
|
const repo = freshRepo();
|
|
643
744
|
const wtPath = createAutoWorktree(repo, "M190");
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
enterAutoWorktree,
|
|
21
21
|
getAutoWorktreeOriginalBase,
|
|
22
22
|
getActiveAutoWorktreeContext,
|
|
23
|
+
syncGsdStateToWorktree,
|
|
23
24
|
} from "../../auto-worktree.ts";
|
|
24
25
|
|
|
25
26
|
// Note: execSync is used intentionally in tests for git operations with
|
|
@@ -286,4 +287,62 @@ describe("auto-worktree lifecycle", () => {
|
|
|
286
287
|
teardownAutoWorktree(tempDir, "M004");
|
|
287
288
|
}
|
|
288
289
|
});
|
|
290
|
+
|
|
291
|
+
test("#2791: mcp.json copied into worktree via copyPlanningArtifacts", () => {
|
|
292
|
+
tempDir = createTempRepo();
|
|
293
|
+
const msDir = join(tempDir, ".gsd", "milestones", "M003");
|
|
294
|
+
mkdirSync(msDir, { recursive: true });
|
|
295
|
+
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
296
|
+
run("git add .", tempDir);
|
|
297
|
+
run("git commit -m \"add milestone\"", tempDir);
|
|
298
|
+
|
|
299
|
+
// Create mcp.json in .gsd/ AFTER the commit (untracked, like real usage).
|
|
300
|
+
// copyPlanningArtifacts should copy it into the worktree's .gsd/.
|
|
301
|
+
writeFileSync(
|
|
302
|
+
join(tempDir, ".gsd", "mcp.json"),
|
|
303
|
+
JSON.stringify({ servers: { test: { command: "echo" } } }),
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
const wtPath = createAutoWorktree(tempDir, "M003");
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
assert.ok(
|
|
310
|
+
existsSync(join(wtPath, ".gsd", "mcp.json")),
|
|
311
|
+
"mcp.json should be copied into worktree .gsd/ on creation",
|
|
312
|
+
);
|
|
313
|
+
} finally {
|
|
314
|
+
teardownAutoWorktree(tempDir, "M003");
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("#2791: mcp.json synced via syncGsdStateToWorktree (ROOT_STATE_FILES)", () => {
|
|
319
|
+
tempDir = createTempRepo();
|
|
320
|
+
const msDir = join(tempDir, ".gsd", "milestones", "M003");
|
|
321
|
+
mkdirSync(msDir, { recursive: true });
|
|
322
|
+
writeFileSync(join(msDir, "CONTEXT.md"), "# M003 Context\n");
|
|
323
|
+
run("git add .", tempDir);
|
|
324
|
+
run("git commit -m \"add milestone\"", tempDir);
|
|
325
|
+
|
|
326
|
+
// Create worktree first (no mcp.json yet)
|
|
327
|
+
const wtPath = createAutoWorktree(tempDir, "M003");
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
// Now add mcp.json to the main .gsd/ after worktree was created
|
|
331
|
+
writeFileSync(
|
|
332
|
+
join(tempDir, ".gsd", "mcp.json"),
|
|
333
|
+
JSON.stringify({ servers: { test: { command: "echo" } } }),
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
// Sync should pick up the new mcp.json
|
|
337
|
+
const { synced } = syncGsdStateToWorktree(tempDir, wtPath);
|
|
338
|
+
|
|
339
|
+
assert.ok(synced.includes("mcp.json"), "mcp.json should be in the synced list");
|
|
340
|
+
assert.ok(
|
|
341
|
+
existsSync(join(wtPath, ".gsd", "mcp.json")),
|
|
342
|
+
"mcp.json should exist in worktree after sync",
|
|
343
|
+
);
|
|
344
|
+
} finally {
|
|
345
|
+
teardownAutoWorktree(tempDir, "M003");
|
|
346
|
+
}
|
|
347
|
+
});
|
|
289
348
|
});
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { describe, test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readdirSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
|
|
7
|
+
import { runGSDDoctor } from "../../doctor.js";
|
|
8
|
+
import { parsePlan } from "../../parsers-legacy.js";
|
|
9
|
+
|
|
10
|
+
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
function makeBase(): { base: string; gsd: string; mDir: string } {
|
|
13
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-doctor-fp-"));
|
|
14
|
+
const gsd = join(base, ".gsd");
|
|
15
|
+
const mDir = join(gsd, "milestones", "M001");
|
|
16
|
+
mkdirSync(join(mDir, "slices"), { recursive: true });
|
|
17
|
+
return { base, gsd, mDir };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function writeRoadmap(mDir: string, content: string): void {
|
|
21
|
+
writeFileSync(join(mDir, "M001-ROADMAP.md"), content);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function writeSlice(mDir: string, sliceId: string, planContent: string): string {
|
|
25
|
+
const sDir = join(mDir, "slices", sliceId);
|
|
26
|
+
const tDir = join(sDir, "tasks");
|
|
27
|
+
mkdirSync(tDir, { recursive: true });
|
|
28
|
+
writeFileSync(join(sDir, `${sliceId}-PLAN.md`), planContent);
|
|
29
|
+
return sDir;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('doctor false-positives (#3105)', async () => {
|
|
33
|
+
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
35
|
+
// Bug 1: Orphaned worktree directory recreated by appendDoctorHistory
|
|
36
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
37
|
+
|
|
38
|
+
test('Bug 1: orphaned worktree check ignores dirs containing only .gsd/doctor-history.jsonl', async () => {
|
|
39
|
+
// Simulate: a worktree dir that only contains .gsd/doctor-history.jsonl
|
|
40
|
+
// (created by appendDoctorHistory writing to the worktree-scoped path).
|
|
41
|
+
// The orphan check should NOT warn about this directory.
|
|
42
|
+
const { base, gsd } = makeBase();
|
|
43
|
+
writeRoadmap(join(gsd, "milestones", "M001"), `# M001: Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
44
|
+
writeSlice(join(gsd, "milestones", "M001"), "S01", "# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [ ] **T01: Task** `est:10m`\n Pending.\n");
|
|
45
|
+
|
|
46
|
+
// Create a worktree directory that only has .gsd/doctor-history.jsonl
|
|
47
|
+
const wtDir = join(gsd, "worktrees", "M042");
|
|
48
|
+
const wtGsdDir = join(wtDir, ".gsd");
|
|
49
|
+
mkdirSync(wtGsdDir, { recursive: true });
|
|
50
|
+
writeFileSync(join(wtGsdDir, "doctor-history.jsonl"), '{"ts":"2026-01-01","ok":true}\n');
|
|
51
|
+
|
|
52
|
+
const result = await runGSDDoctor(base, { fix: false });
|
|
53
|
+
|
|
54
|
+
// Should NOT produce worktree_directory_orphaned for a dir that only has doctor history
|
|
55
|
+
const orphanIssues = result.issues.filter(
|
|
56
|
+
i => i.code === "worktree_directory_orphaned" && i.unitId === "M042"
|
|
57
|
+
);
|
|
58
|
+
assert.equal(orphanIssues.length, 0,
|
|
59
|
+
"should not warn about worktree dir that only contains .gsd/doctor-history.jsonl");
|
|
60
|
+
|
|
61
|
+
rmSync(base, { recursive: true, force: true });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
65
|
+
// Bug 2: blocker_discovered + all tasks done = unfixable deadlock
|
|
66
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
67
|
+
|
|
68
|
+
test('Bug 2: blocker_discovered with all tasks done should not warn (implicitly resolved)', async () => {
|
|
69
|
+
// Scenario: blocker was discovered and resolved within the same task.
|
|
70
|
+
// blocker_discovered: true, no REPLAN, but all tasks are done.
|
|
71
|
+
// Neither blocker_discovered_no_replan nor stale_replan_file should fire.
|
|
72
|
+
const { base, mDir } = makeBase();
|
|
73
|
+
writeRoadmap(mDir, `# M001: Blocker Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
74
|
+
const sDir = writeSlice(mDir, "S01",
|
|
75
|
+
"# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task** `est:10m`\n Done.\n");
|
|
76
|
+
writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), `---
|
|
77
|
+
id: T01
|
|
78
|
+
parent: S01
|
|
79
|
+
milestone: M001
|
|
80
|
+
provides: []
|
|
81
|
+
requires: []
|
|
82
|
+
affects: []
|
|
83
|
+
key_files: []
|
|
84
|
+
key_decisions: []
|
|
85
|
+
patterns_established: []
|
|
86
|
+
observability_surfaces: []
|
|
87
|
+
drill_down_paths: []
|
|
88
|
+
duration: 10m
|
|
89
|
+
verification_result: passed
|
|
90
|
+
completed_at: 2026-01-01T00:00:00Z
|
|
91
|
+
blocker_discovered: true
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
# T01: Task
|
|
95
|
+
|
|
96
|
+
**Done**
|
|
97
|
+
|
|
98
|
+
## What Happened
|
|
99
|
+
Found a blocker, resolved it in-task.
|
|
100
|
+
|
|
101
|
+
## Diagnostics
|
|
102
|
+
- log
|
|
103
|
+
`);
|
|
104
|
+
|
|
105
|
+
const result = await runGSDDoctor(base, { fix: false });
|
|
106
|
+
|
|
107
|
+
// Should NOT produce blocker_discovered_no_replan when all tasks are done
|
|
108
|
+
const blockerIssues = result.issues.filter(i => i.code === "blocker_discovered_no_replan");
|
|
109
|
+
assert.equal(blockerIssues.length, 0,
|
|
110
|
+
"should not warn about blocker_discovered when all tasks are done (blocker was implicitly resolved)");
|
|
111
|
+
|
|
112
|
+
// Also should NOT produce stale_replan_file (no REPLAN exists, so this shouldn't fire anyway)
|
|
113
|
+
const staleReplanIssues = result.issues.filter(i => i.code === "stale_replan_file");
|
|
114
|
+
assert.equal(staleReplanIssues.length, 0,
|
|
115
|
+
"should not produce stale_replan_file when no REPLAN exists");
|
|
116
|
+
|
|
117
|
+
rmSync(base, { recursive: true, force: true });
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('Bug 2: blocker_discovered with incomplete tasks should still warn', async () => {
|
|
121
|
+
// Sanity check: when there IS an incomplete task and blocker_discovered, warn as before.
|
|
122
|
+
const { base, mDir } = makeBase();
|
|
123
|
+
writeRoadmap(mDir, `# M001: Blocker Warn Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
124
|
+
const sDir = writeSlice(mDir, "S01",
|
|
125
|
+
"# S01: Slice\n\n**Goal:** G\n**Demo:** D\n\n## Tasks\n- [x] **T01: Task A** `est:10m`\n Done.\n- [ ] **T02: Task B** `est:10m`\n Pending.\n");
|
|
126
|
+
writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), `---
|
|
127
|
+
id: T01
|
|
128
|
+
parent: S01
|
|
129
|
+
milestone: M001
|
|
130
|
+
provides: []
|
|
131
|
+
requires: []
|
|
132
|
+
affects: []
|
|
133
|
+
key_files: []
|
|
134
|
+
key_decisions: []
|
|
135
|
+
patterns_established: []
|
|
136
|
+
observability_surfaces: []
|
|
137
|
+
drill_down_paths: []
|
|
138
|
+
duration: 10m
|
|
139
|
+
verification_result: passed
|
|
140
|
+
completed_at: 2026-01-01T00:00:00Z
|
|
141
|
+
blocker_discovered: true
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
# T01: Task A
|
|
145
|
+
|
|
146
|
+
**Done**
|
|
147
|
+
|
|
148
|
+
## What Happened
|
|
149
|
+
Found blocker, but T02 is still pending.
|
|
150
|
+
|
|
151
|
+
## Diagnostics
|
|
152
|
+
- log
|
|
153
|
+
`);
|
|
154
|
+
|
|
155
|
+
const result = await runGSDDoctor(base, { fix: false });
|
|
156
|
+
|
|
157
|
+
const blockerIssues = result.issues.filter(i => i.code === "blocker_discovered_no_replan");
|
|
158
|
+
assert.ok(blockerIssues.length > 0,
|
|
159
|
+
"should still warn about blocker_discovered when some tasks are not done");
|
|
160
|
+
|
|
161
|
+
rmSync(base, { recursive: true, force: true });
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
165
|
+
// Bug 3: Multi-task plan — T02+ outside ## Tasks section
|
|
166
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
167
|
+
|
|
168
|
+
test('Bug 3: parsePlan finds all tasks even when interleaved with detail sections', () => {
|
|
169
|
+
// Multi-task plan where T02 checkbox appears after T01's ## Steps heading,
|
|
170
|
+
// which ends the ## Tasks section for extractSection().
|
|
171
|
+
const planContent = `# S01: Demo Slice
|
|
172
|
+
|
|
173
|
+
**Goal:** Build the demo
|
|
174
|
+
**Demo:** Run it
|
|
175
|
+
|
|
176
|
+
## Must-Haves
|
|
177
|
+
- Feature A
|
|
178
|
+
|
|
179
|
+
## Tasks
|
|
180
|
+
- [x] **T01: First task** \`est:30m\`
|
|
181
|
+
Implement the first thing.
|
|
182
|
+
## Steps
|
|
183
|
+
1. Step one
|
|
184
|
+
2. Step two
|
|
185
|
+
## Must-Haves
|
|
186
|
+
- Requirement A
|
|
187
|
+
- [x] **T02: Second task** \`est:1h\`
|
|
188
|
+
Implement the second thing.
|
|
189
|
+
## Steps
|
|
190
|
+
1. Step one
|
|
191
|
+
2. Step two
|
|
192
|
+
`;
|
|
193
|
+
|
|
194
|
+
const plan = parsePlan(planContent);
|
|
195
|
+
const taskIds = plan.tasks.map(t => t.id);
|
|
196
|
+
|
|
197
|
+
assert.ok(taskIds.includes("T01"), "should find T01");
|
|
198
|
+
assert.ok(taskIds.includes("T02"), "should find T02 even when after T01 detail headings");
|
|
199
|
+
assert.equal(plan.tasks.length, 2, "should find exactly 2 tasks");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('Bug 3: task_file_not_in_plan should not fire for T02 in multi-task plan', async () => {
|
|
203
|
+
const { base, mDir } = makeBase();
|
|
204
|
+
writeRoadmap(mDir, `# M001: Multi-Task Test\n\n## Slices\n- [ ] **S01: Slice** \`risk:low\` \`depends:[]\`\n > After this: done\n`);
|
|
205
|
+
|
|
206
|
+
// Plan with interleaved headings (the problematic format)
|
|
207
|
+
const sDir = writeSlice(mDir, "S01", `# S01: Demo Slice
|
|
208
|
+
|
|
209
|
+
**Goal:** Build the demo
|
|
210
|
+
**Demo:** Run it
|
|
211
|
+
|
|
212
|
+
## Must-Haves
|
|
213
|
+
- Feature A
|
|
214
|
+
|
|
215
|
+
## Tasks
|
|
216
|
+
- [x] **T01: First task** \`est:30m\`
|
|
217
|
+
Implement the first thing.
|
|
218
|
+
## Steps
|
|
219
|
+
1. Step one
|
|
220
|
+
## Must-Haves
|
|
221
|
+
- Req A
|
|
222
|
+
- [x] **T02: Second task** \`est:1h\`
|
|
223
|
+
Implement the second thing.
|
|
224
|
+
## Steps
|
|
225
|
+
1. Step one
|
|
226
|
+
`);
|
|
227
|
+
|
|
228
|
+
// Both tasks have summaries on disk
|
|
229
|
+
writeFileSync(join(sDir, "tasks", "T01-SUMMARY.md"), "---\nstatus: done\ncompleted_at: 2026-01-01T00:00:00Z\n---\n# T01\nDone.\n");
|
|
230
|
+
writeFileSync(join(sDir, "tasks", "T02-SUMMARY.md"), "---\nstatus: done\ncompleted_at: 2026-01-01T00:00:00Z\n---\n# T02\nDone.\n");
|
|
231
|
+
|
|
232
|
+
const result = await runGSDDoctor(base, { fix: false });
|
|
233
|
+
|
|
234
|
+
// T02 should NOT be flagged as "not in plan"
|
|
235
|
+
const notInPlan = result.issues.filter(
|
|
236
|
+
i => i.code === "task_file_not_in_plan" && i.message.includes("T02")
|
|
237
|
+
);
|
|
238
|
+
assert.equal(notInPlan.length, 0,
|
|
239
|
+
"should not report T02 as 'not in plan' when it exists in the interleaved plan format");
|
|
240
|
+
|
|
241
|
+
rmSync(base, { recursive: true, force: true });
|
|
242
|
+
});
|
|
243
|
+
});
|