gsd-pi 2.78.1-dev.b0759e59b → 2.78.1-dev.d8826a445
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/headless-recover.d.ts +23 -0
- package/dist/headless-recover.js +93 -0
- package/dist/headless.js +9 -0
- package/dist/help-text.js +1 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +8 -1
- package/dist/resources/extensions/gsd/auto/phases.js +7 -2
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +7 -58
- package/dist/resources/extensions/gsd/auto-post-unit.js +14 -28
- package/dist/resources/extensions/gsd/auto-start.js +1 -8
- package/dist/resources/extensions/gsd/auto-worktree.js +244 -216
- package/dist/resources/extensions/gsd/auto.js +86 -7
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -77
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -16
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -55
- package/dist/resources/extensions/gsd/commands-codebase.js +2 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +5 -5
- package/dist/resources/extensions/gsd/commands-logs.js +2 -2
- package/dist/resources/extensions/gsd/commands-scan.js +2 -2
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +5 -5
- package/dist/resources/extensions/gsd/db-writer.js +106 -95
- package/dist/resources/extensions/gsd/delegation-policy.js +155 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +6 -10
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +2 -2
- package/dist/resources/extensions/gsd/gsd-db.js +268 -8
- package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
- package/dist/resources/extensions/gsd/guided-flow.js +141 -32
- package/dist/resources/extensions/gsd/markdown-renderer.js +14 -51
- package/dist/resources/extensions/gsd/metrics.js +287 -1
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -13
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +5 -2
- package/dist/resources/extensions/gsd/paths.js +114 -9
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -3
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
- package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
- package/dist/resources/extensions/gsd/queue-order.js +6 -1
- package/dist/resources/extensions/gsd/rethink.js +2 -2
- package/dist/resources/extensions/gsd/state.js +91 -372
- package/dist/resources/extensions/gsd/templates/project.md +10 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -5
- package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -12
- package/dist/resources/extensions/gsd/tools/complete-task.js +19 -31
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -5
- package/dist/resources/extensions/gsd/workflow-manifest.js +2 -1
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -21
- package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
- package/dist/resources/extensions/gsd/workflow-reconcile.js +3 -3
- package/dist/resources/extensions/gsd/workspace.js +59 -0
- package/dist/resources/extensions/gsd/worktree-command.js +4 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +15 -2
- package/dist/resources/extensions/gsd/write-intercept.js +3 -3
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/6336.js +1 -0
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- 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/server.js +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/README.md +2 -11
- package/packages/mcp-server/dist/remote-questions.d.ts +27 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
- package/packages/mcp-server/dist/remote-questions.js +28 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -1
- package/packages/mcp-server/dist/server.d.ts +28 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +94 -4
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +6 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +56 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/mcp-server.test.ts +226 -0
- package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
- package/packages/mcp-server/src/remote-questions.test.ts +103 -0
- package/packages/mcp-server/src/remote-questions.ts +35 -0
- package/packages/mcp-server/src/server.ts +129 -6
- package/packages/mcp-server/src/workflow-tools.ts +62 -3
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +13 -2
- package/src/resources/extensions/gsd/auto/phases.ts +8 -2
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +14 -62
- package/src/resources/extensions/gsd/auto-post-unit.ts +15 -27
- package/src/resources/extensions/gsd/auto-start.ts +1 -8
- package/src/resources/extensions/gsd/auto-worktree.ts +286 -251
- package/src/resources/extensions/gsd/auto.ts +102 -7
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +9 -84
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -17
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -55
- package/src/resources/extensions/gsd/commands-codebase.ts +2 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +5 -5
- package/src/resources/extensions/gsd/commands-logs.ts +2 -2
- package/src/resources/extensions/gsd/commands-scan.ts +2 -2
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -5
- package/src/resources/extensions/gsd/db-writer.ts +123 -94
- package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +6 -11
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +2 -2
- package/src/resources/extensions/gsd/gsd-db.ts +269 -8
- package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
- package/src/resources/extensions/gsd/guided-flow.ts +181 -32
- package/src/resources/extensions/gsd/markdown-renderer.ts +13 -64
- package/src/resources/extensions/gsd/metrics.ts +321 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +14 -13
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +5 -2
- package/src/resources/extensions/gsd/paths.ts +122 -9
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -3
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
- package/src/resources/extensions/gsd/queue-order.ts +6 -1
- package/src/resources/extensions/gsd/rethink.ts +2 -2
- package/src/resources/extensions/gsd/state.ts +91 -389
- package/src/resources/extensions/gsd/templates/project.md +10 -0
- package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +14 -14
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +21 -34
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +331 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +6 -7
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +12 -27
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +18 -5
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +10 -38
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +136 -56
- package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +119 -61
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +6 -20
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +14 -15
- package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +3 -23
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +11 -16
- package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
- package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +68 -5
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +15 -36
- package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +15 -15
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +15 -5
- package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +371 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +14 -8
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
- package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +329 -0
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +25 -16
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +150 -7
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +184 -0
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +28 -16
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +4 -0
- package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +10 -56
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +15 -16
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +23 -27
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +13 -14
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +10 -33
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +12 -7
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +26 -3
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +9 -15
- package/src/resources/extensions/gsd/tests/workspace.test.ts +190 -0
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +65 -71
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +26 -151
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +35 -35
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -52
- package/src/resources/extensions/gsd/tests/write-intercept.test.ts +1 -1
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -5
- package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -14
- package/src/resources/extensions/gsd/tools/complete-task.ts +19 -34
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +7 -5
- package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -18
- package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workspace.ts +95 -0
- package/src/resources/extensions/gsd/worktree-command.ts +4 -3
- package/src/resources/extensions/gsd/worktree-resolver.ts +16 -2
- package/src/resources/extensions/gsd/write-intercept.ts +3 -3
- package/dist/web/standalone/.next/server/chunks/8527.js +0 -1
- /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_ssgManifest.js +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// GSD-2 — ID-based path resolution for GSD project files and directories
|
|
1
2
|
/**
|
|
2
3
|
* GSD Paths — ID-based path resolution
|
|
3
4
|
*
|
|
@@ -10,12 +11,13 @@
|
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import { readdirSync, existsSync, realpathSync, Dirent } from "node:fs";
|
|
13
|
-
import { join, dirname, normalize } from "node:path";
|
|
14
|
+
import { join, dirname, normalize, resolve } from "node:path";
|
|
14
15
|
import { homedir } from "node:os";
|
|
15
16
|
import { spawnSync } from "node:child_process";
|
|
16
17
|
import { nativeScanGsdTree, type GsdTreeEntry } from "./native-parser-bridge.js";
|
|
17
18
|
import { DIR_CACHE_MAX } from "./constants.js";
|
|
18
19
|
import { gsdHome } from "./gsd-home.js";
|
|
20
|
+
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
19
21
|
|
|
20
22
|
// ─── Directory Listing Cache ──────────────────────────────────────────────────
|
|
21
23
|
|
|
@@ -127,9 +129,15 @@ function cachedReaddir(dirPath: string): string[] {
|
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
/**
|
|
130
|
-
* Clear the directory listing
|
|
132
|
+
* Clear the volatile directory listing caches.
|
|
131
133
|
* Call after milestone transitions, file creation in planning directories,
|
|
132
134
|
* or at the start/end of a dispatch cycle.
|
|
135
|
+
*
|
|
136
|
+
* NOTE: This does NOT clear gsdRootCache. The project root is stable for
|
|
137
|
+
* the lifetime of a process; clearing it on every agent turn-end caused a
|
|
138
|
+
* 250–2500 ms regression per session (git rev-parse + dir walk per turn).
|
|
139
|
+
* Use _clearGsdRootCache() at session-reset boundaries (workspace switch,
|
|
140
|
+
* process exit) when the project root may genuinely change.
|
|
133
141
|
*/
|
|
134
142
|
export function clearPathCache(): void {
|
|
135
143
|
dirEntryCache.clear();
|
|
@@ -284,13 +292,97 @@ const LEGACY_GSD_ROOT_FILES: Record<GSDRootFileKey, string> = {
|
|
|
284
292
|
|
|
285
293
|
// ─── GSD Root Discovery ───────────────────────────────────────────────────────
|
|
286
294
|
|
|
295
|
+
// Process-lifetime cache for gsdRoot() results.
|
|
296
|
+
// Keys are realpath-normalized (via normCacheKey) so /foo and /foo/ share the
|
|
297
|
+
// same entry and so do case-variant paths on case-insensitive volumes. This
|
|
298
|
+
// normalization is the safety net that prevents cache poisoning from the
|
|
299
|
+
// ~/.gsd walk-up bug (fixed in c46cf4786 + b35e070eb), making it safe to
|
|
300
|
+
// hold this cache for the entire process lifetime.
|
|
301
|
+
// Use _clearGsdRootCache() only at session-reset boundaries (workspace switch,
|
|
302
|
+
// process exit) — NOT inside clearPathCache(), which runs on every agent turn.
|
|
287
303
|
const gsdRootCache = new Map<string, string>();
|
|
288
304
|
|
|
289
|
-
|
|
305
|
+
export interface GsdPathContract {
|
|
306
|
+
/** Canonical repo/project root where authoritative state lives. */
|
|
307
|
+
projectRoot: string;
|
|
308
|
+
/** Current execution root, which may be an auto-worktree. */
|
|
309
|
+
workRoot: string;
|
|
310
|
+
/** Canonical authoritative .gsd directory. */
|
|
311
|
+
projectGsd: string;
|
|
312
|
+
/** Legacy worktree-local .gsd projection directory, when applicable. */
|
|
313
|
+
worktreeGsd: string | null;
|
|
314
|
+
/** Canonical authoritative SQLite DB path. */
|
|
315
|
+
projectDb: string;
|
|
316
|
+
/** True when workRoot is inside a GSD worktree layout. */
|
|
317
|
+
isWorktree: boolean;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function resolveGsdPathContract(
|
|
321
|
+
workRoot: string,
|
|
322
|
+
originalProjectRoot?: string | null,
|
|
323
|
+
): GsdPathContract {
|
|
324
|
+
const resolvedWorkRoot = resolve(workRoot || process.cwd());
|
|
325
|
+
const isWorktree = isGsdWorktreePath(resolvedWorkRoot);
|
|
326
|
+
if (isWorktree && !originalProjectRoot?.trim()) {
|
|
327
|
+
const externalMatch = /[/\\]\.gsd[/\\]projects[/\\][^/\\]+[/\\]worktrees(?:[/\\]|$)/.exec(resolvedWorkRoot);
|
|
328
|
+
if (externalMatch) {
|
|
329
|
+
const worktreesIdx = externalMatch[0].search(/[/\\]worktrees(?:[/\\]|$)/);
|
|
330
|
+
const projectGsd = resolvedWorkRoot.slice(0, externalMatch.index + worktreesIdx);
|
|
331
|
+
return {
|
|
332
|
+
projectRoot: dirname(dirname(projectGsd)),
|
|
333
|
+
workRoot: resolvedWorkRoot,
|
|
334
|
+
projectGsd,
|
|
335
|
+
worktreeGsd: join(resolvedWorkRoot, ".gsd"),
|
|
336
|
+
projectDb: join(projectGsd, "gsd.db"),
|
|
337
|
+
isWorktree,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
const projectRoot = resolve(resolveWorktreeProjectRoot(resolvedWorkRoot, originalProjectRoot));
|
|
342
|
+
const projectGsd = join(projectRoot, ".gsd");
|
|
343
|
+
const worktreeGsd = isWorktree ? join(resolvedWorkRoot, ".gsd") : null;
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
projectRoot,
|
|
347
|
+
workRoot: resolvedWorkRoot,
|
|
348
|
+
projectGsd,
|
|
349
|
+
worktreeGsd,
|
|
350
|
+
projectDb: join(projectGsd, "gsd.db"),
|
|
351
|
+
isWorktree,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Invalidate the gsdRoot cache.
|
|
357
|
+
* Use ONLY at session-reset boundaries: workspace switch, process exit, or
|
|
358
|
+
* any context where the project root itself may genuinely change.
|
|
359
|
+
* Do NOT call this on every agent turn — use clearPathCache() for volatile
|
|
360
|
+
* directory listing invalidation instead.
|
|
361
|
+
*/
|
|
290
362
|
export function _clearGsdRootCache(): void {
|
|
291
363
|
gsdRootCache.clear();
|
|
292
364
|
}
|
|
293
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Resolve a path to its canonical real path using the native resolver.
|
|
368
|
+
* On macOS case-insensitive (HFS+/APFS) volumes, realpathSync.native normalizes
|
|
369
|
+
* case — ensuring that /foo/Bar and /foo/bar resolve to the same string.
|
|
370
|
+
* Falls back to resolve(p) for non-existent paths.
|
|
371
|
+
*
|
|
372
|
+
* Use this helper everywhere a path is used as an identity/cache key so that
|
|
373
|
+
* all callers agree on the canonical form.
|
|
374
|
+
*/
|
|
375
|
+
export function normalizeRealPath(p: string): string {
|
|
376
|
+
try { return realpathSync.native(p); } catch { return resolve(p); }
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** Normalize a path for use as a gsdRootCache key (realpath + trailing-slash strip). */
|
|
380
|
+
function normCacheKey(p: string): string {
|
|
381
|
+
const r = normalizeRealPath(p);
|
|
382
|
+
const s = r.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
383
|
+
return process.platform === "win32" ? s.toLowerCase() : s;
|
|
384
|
+
}
|
|
385
|
+
|
|
294
386
|
/**
|
|
295
387
|
* Resolve the `.gsd` directory for a given project base path.
|
|
296
388
|
*
|
|
@@ -300,13 +392,19 @@ export function _clearGsdRootCache(): void {
|
|
|
300
392
|
* 3. Walk up from basePath — handles moved .gsd in an ancestor (bounded by git root)
|
|
301
393
|
* 4. basePath/.gsd — creation fallback (init scenario)
|
|
302
394
|
*
|
|
303
|
-
* Result is cached per basePath for the process lifetime.
|
|
395
|
+
* Result is cached per normalized basePath for the process lifetime.
|
|
396
|
+
* Keys are realpath-normalized so /foo and /foo/ share the same cache entry.
|
|
304
397
|
*/
|
|
305
398
|
export function gsdRoot(basePath: string): string {
|
|
306
|
-
const
|
|
399
|
+
const cacheKey = normCacheKey(basePath);
|
|
400
|
+
const cached = gsdRootCache.get(cacheKey);
|
|
307
401
|
if (cached) return cached;
|
|
308
402
|
|
|
309
|
-
|
|
403
|
+
// Canonicalize result via realpath before asserting and caching so that
|
|
404
|
+
// callers always receive a canonical path regardless of whether probeGsdRoot
|
|
405
|
+
// returned a path through a symlink. Without this, the cached value can
|
|
406
|
+
// diverge from other realpath-normalized paths (e.g. workspace.identityKey).
|
|
407
|
+
const result = normalizeRealPath(probeGsdRoot(basePath));
|
|
310
408
|
|
|
311
409
|
// Defense-in-depth: if basePath resolves to the user's home directory and
|
|
312
410
|
// the result equals gsdHome(), refuse — project-scoped writes must never
|
|
@@ -314,7 +412,7 @@ export function gsdRoot(basePath: string): string {
|
|
|
314
412
|
// valid (their basePath does not equal homedir).
|
|
315
413
|
assertNotGlobalGsdHome(basePath, result);
|
|
316
414
|
|
|
317
|
-
gsdRootCache.set(
|
|
415
|
+
gsdRootCache.set(cacheKey, result);
|
|
318
416
|
return result;
|
|
319
417
|
}
|
|
320
418
|
|
|
@@ -378,6 +476,9 @@ function isInsideGsdWorktree(p: string): boolean {
|
|
|
378
476
|
}
|
|
379
477
|
|
|
380
478
|
function probeGsdRoot(rawBasePath: string): string {
|
|
479
|
+
const contract = resolveGsdPathContract(rawBasePath);
|
|
480
|
+
if (contract.isWorktree) return contract.projectGsd;
|
|
481
|
+
|
|
381
482
|
// 1. Fast path — check the input path directly
|
|
382
483
|
const local = join(rawBasePath, ".gsd");
|
|
383
484
|
if (existsSync(local)) return local;
|
|
@@ -412,9 +513,21 @@ function probeGsdRoot(rawBasePath: string): string {
|
|
|
412
513
|
}
|
|
413
514
|
} catch { /* git not available */ }
|
|
414
515
|
|
|
516
|
+
// Compute gsdHome once for the skip-check used in steps 2 and 3.
|
|
517
|
+
const normPath = (p: string): string => {
|
|
518
|
+
let r: string;
|
|
519
|
+
try { r = realpathSync.native(p); } catch { r = p; }
|
|
520
|
+
const s = r.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
521
|
+
return process.platform === "win32" ? s.toLowerCase() : s;
|
|
522
|
+
};
|
|
523
|
+
let gsdHomeNorm: string;
|
|
524
|
+
try { gsdHomeNorm = normPath(gsdHome()); } catch { gsdHomeNorm = ""; }
|
|
525
|
+
|
|
415
526
|
if (gitRoot) {
|
|
416
527
|
const candidate = join(gitRoot, ".gsd");
|
|
417
|
-
if
|
|
528
|
+
// Skip if the candidate resolves to the global GSD home — a subdir basePath
|
|
529
|
+
// must not be anchored to ~/.gsd just because $HOME is a git repo.
|
|
530
|
+
if (existsSync(candidate) && normPath(candidate) !== gsdHomeNorm) return candidate;
|
|
418
531
|
}
|
|
419
532
|
|
|
420
533
|
// 3. Walk up from basePath to the git root (only if we are in a subdirectory)
|
|
@@ -422,7 +535,7 @@ function probeGsdRoot(rawBasePath: string): string {
|
|
|
422
535
|
let cur = dirname(basePath);
|
|
423
536
|
while (cur !== basePath) {
|
|
424
537
|
const candidate = join(cur, ".gsd");
|
|
425
|
-
if (existsSync(candidate)) return candidate;
|
|
538
|
+
if (existsSync(candidate) && normPath(candidate) !== gsdHomeNorm) return candidate;
|
|
426
539
|
if (cur === gitRoot) break;
|
|
427
540
|
basePath = cur;
|
|
428
541
|
cur = dirname(cur);
|
|
@@ -28,7 +28,7 @@ This unit runs under the `planning-dispatch` tools-policy: you may use the `suba
|
|
|
28
28
|
- **Touched auth, network, parsing, file IO, shell exec, or crypto** → dispatch the **security** agent for an OWASP-style audit.
|
|
29
29
|
- **Added or modified tests** → dispatch the **tester** agent to assess coverage gaps relative to the slice plan.
|
|
30
30
|
|
|
31
|
-
Subagents read the diff and report findings — they do **not** write user source. You remain responsible for acting on their feedback before calling `
|
|
31
|
+
Subagents read the diff and report findings — they do **not** write user source. You remain responsible for acting on their feedback before calling `gsd_slice_complete` with `milestoneId` and `sliceId`.
|
|
32
32
|
|
|
33
33
|
Then:
|
|
34
34
|
1. Use the **Slice Summary** and **UAT** output templates from the inlined context above
|
|
@@ -37,11 +37,11 @@ Then:
|
|
|
37
37
|
4. If the slice plan includes observability/diagnostic surfaces, confirm they work. Skip this for simple slices that don't have observability sections.
|
|
38
38
|
5. Address every gate listed in the **Gates to Close** section above — each gate maps to a specific slice-summary section the handler inspects (for example, Q8 maps to **Operational Readiness**: health signal, failure signal, recovery procedure, and monitoring gaps). Leaving a section empty records the gate as `omitted`.
|
|
39
39
|
6. If this slice produced evidence that a requirement changed status (Active → Validated, Active → Deferred, etc.), call `gsd_requirement_update` with the requirement ID, updated `status`, and `validation` evidence. Do NOT write `.gsd/REQUIREMENTS.md` directly — the engine renders it from the database.
|
|
40
|
-
7. Prepare the slice completion content you will pass to `
|
|
40
|
+
7. Prepare the slice completion content you will pass to `gsd_slice_complete` using the camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`. Do **not** manually write `{{sliceSummaryPath}}`. Do **not** manually write `{{sliceUatPath}}` — the DB-backed tool is the canonical write path for both artifacts.
|
|
41
41
|
8. Draft the UAT content you will pass as `uatContent` — a concrete UAT script with real test cases derived from the slice plan and task summaries. Include preconditions, numbered steps with expected outcomes, and edge cases. This must NOT be a placeholder or generic template — tailor every test case to what this slice actually built. Fill the `UAT Type` and `Not Proven By This UAT` sections explicitly so the artifact states what class of acceptance it covers and what still remains unproven (e.g. live integration paths, performance under load, scenarios deferred to a later slice).
|
|
42
42
|
9. Review task summaries for `key_decisions`. For each significant decision, call `capture_thought` with `category: "architecture"` (or `"pattern"`) and a `structuredFields` payload of `{ scope, decision, choice, rationale, made_by: "agent", revisable }`.
|
|
43
43
|
10. Review task summaries for patterns, gotchas, or non-obvious lessons learned. For each one that would save future agents from repeating investigation, call `capture_thought` with the matching category (`gotcha`, `convention`, `pattern`, `environment`). The memory store is the single source of truth (ADR-013); do not append to `.gsd/DECISIONS.md` or `.gsd/KNOWLEDGE.md` directly.
|
|
44
|
-
11. Call `
|
|
44
|
+
11. Call `gsd_slice_complete` with the camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`, plus any optional enrichment fields you have. Do NOT manually mark the roadmap checkbox — the tool writes to the DB, renders `{{sliceSummaryPath}}` and `{{sliceUatPath}}`, and updates the ROADMAP.md projection automatically.
|
|
45
45
|
12. Do not run git commands — the system commits your changes and handles any merge after this unit succeeds.
|
|
46
46
|
13. Update `.gsd/PROJECT.md` if it exists — refresh current state if needed: use the `write` tool with `path: ".gsd/PROJECT.md"` and `content` containing the full updated document reflecting current project state. Do NOT use the `edit` tool for this — PROJECT.md is a full-document refresh.
|
|
47
47
|
|
|
@@ -49,6 +49,6 @@ Then:
|
|
|
49
49
|
|
|
50
50
|
**File system safety:** Task summaries are preloaded in the inlined context above. Task artifacts use a **flat file layout** — files such as `T01-SUMMARY.md` and `T02-SUMMARY.md` live directly inside the `tasks/` directory, not inside per-task subdirectories like `tasks/T01/SUMMARY.md`. If you need to re-read any of them, use `find .gsd/milestones/{{milestoneId}}/slices/{{sliceId}}/tasks -name "*-SUMMARY.md"` to list file paths first. Never use `tasks/*/SUMMARY.md`, and never pass `{{slicePath}}` or any other directory path directly to the `read` tool. The `read` tool only accepts file paths, not directories.
|
|
51
51
|
|
|
52
|
-
**You MUST call `
|
|
52
|
+
**You MUST call `gsd_slice_complete` with the slice summary and UAT content before finishing. The tool persists to both DB and disk and renders `{{sliceSummaryPath}}` and `{{sliceUatPath}}` automatically.**
|
|
53
53
|
|
|
54
54
|
When done, say: "Slice {{sliceId}} complete."
|
|
@@ -85,14 +85,14 @@ Then:
|
|
|
85
85
|
17. If you made an architectural, pattern, library, or observability decision during this task that downstream work should know about, call `capture_thought` with `category: "architecture"` (or `"pattern"`). For decisions, populate `structuredFields` with `{ scope, decision, choice, rationale, made_by: "agent", revisable }` so future projection back to a human-visible decisions register stays lossless. Not every task produces decisions — only capture when a meaningful choice was made.
|
|
86
86
|
18. If you discover a non-obvious rule, recurring gotcha, or useful pattern during execution, call `capture_thought` with `category: "gotcha"`, `"convention"`, `"pattern"`, or `"environment"` as appropriate. Only capture entries that would save future agents from repeating your investigation — don't capture obvious things. The memory store is the single source of truth for cross-session knowledge (ADR-013); do not append to `.gsd/DECISIONS.md` or `.gsd/KNOWLEDGE.md` directly.
|
|
87
87
|
19. Read the template at `~/.gsd/agent/extensions/gsd/templates/task-summary.md`
|
|
88
|
-
20. Use that template to prepare the completion content you will pass to `
|
|
89
|
-
21. Call `
|
|
88
|
+
20. Use that template to prepare the completion content you will pass to `gsd_task_complete` using the camelCase fields `milestoneId`, `sliceId`, `taskId`, `oneLiner`, `narrative`, `verification`, and `verificationEvidence`. Do **not** manually write `{{taskSummaryPath}}` — the DB-backed tool is the canonical write path and renders the summary file for you.
|
|
89
|
+
21. Call `gsd_task_complete` with milestoneId, sliceId, taskId, and the completion fields derived from the template. This is your final required step — do NOT manually edit PLAN.md checkboxes. The tool marks the task complete, updates the DB, renders `{{taskSummaryPath}}`, and updates PLAN.md automatically.
|
|
90
90
|
22. Do not run git commands — the system reads your task summary after completion and creates a meaningful commit from it (type inferred from title, message from your one-liner, key files from frontmatter). Write a clear, specific one-liner in the summary — it becomes the commit message.
|
|
91
91
|
|
|
92
92
|
All work stays in your working directory: `{{workingDirectory}}`.
|
|
93
93
|
|
|
94
94
|
**Autonomous execution:** Do not call `ask_user_questions` or `secure_env_collect`. You are running in auto-mode — there is no human available to answer questions. Make reasonable assumptions and document them in the task summary. If a decision genuinely requires human input, note it in the summary and proceed with the best available option.
|
|
95
95
|
|
|
96
|
-
**You MUST call `
|
|
96
|
+
**You MUST call `gsd_task_complete` before finishing. Do not manually write `{{taskSummaryPath}}`.**
|
|
97
97
|
|
|
98
98
|
When done, say: "Task {{taskId}} complete."
|
|
@@ -12,6 +12,13 @@ Discuss milestone {{milestoneId}} ("{{milestoneTitle}}"). Identify gray areas, a
|
|
|
12
12
|
|
|
13
13
|
{{fastPathInstruction}}
|
|
14
14
|
|
|
15
|
+
### Read project shape
|
|
16
|
+
|
|
17
|
+
Before your first question round, read `.gsd/PROJECT.md` and look for `## Project Shape` → `**Complexity:**`. The verdict is either **`simple`** or **`complex`** (default to `complex` if PROJECT.md is missing the section, predates this convention, or the value is unclear). The verdict scales the rest of this stage:
|
|
18
|
+
|
|
19
|
+
- **`simple`** — favor 1–2 plain-text question rounds. Skip the parallel-research investigation. Skip `ask_user_questions` unless presenting concrete alternatives.
|
|
20
|
+
- **`complex`** — full investigation, 3–4-option structured questions, multi-round.
|
|
21
|
+
|
|
15
22
|
### Before your first question round
|
|
16
23
|
|
|
17
24
|
Do a lightweight targeted investigation so your questions are grounded in reality:
|
|
@@ -36,7 +43,7 @@ Ask **1–3 questions per round**. Keep each question focused on one of:
|
|
|
36
43
|
|
|
37
44
|
**Never fabricate or simulate user input.** Never generate fake transcript markers like `[User]`, `[Human]`, or `User:`. Ask one question round, then wait for the user's actual response before continuing.
|
|
38
45
|
|
|
39
|
-
**If `{{structuredQuestionsAvailable}}` is `true`:** use `ask_user_questions` for each round. 1–3 questions per call, each as a separate question object. Keep option labels short (3–5 words).
|
|
46
|
+
**If `{{structuredQuestionsAvailable}}` is `true`:** use `ask_user_questions` for each round. 1–3 questions per call, each as a separate question object. Keep option labels short (3–5 words). In **`complex`** mode, each multi-choice question MUST present **3 or 4 concrete, researched options** plus a final **"Other — let me discuss"** option; options must be grounded in the investigation above (codebase signals, library docs, prior `.gsd/` artifacts), not generic placeholders. In **`simple`** mode, 2 options is fine when alternatives are genuinely binary. Binary depth-check / wrap-up gates are exempt from the 3-or-4 rule. When the user picks "Other — let me discuss" or writes a long freeform answer, switch to plain text follow-up for that thread before resuming structured questions. **IMPORTANT: Call `ask_user_questions` exactly once per turn. Never make multiple calls with the same or overlapping questions — wait for the user's response before asking the next round.**
|
|
40
47
|
|
|
41
48
|
**If `{{structuredQuestionsAvailable}}` is `false`:** ask questions in plain text. Keep each round to 1–3 focused questions. Wait for answers before asking the next round.
|
|
42
49
|
|
|
@@ -26,6 +26,18 @@ Ask the user a single freeform question in plain text, not structured: **"What d
|
|
|
26
26
|
|
|
27
27
|
Wait for their response. This grounds every follow-up in their own terminology.
|
|
28
28
|
|
|
29
|
+
### Classify project shape
|
|
30
|
+
|
|
31
|
+
After the opening answer, classify the project as **`simple`** or **`complex`** before continuing. Print the verdict in chat as one line: `Project shape: simple` or `Project shape: complex` followed by a one-line rationale.
|
|
32
|
+
|
|
33
|
+
**`simple`** — most of these apply: single primary user (the user themselves or one immediate team), no external integrations beyond well-known SDKs/libs, greenfield or self-contained, scope describable in 1–2 sentences without ambiguity, no compliance/regulatory needs, ≤5 distinct capabilities.
|
|
34
|
+
|
|
35
|
+
**`complex`** — any of these apply: multi-user with roles/permissions, non-trivial brownfield codebase, external integrations with auth/data exchange, compliance/security/regulated domain (PII, payments, healthcare), >5 capabilities or unclear scope, cross-team/cross-org coordination, novel domain where assumptions need validation.
|
|
36
|
+
|
|
37
|
+
**Default to `complex` when uncertain.** The user can override the verdict in plain text; if they do, accept it and proceed.
|
|
38
|
+
|
|
39
|
+
The verdict drives the rest of this stage and gets persisted to PROJECT.md → `## Project Shape`. Downstream stages (`discuss-requirements`, `discuss-milestone`, `discuss-slice`) read it from there.
|
|
40
|
+
|
|
29
41
|
### Before deeper rounds
|
|
30
42
|
|
|
31
43
|
Do a lightweight targeted investigation so your questions are grounded in reality:
|
|
@@ -50,9 +62,11 @@ Ask **1–3 questions per round**. Each round targets one of:
|
|
|
50
62
|
|
|
51
63
|
**Never fabricate or simulate user input.** Never generate fake transcript markers like `[User]`, `[Human]`, or `User:`. Ask one question round, then wait for the user's actual response before continuing.
|
|
52
64
|
|
|
53
|
-
**
|
|
65
|
+
**Cadence is shape-dependent:**
|
|
66
|
+
- **`simple`** — favor 1–2 plain-text rounds. Skip `ask_user_questions` unless you are presenting concrete alternatives. Get to the depth checklist fast.
|
|
67
|
+
- **`complex`** — full investigation, multiple rounds, structured questions when meaningful alternatives exist.
|
|
54
68
|
|
|
55
|
-
**If `{{structuredQuestionsAvailable}}` is `true` and you use `ask_user_questions`:** ask 1–3 questions per call. Every question object MUST include a stable lowercase `id`. Keep option labels short (3–5 words).
|
|
69
|
+
**If `{{structuredQuestionsAvailable}}` is `true` and you use `ask_user_questions`:** ask 1–3 questions per call. Every question object MUST include a stable lowercase `id`. Keep option labels short (3–5 words). In **`complex`** mode, each multi-choice question MUST present **3 or 4 concrete, researched options** plus a final **"Other — let me discuss"** option; options must be grounded in your investigation (codebase signals, library docs, prior `.gsd/` artifacts), not generic placeholders. In **`simple`** mode, 2 options is fine. Binary depth-check / wrap-up gates are exempt from the 3-or-4 rule. Wait for each tool result before asking the next round.
|
|
56
70
|
|
|
57
71
|
**If `{{structuredQuestionsAvailable}}` is `false`:** ask questions in plain text. Keep each round to 1–3 focused questions.
|
|
58
72
|
|
|
@@ -126,8 +140,9 @@ Once the user confirms depth:
|
|
|
126
140
|
|
|
127
141
|
1. Use the **Project** output template (inlined above).
|
|
128
142
|
2. Call `gsd_summary_save` with `artifact_type: "PROJECT"` and the full project markdown as `content`; omit `milestone_id`. The tool writes `.gsd/PROJECT.md` to disk and persists to DB. Preserve the user's exact terminology, emphasis, and framing.
|
|
129
|
-
3. The `##
|
|
130
|
-
4. The `##
|
|
131
|
-
5.
|
|
132
|
-
6.
|
|
133
|
-
7.
|
|
143
|
+
3. The `## Project Shape` section MUST contain `**Complexity:** simple` or `**Complexity:** complex` (matching the verdict you announced) plus a one-line `**Why:**` rationale. Downstream stages read this line.
|
|
144
|
+
4. The `## Capability Contract` section MUST reference `.gsd/REQUIREMENTS.md` — that file does not yet exist; the next stage (`discuss-requirements`) will produce it.
|
|
145
|
+
5. The `## Milestone Sequence` MUST list at least M001 with title and one-liner. Subsequent milestones may be listed as known intents; they will be elaborated in their own discuss-milestone stages.
|
|
146
|
+
6. Do NOT use `artifact_type: "CONTEXT"` and do NOT pass `milestone_id: "PROJECT"`; that creates a fake milestone named PROJECT.
|
|
147
|
+
7. {{commitInstruction}}
|
|
148
|
+
8. Say exactly: `"Project context written."` — nothing else.
|
|
@@ -21,9 +21,13 @@ Before your first action, print this banner verbatim in chat:
|
|
|
21
21
|
## Pre-flight
|
|
22
22
|
|
|
23
23
|
1. Read `.gsd/PROJECT.md` end-to-end. If it does not exist, STOP and emit: `"PROJECT.md missing — run discuss-project first."`
|
|
24
|
-
2. Extract: Core Value, Anti-goals, Constraints, Milestone Sequence.
|
|
24
|
+
2. Extract: Core Value, Anti-goals, Constraints, Milestone Sequence, and the project shape verdict — read the `## Project Shape` section and look for `**Complexity:**` (verdict is either `simple` or `complex`; default to `complex` if the section is missing or unclear).
|
|
25
25
|
3. Check for existing `.gsd/REQUIREMENTS.md` — if present, this is a refinement pass, not a fresh write. Read existing requirements and treat them as the working set.
|
|
26
26
|
|
|
27
|
+
**Shape-dependent cadence:**
|
|
28
|
+
- **`simple`** — favor a single fast pass: extract requirements directly from PROJECT.md, ask 1–2 plain-text clarifying questions only if a class or status assignment is genuinely ambiguous, then write REQUIREMENTS.md.
|
|
29
|
+
- **`complex`** — full multi-round questioning with structured 3–4-option questions where alternatives matter.
|
|
30
|
+
|
|
27
31
|
---
|
|
28
32
|
|
|
29
33
|
## Interview Protocol
|
|
@@ -51,7 +55,7 @@ Ask **1–3 questions per round**. Each round targets one dimension:
|
|
|
51
55
|
|
|
52
56
|
**Never fabricate or simulate user input.** Wait for actual responses.
|
|
53
57
|
|
|
54
|
-
**If `{{structuredQuestionsAvailable}}` is `true`:** use `ask_user_questions`. Every question object MUST include a stable lowercase `id`. For class assignments, present the allowed classes as multi-select options. For status, present the four statuses as exclusive options. Ask 1–3 questions per call. Wait for each tool result before asking the next round.
|
|
58
|
+
**If `{{structuredQuestionsAvailable}}` is `true`:** use `ask_user_questions`. Every question object MUST include a stable lowercase `id`. For class assignments, present the allowed classes as multi-select options. For status, present the four statuses as exclusive options. In **`complex`** mode, any free-form question MUST present **3 or 4 concrete, researched options** plus a final **"Other — let me discuss"** option grounded in the investigation above. The class-assignment and status questions are exempt — they have fixed enumerations. Ask 1–3 questions per call. Wait for each tool result before asking the next round.
|
|
55
59
|
|
|
56
60
|
**If `{{structuredQuestionsAvailable}}` is `false`:** ask in plain text. Keep each round to 1–3 questions.
|
|
57
61
|
|
|
@@ -8,6 +8,13 @@ Your goal is **not** to center the discussion on tech stack trivia, naming conve
|
|
|
8
8
|
|
|
9
9
|
## Interview Protocol
|
|
10
10
|
|
|
11
|
+
### Read project shape
|
|
12
|
+
|
|
13
|
+
Before your first question round, read `.gsd/PROJECT.md` and look for `## Project Shape` → `**Complexity:**`. The verdict is either **`simple`** or **`complex`** (default to `complex` if the section is missing or unclear).
|
|
14
|
+
|
|
15
|
+
- **`simple`** — favor 1–2 plain-text rounds, write the slice context fast. Skip parallel-research investigation.
|
|
16
|
+
- **`complex`** — full investigation with structured 3–4-option questions.
|
|
17
|
+
|
|
11
18
|
### Before your first question round
|
|
12
19
|
|
|
13
20
|
Do a lightweight targeted investigation so your questions are grounded in reality:
|
|
@@ -24,7 +31,7 @@ Do **not** go deep — just enough that your questions reflect what's actually t
|
|
|
24
31
|
|
|
25
32
|
**Never fabricate or simulate user input.** Never generate fake transcript markers like `[User]`, `[Human]`, or `User:`. Ask one question round, then wait for the user's actual response before continuing.
|
|
26
33
|
|
|
27
|
-
**If `{{structuredQuestionsAvailable}}` is `true`:** Ask **1–3 questions per round** using `ask_user_questions`. **Call `ask_user_questions` exactly once per turn — never make multiple calls with the same or overlapping questions. Wait for the user's response before asking the next round.**
|
|
34
|
+
**If `{{structuredQuestionsAvailable}}` is `true`:** Ask **1–3 questions per round** using `ask_user_questions`. In **`complex`** mode, each multi-choice question MUST present **3 or 4 concrete, researched options** plus a final **"Other — let me discuss"** option; options must be grounded in the investigation above (codebase signals, library docs, prior `.gsd/` artifacts), not generic placeholders. In **`simple`** mode, 2 options is fine. Binary wrap-up gates are exempt from the 3-or-4 rule. **Call `ask_user_questions` exactly once per turn — never make multiple calls with the same or overlapping questions. Wait for the user's response before asking the next round.**
|
|
28
35
|
**If `{{structuredQuestionsAvailable}}` is `false`:** Ask **1–3 questions per round** in plain text. Number them and wait for the user's response before asking the next round.
|
|
29
36
|
Keep each question focused on one of:
|
|
30
37
|
- **UX and user-facing behaviour** — what does the user see, click, trigger, or experience?
|
|
@@ -10,6 +10,12 @@ All relevant context has been preloaded below — start working immediately with
|
|
|
10
10
|
|
|
11
11
|
{{inlinedContext}}
|
|
12
12
|
|
|
13
|
+
## Already Planned? Soft Brake
|
|
14
|
+
|
|
15
|
+
If `{{outputPath}}` already exists on disk with at least one slice line (e.g. `- [ ] **S01:`) AND `gsd_query` reports slice rows for this milestone, a prior `gsd_plan_milestone` call already persisted the plan. Do **not** re-call `gsd_plan_milestone` — its UPSERT would overwrite the existing plan with whatever you reconstruct, which is unsafe when you don't have the original decomposition reasoning. Skip directly to the ready phrase at the end of this prompt.
|
|
16
|
+
|
|
17
|
+
If only the file exists (no DB rows) or only DB rows exist (no file), the prior write was incomplete — proceed with planning as normal so the tool reconciles both.
|
|
18
|
+
|
|
13
19
|
## Your Role in the Pipeline
|
|
14
20
|
|
|
15
21
|
You are the first deep look at this milestone. You have full tool access — explore the codebase, look up docs, investigate technology choices. Your job is to understand the landscape and then strategically decompose the work into demoable slices.
|
|
@@ -13,6 +13,7 @@ import { join } from "node:path";
|
|
|
13
13
|
import { gsdRoot } from "./paths.js";
|
|
14
14
|
import { milestoneIdSort } from "./milestone-ids.js";
|
|
15
15
|
import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
|
|
16
|
+
import { isDbAvailable, setMilestoneQueueOrder } from "./gsd-db.js";
|
|
16
17
|
|
|
17
18
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -63,9 +64,13 @@ export function loadQueueOrder(basePath: string): string[] | null {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
|
-
* Save a custom queue order
|
|
67
|
+
* Save a custom queue order. The DB sequence is canonical when a DB
|
|
68
|
+
* connection is open; QUEUE-ORDER.json remains a compatibility projection.
|
|
67
69
|
*/
|
|
68
70
|
export function saveQueueOrder(basePath: string, order: string[]): void {
|
|
71
|
+
if (isDbAvailable()) {
|
|
72
|
+
setMilestoneQueueOrder(order);
|
|
73
|
+
}
|
|
69
74
|
const data: QueueOrderFile = {
|
|
70
75
|
order,
|
|
71
76
|
updatedAt: new Date().toISOString(),
|
|
@@ -20,7 +20,7 @@ import { getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
|
|
|
20
20
|
import { buildExistingMilestonesContext } from "./guided-flow-queue.js";
|
|
21
21
|
import { loadPrompt } from "./prompt-loader.js";
|
|
22
22
|
import { isGsdGitignored } from "./gitignore.js";
|
|
23
|
-
import {
|
|
23
|
+
import { currentDirectoryRoot } from "./commands/context.js";
|
|
24
24
|
|
|
25
25
|
// ─── Entry Point ──────────────────────────────────────────────────────────────
|
|
26
26
|
|
|
@@ -34,7 +34,7 @@ export async function handleRethink(
|
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const basePath =
|
|
37
|
+
const basePath = currentDirectoryRoot();
|
|
38
38
|
const root = gsdRoot(basePath);
|
|
39
39
|
if (!existsSync(root)) {
|
|
40
40
|
ctx.ui.notify("No GSD project found. Run /gsd init first.", "warning");
|