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
|
@@ -11,6 +11,16 @@
|
|
|
11
11
|
|
|
12
12
|
{{theOneThingThatMustWorkEvenIfEverythingElseIsCut}}
|
|
13
13
|
|
|
14
|
+
## Project Shape
|
|
15
|
+
|
|
16
|
+
<!-- Drives questioning depth in downstream stages. `simple` → short plain-text
|
|
17
|
+
rounds, fast PROJECT/CONTEXT/REQUIREMENTS writes. `complex` → researched
|
|
18
|
+
3–4-option questions with an "Other — let me discuss" hatch.
|
|
19
|
+
Default to `complex` when uncertain. -->
|
|
20
|
+
|
|
21
|
+
- **Complexity:** {{simple | complex}}
|
|
22
|
+
- **Why:** {{one-line rationale citing the signals that decided it}}
|
|
23
|
+
|
|
14
24
|
## Current State
|
|
15
25
|
|
|
16
26
|
{{whatHasBeenBuiltSoFar — what works, what exists, what's deployed}}
|
|
@@ -35,7 +35,7 @@ import { _setAutoActiveForTest } from '../auto.ts';
|
|
|
35
35
|
// Reset all relevant state before and after each test.
|
|
36
36
|
function resetState(): void {
|
|
37
37
|
_setAutoActiveForTest(false);
|
|
38
|
-
clearDiscussionFlowState();
|
|
38
|
+
clearDiscussionFlowState(process.cwd());
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
@@ -51,7 +51,7 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
51
51
|
_setAutoActiveForTest(true);
|
|
52
52
|
|
|
53
53
|
// Before mark: blocked
|
|
54
|
-
const snapshotBefore = loadWriteGateSnapshot();
|
|
54
|
+
const snapshotBefore = loadWriteGateSnapshot(process.cwd());
|
|
55
55
|
const beforeResult = shouldBlockContextArtifactSaveInSnapshot(
|
|
56
56
|
snapshotBefore,
|
|
57
57
|
'CONTEXT',
|
|
@@ -61,10 +61,10 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
61
61
|
assert.strictEqual(beforeResult.block, true, 'should block before markDepthVerified');
|
|
62
62
|
|
|
63
63
|
// Simulate what the dispatch rule now does in auto-mode
|
|
64
|
-
markDepthVerified('M001');
|
|
64
|
+
markDepthVerified('M001', process.cwd());
|
|
65
65
|
|
|
66
66
|
// After mark: unblocked
|
|
67
|
-
const snapshotAfter = loadWriteGateSnapshot();
|
|
67
|
+
const snapshotAfter = loadWriteGateSnapshot(process.cwd());
|
|
68
68
|
const afterResult = shouldBlockContextArtifactSaveInSnapshot(
|
|
69
69
|
snapshotAfter,
|
|
70
70
|
'CONTEXT',
|
|
@@ -87,7 +87,7 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
87
87
|
assert.strictEqual(beforeResult.block, true, 'write should be blocked before markDepthVerified');
|
|
88
88
|
|
|
89
89
|
// Simulate dispatch rule auto-mark
|
|
90
|
-
markDepthVerified('M001');
|
|
90
|
+
markDepthVerified('M001', process.cwd());
|
|
91
91
|
|
|
92
92
|
// After mark: unblocked
|
|
93
93
|
const afterResult = shouldBlockContextWrite('write', contextPath, 'M001');
|
|
@@ -109,8 +109,8 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
109
109
|
// the dispatch-site call site is safe regardless of prior session state.
|
|
110
110
|
test('Test 3: session_switch ordering — clearDiscussionFlowState clears mark; dispatch-site call re-establishes it', () => {
|
|
111
111
|
// Simulate a mark from a prior session
|
|
112
|
-
markDepthVerified('M001');
|
|
113
|
-
let snapshot = loadWriteGateSnapshot();
|
|
112
|
+
markDepthVerified('M001', process.cwd());
|
|
113
|
+
let snapshot = loadWriteGateSnapshot(process.cwd());
|
|
114
114
|
assert.strictEqual(
|
|
115
115
|
isMilestoneDepthVerifiedInSnapshot(snapshot, 'M001'),
|
|
116
116
|
true,
|
|
@@ -119,8 +119,8 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
119
119
|
|
|
120
120
|
// session_switch fires clearDiscussionFlowState() — this is exactly what
|
|
121
121
|
// register-hooks.ts:106 does
|
|
122
|
-
clearDiscussionFlowState();
|
|
123
|
-
snapshot = loadWriteGateSnapshot();
|
|
122
|
+
clearDiscussionFlowState(process.cwd());
|
|
123
|
+
snapshot = loadWriteGateSnapshot(process.cwd());
|
|
124
124
|
assert.strictEqual(
|
|
125
125
|
isMilestoneDepthVerifiedInSnapshot(snapshot, 'M001'),
|
|
126
126
|
false,
|
|
@@ -130,9 +130,9 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
130
130
|
// Now the dispatch rule fires (after session_switch cleared state)
|
|
131
131
|
// and re-establishes the mark for the new session
|
|
132
132
|
_setAutoActiveForTest(true);
|
|
133
|
-
markDepthVerified('M001'); // this is what the dispatch rule does
|
|
133
|
+
markDepthVerified('M001', process.cwd()); // this is what the dispatch rule does
|
|
134
134
|
|
|
135
|
-
snapshot = loadWriteGateSnapshot();
|
|
135
|
+
snapshot = loadWriteGateSnapshot(process.cwd());
|
|
136
136
|
assert.strictEqual(
|
|
137
137
|
isMilestoneDepthVerifiedInSnapshot(snapshot, 'M001'),
|
|
138
138
|
true,
|
|
@@ -158,7 +158,7 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
158
158
|
|
|
159
159
|
// CONTEXT artifact save is still blocked
|
|
160
160
|
const snapshotResult = shouldBlockContextArtifactSaveInSnapshot(
|
|
161
|
-
loadWriteGateSnapshot(),
|
|
161
|
+
loadWriteGateSnapshot(process.cwd()),
|
|
162
162
|
'CONTEXT',
|
|
163
163
|
'M002',
|
|
164
164
|
null,
|
|
@@ -238,7 +238,7 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
238
238
|
);
|
|
239
239
|
|
|
240
240
|
// ── Deep auto-mode case: the user-facing approval gate must stay closed ──
|
|
241
|
-
clearDiscussionFlowState();
|
|
241
|
+
clearDiscussionFlowState(process.cwd());
|
|
242
242
|
if (existsSync(snapshotFile)) unlinkSync(snapshotFile);
|
|
243
243
|
_setAutoActiveForTest(true);
|
|
244
244
|
const deepCtx = {
|
|
@@ -264,7 +264,7 @@ describe('auto-discuss-milestone-deadlock-4973', () => {
|
|
|
264
264
|
// ── Interactive case: the rule must NOT call markDepthVerified ──
|
|
265
265
|
// clearDiscussionFlowState() only deletes the snapshot at process.cwd(),
|
|
266
266
|
// so we must explicitly remove the snapshot under our tempBase too.
|
|
267
|
-
clearDiscussionFlowState();
|
|
267
|
+
clearDiscussionFlowState(process.cwd());
|
|
268
268
|
if (existsSync(snapshotFile)) unlinkSync(snapshotFile);
|
|
269
269
|
_setAutoActiveForTest(false);
|
|
270
270
|
snap = loadWriteGateSnapshot(tempBase);
|
|
@@ -40,6 +40,12 @@ test("auto.ts validates milestone before restoring paused session (#1664)", () =
|
|
|
40
40
|
"auto.ts must check for SUMMARY file to detect completed milestones",
|
|
41
41
|
);
|
|
42
42
|
|
|
43
|
+
assert.ok(
|
|
44
|
+
source.includes("await ensureDbOpen(base)") &&
|
|
45
|
+
source.indexOf("await ensureDbOpen(base)") < source.indexOf('resolveMilestoneFile(base, meta.milestoneId, "SUMMARY")'),
|
|
46
|
+
"auto.ts must open the canonical DB before using SUMMARY as a paused-session fallback",
|
|
47
|
+
);
|
|
48
|
+
|
|
43
49
|
// Resume path must sanitize paused session file metadata before unlink/recovery.
|
|
44
50
|
assert.ok(
|
|
45
51
|
source.includes("normalizeSessionFilePath(meta.sessionFile ?? null)"),
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Regression test for
|
|
2
|
+
* Regression test for DB-authoritative rogue detection.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* re-dispatch. The fix calls updateSliceStatus() to sync the DB.
|
|
4
|
+
* A SUMMARY.md on disk is a projection/diagnostic. Runtime post-unit checks
|
|
5
|
+
* must not use it to mark the DB slice complete; explicit import/recovery
|
|
6
|
+
* commands own markdown-to-DB behavior.
|
|
8
7
|
*
|
|
9
|
-
* This structural test verifies
|
|
10
|
-
*
|
|
8
|
+
* This structural test verifies the complete-slice rogue branch reports the
|
|
9
|
+
* stale projection without calling updateSliceStatus().
|
|
11
10
|
*/
|
|
12
11
|
|
|
13
12
|
import { describe, test } from 'node:test';
|
|
@@ -22,38 +21,26 @@ const __dirname = dirname(__filename);
|
|
|
22
21
|
|
|
23
22
|
const source = readFileSync(join(__dirname, '..', 'auto-post-unit.ts'), 'utf-8');
|
|
24
23
|
|
|
25
|
-
describe('
|
|
26
|
-
test('updateSliceStatus is imported
|
|
27
|
-
assert.
|
|
28
|
-
'
|
|
24
|
+
describe('DB-authoritative slice rogue detection', () => {
|
|
25
|
+
test('updateSliceStatus is not imported for post-unit rogue reconciliation', () => {
|
|
26
|
+
assert.doesNotMatch(source, /import\s*\{[^}]*updateSliceStatus[^}]*\}\s*from\s*["']\.\/gsd-db/,
|
|
27
|
+
'auto-post-unit must not import updateSliceStatus for disk-to-DB reconciliation');
|
|
29
28
|
});
|
|
30
29
|
|
|
31
|
-
test('
|
|
32
|
-
assert.
|
|
33
|
-
'
|
|
30
|
+
test('complete-slice rogue branch does not mark DB complete from disk', () => {
|
|
31
|
+
assert.doesNotMatch(source, /updateSliceStatus\(mid,\s*sid,\s*["']complete["']/,
|
|
32
|
+
'SUMMARY.md on disk must not mark slice complete in DB');
|
|
34
33
|
});
|
|
35
34
|
|
|
36
|
-
test('
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
assert.ok(updateIdx > 0, 'updateSliceStatus call should exist');
|
|
41
|
-
|
|
42
|
-
// Find surrounding try-catch
|
|
43
|
-
const before = source.slice(Math.max(0, updateIdx - 200), updateIdx);
|
|
44
|
-
assert.match(before, /try\s*\{/,
|
|
45
|
-
'updateSliceStatus should be inside a try block');
|
|
46
|
-
|
|
47
|
-
// Bound the region to stop before the rogue fallback so /catch/ only
|
|
48
|
-
// matches this try block's catch, not an unrelated later one.
|
|
49
|
-
const after = extractSourceRegion(source, 'updateSliceStatus(mid, sid', 'rogues.push({');
|
|
50
|
-
assert.match(after, /catch/,
|
|
51
|
-
'try block should have a catch for fallback');
|
|
35
|
+
test('explicit rogue diagnostic reports stale slice summary projection', () => {
|
|
36
|
+
const branch = extractSourceRegion(source, 'unitType === "complete-slice"', 'unitType === "plan-milestone"');
|
|
37
|
+
assert.match(branch, /rogues\.push\(\{\s*path:\s*summaryPath,\s*unitType,\s*unitId\s*\}\)/,
|
|
38
|
+
'complete-slice branch should report stale SUMMARY.md as rogue');
|
|
52
39
|
});
|
|
53
40
|
|
|
54
|
-
test('
|
|
55
|
-
|
|
56
|
-
assert.
|
|
57
|
-
'
|
|
41
|
+
test('post-unit runtime does not call rogue diagnostics automatically', () => {
|
|
42
|
+
const postUnit = extractSourceRegion(source, 'export async function postUnitPostVerification');
|
|
43
|
+
assert.doesNotMatch(postUnit, /detectRogueFileWrites\(/,
|
|
44
|
+
'runtime post-unit path must not scan disk projections for rogue files');
|
|
58
45
|
});
|
|
59
46
|
});
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// GSD-2 + Tests for MilestoneScope threading through AutoSession state (C2)
|
|
2
|
+
//
|
|
3
|
+
// Strategy: construct AutoSession directly + call createWorkspace/scopeMilestone
|
|
4
|
+
// to mirror the rebuildScope() helper in auto.ts — avoids importing the full
|
|
5
|
+
// auto.ts module (too many .js resolved imports).
|
|
6
|
+
|
|
7
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { mkdtempSync, mkdirSync, rmSync, realpathSync, existsSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
|
|
13
|
+
import { AutoSession } from "../auto/session.ts";
|
|
14
|
+
import { createWorkspace, scopeMilestone } from "../workspace.ts";
|
|
15
|
+
import type { MilestoneScope } from "../workspace.ts";
|
|
16
|
+
|
|
17
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
function makeProjectDir(): string {
|
|
20
|
+
const dir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-scope-test-")));
|
|
21
|
+
mkdirSync(join(dir, ".gsd", "milestones"), { recursive: true });
|
|
22
|
+
return dir;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function makeWorktreeDir(projectDir: string, milestoneId: string): string {
|
|
26
|
+
const wt = join(projectDir, ".gsd", "worktrees", milestoneId);
|
|
27
|
+
mkdirSync(wt, { recursive: true });
|
|
28
|
+
return wt;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Mirror the rebuildScope() helper from auto.ts — computes s.scope from the
|
|
33
|
+
* same inputs so tests can verify the behaviour without importing auto.ts.
|
|
34
|
+
*/
|
|
35
|
+
function applyRebuildScope(
|
|
36
|
+
s: AutoSession,
|
|
37
|
+
rawPath: string,
|
|
38
|
+
milestoneId: string | null,
|
|
39
|
+
): void {
|
|
40
|
+
if (!milestoneId) {
|
|
41
|
+
s.scope = null;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const workspace = createWorkspace(rawPath);
|
|
46
|
+
s.scope = scopeMilestone(workspace, milestoneId);
|
|
47
|
+
} catch {
|
|
48
|
+
s.scope = null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─── Tests ───────────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
describe("AutoSession.scope — project mode (basePath equals originalBasePath)", () => {
|
|
55
|
+
let s: AutoSession;
|
|
56
|
+
let projectDir: string;
|
|
57
|
+
|
|
58
|
+
beforeEach(() => {
|
|
59
|
+
projectDir = makeProjectDir();
|
|
60
|
+
s = new AutoSession();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
afterEach(() => {
|
|
64
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("scope is null when milestoneId is null", () => {
|
|
68
|
+
s.basePath = projectDir;
|
|
69
|
+
s.originalBasePath = projectDir;
|
|
70
|
+
s.currentMilestoneId = null;
|
|
71
|
+
|
|
72
|
+
applyRebuildScope(s, projectDir, null);
|
|
73
|
+
|
|
74
|
+
assert.equal(s.scope, null);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("scope mode is 'project' when basePath equals originalBasePath", () => {
|
|
78
|
+
const mid = "M001";
|
|
79
|
+
s.basePath = projectDir;
|
|
80
|
+
s.originalBasePath = projectDir;
|
|
81
|
+
s.currentMilestoneId = mid;
|
|
82
|
+
|
|
83
|
+
applyRebuildScope(s, projectDir, mid);
|
|
84
|
+
|
|
85
|
+
assert.ok(s.scope, "scope should be set");
|
|
86
|
+
assert.equal(s.scope.workspace.mode, "project");
|
|
87
|
+
assert.equal(s.scope.milestoneId, mid);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("scope projectRoot matches realpath of projectDir", () => {
|
|
91
|
+
const mid = "M001";
|
|
92
|
+
s.basePath = projectDir;
|
|
93
|
+
s.originalBasePath = projectDir;
|
|
94
|
+
s.currentMilestoneId = mid;
|
|
95
|
+
|
|
96
|
+
applyRebuildScope(s, projectDir, mid);
|
|
97
|
+
|
|
98
|
+
assert.ok(s.scope, "scope should be set");
|
|
99
|
+
assert.equal(s.scope.workspace.projectRoot, realpathSync(projectDir));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("scope worktreeRoot is null in project mode", () => {
|
|
103
|
+
const mid = "M001";
|
|
104
|
+
s.basePath = projectDir;
|
|
105
|
+
s.originalBasePath = projectDir;
|
|
106
|
+
s.currentMilestoneId = mid;
|
|
107
|
+
|
|
108
|
+
applyRebuildScope(s, projectDir, mid);
|
|
109
|
+
|
|
110
|
+
assert.ok(s.scope, "scope should be set");
|
|
111
|
+
assert.equal(s.scope.workspace.worktreeRoot, null);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("scope path methods resolve under the .gsd directory", () => {
|
|
115
|
+
const mid = "M002";
|
|
116
|
+
s.basePath = projectDir;
|
|
117
|
+
s.originalBasePath = projectDir;
|
|
118
|
+
s.currentMilestoneId = mid;
|
|
119
|
+
|
|
120
|
+
applyRebuildScope(s, projectDir, mid);
|
|
121
|
+
|
|
122
|
+
assert.ok(s.scope, "scope should be set");
|
|
123
|
+
const gsd = join(projectDir, ".gsd");
|
|
124
|
+
assert.equal(s.scope.contextFile(), join(gsd, "milestones", mid, `${mid}-CONTEXT.md`));
|
|
125
|
+
assert.equal(s.scope.roadmapFile(), join(gsd, "milestones", mid, `${mid}-ROADMAP.md`));
|
|
126
|
+
assert.equal(s.scope.stateFile(), join(gsd, "STATE.md"));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("AutoSession.scope — worktree mode (basePath differs from originalBasePath)", () => {
|
|
131
|
+
let s: AutoSession;
|
|
132
|
+
let projectDir: string;
|
|
133
|
+
let worktreeDir: string;
|
|
134
|
+
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
projectDir = makeProjectDir();
|
|
137
|
+
worktreeDir = makeWorktreeDir(projectDir, "M001");
|
|
138
|
+
s = new AutoSession();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
afterEach(() => {
|
|
142
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test("scope mode is 'worktree' when basePath is the worktree path", () => {
|
|
146
|
+
const mid = "M001";
|
|
147
|
+
s.basePath = worktreeDir;
|
|
148
|
+
s.originalBasePath = projectDir;
|
|
149
|
+
s.currentMilestoneId = mid;
|
|
150
|
+
|
|
151
|
+
applyRebuildScope(s, worktreeDir, mid);
|
|
152
|
+
|
|
153
|
+
assert.ok(s.scope, "scope should be set");
|
|
154
|
+
assert.equal(s.scope.workspace.mode, "worktree");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("scope worktreeRoot matches realpath of worktreeDir", () => {
|
|
158
|
+
const mid = "M001";
|
|
159
|
+
s.basePath = worktreeDir;
|
|
160
|
+
s.originalBasePath = projectDir;
|
|
161
|
+
s.currentMilestoneId = mid;
|
|
162
|
+
|
|
163
|
+
applyRebuildScope(s, worktreeDir, mid);
|
|
164
|
+
|
|
165
|
+
assert.ok(s.scope, "scope should be set");
|
|
166
|
+
assert.equal(s.scope.workspace.worktreeRoot, realpathSync(worktreeDir));
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("scope projectRoot resolves to project root (not worktree)", () => {
|
|
170
|
+
const mid = "M001";
|
|
171
|
+
s.basePath = worktreeDir;
|
|
172
|
+
s.originalBasePath = projectDir;
|
|
173
|
+
s.currentMilestoneId = mid;
|
|
174
|
+
|
|
175
|
+
applyRebuildScope(s, worktreeDir, mid);
|
|
176
|
+
|
|
177
|
+
assert.ok(s.scope, "scope should be set");
|
|
178
|
+
assert.equal(s.scope.workspace.projectRoot, realpathSync(projectDir));
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("scope milestoneId matches the milestone being tracked", () => {
|
|
182
|
+
const mid = "M001";
|
|
183
|
+
s.basePath = worktreeDir;
|
|
184
|
+
s.originalBasePath = projectDir;
|
|
185
|
+
s.currentMilestoneId = mid;
|
|
186
|
+
|
|
187
|
+
applyRebuildScope(s, worktreeDir, mid);
|
|
188
|
+
|
|
189
|
+
assert.ok(s.scope, "scope should be set");
|
|
190
|
+
assert.equal(s.scope.milestoneId, mid);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe("AutoSession.scope — milestoneId change rebuilds scope", () => {
|
|
195
|
+
let s: AutoSession;
|
|
196
|
+
let projectDir: string;
|
|
197
|
+
|
|
198
|
+
beforeEach(() => {
|
|
199
|
+
projectDir = makeProjectDir();
|
|
200
|
+
s = new AutoSession();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
afterEach(() => {
|
|
204
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("scope reflects the new milestoneId after rebuild", () => {
|
|
208
|
+
s.basePath = projectDir;
|
|
209
|
+
s.originalBasePath = projectDir;
|
|
210
|
+
s.currentMilestoneId = "M001";
|
|
211
|
+
applyRebuildScope(s, projectDir, "M001");
|
|
212
|
+
|
|
213
|
+
assert.ok(s.scope, "initial scope should be set");
|
|
214
|
+
assert.equal(s.scope.milestoneId, "M001");
|
|
215
|
+
|
|
216
|
+
// Simulate milestone transition mid-session
|
|
217
|
+
s.currentMilestoneId = "M002";
|
|
218
|
+
applyRebuildScope(s, projectDir, "M002");
|
|
219
|
+
|
|
220
|
+
assert.ok(s.scope, "scope should be set after transition");
|
|
221
|
+
assert.equal(s.scope.milestoneId, "M002");
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("scope contextFile changes when milestoneId changes", () => {
|
|
225
|
+
s.basePath = projectDir;
|
|
226
|
+
s.originalBasePath = projectDir;
|
|
227
|
+
|
|
228
|
+
s.currentMilestoneId = "M001";
|
|
229
|
+
applyRebuildScope(s, projectDir, "M001");
|
|
230
|
+
const ctxM001 = s.scope?.contextFile();
|
|
231
|
+
|
|
232
|
+
s.currentMilestoneId = "M002";
|
|
233
|
+
applyRebuildScope(s, projectDir, "M002");
|
|
234
|
+
const ctxM002 = s.scope?.contextFile();
|
|
235
|
+
|
|
236
|
+
assert.ok(ctxM001, "M001 contextFile should be set");
|
|
237
|
+
assert.ok(ctxM002, "M002 contextFile should be set");
|
|
238
|
+
assert.notEqual(ctxM001, ctxM002, "contextFile must differ between milestone IDs");
|
|
239
|
+
assert.ok(ctxM001.includes("M001"), "M001 path should contain M001");
|
|
240
|
+
assert.ok(ctxM002.includes("M002"), "M002 path should contain M002");
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe("AutoSession.scope — resume from persisted state", () => {
|
|
245
|
+
let s: AutoSession;
|
|
246
|
+
let projectDir: string;
|
|
247
|
+
let worktreeDir: string;
|
|
248
|
+
|
|
249
|
+
beforeEach(() => {
|
|
250
|
+
projectDir = makeProjectDir();
|
|
251
|
+
worktreeDir = makeWorktreeDir(projectDir, "M003");
|
|
252
|
+
s = new AutoSession();
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
afterEach(() => {
|
|
256
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("resume without worktree: scope mode is project, projectRoot is base", () => {
|
|
260
|
+
// Mirror the paused-session resume path:
|
|
261
|
+
// s.currentMilestoneId = meta.milestoneId
|
|
262
|
+
// s.originalBasePath = meta.originalBasePath || base
|
|
263
|
+
// rawPath = originalBasePath (no worktreePath present)
|
|
264
|
+
const mid = "M003";
|
|
265
|
+
s.currentMilestoneId = mid;
|
|
266
|
+
s.originalBasePath = projectDir;
|
|
267
|
+
s.basePath = projectDir;
|
|
268
|
+
|
|
269
|
+
applyRebuildScope(s, s.originalBasePath, s.currentMilestoneId);
|
|
270
|
+
|
|
271
|
+
assert.ok(s.scope, "scope should be reconstructed");
|
|
272
|
+
assert.equal(s.scope.milestoneId, mid);
|
|
273
|
+
assert.equal(s.scope.workspace.mode, "project");
|
|
274
|
+
assert.equal(s.scope.workspace.projectRoot, realpathSync(projectDir));
|
|
275
|
+
assert.equal(s.scope.workspace.worktreeRoot, null);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("resume with valid worktree path: scope mode is worktree", () => {
|
|
279
|
+
// Mirror the paused-session resume path where worktreePath exists on disk:
|
|
280
|
+
// rawPath = worktreePath (existsSync true)
|
|
281
|
+
const mid = "M003";
|
|
282
|
+
s.currentMilestoneId = mid;
|
|
283
|
+
s.originalBasePath = projectDir;
|
|
284
|
+
s.basePath = worktreeDir;
|
|
285
|
+
|
|
286
|
+
assert.ok(existsSync(worktreeDir), "worktreeDir must exist for this test");
|
|
287
|
+
|
|
288
|
+
applyRebuildScope(s, worktreeDir, s.currentMilestoneId);
|
|
289
|
+
|
|
290
|
+
assert.ok(s.scope, "scope should be reconstructed");
|
|
291
|
+
assert.equal(s.scope.milestoneId, mid);
|
|
292
|
+
assert.equal(s.scope.workspace.mode, "worktree");
|
|
293
|
+
assert.equal(s.scope.workspace.projectRoot, realpathSync(projectDir));
|
|
294
|
+
assert.equal(s.scope.workspace.worktreeRoot, realpathSync(worktreeDir));
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("scope is consistent with direct createWorkspace + scopeMilestone for same inputs", () => {
|
|
298
|
+
const mid = "M003";
|
|
299
|
+
s.currentMilestoneId = mid;
|
|
300
|
+
s.originalBasePath = projectDir;
|
|
301
|
+
s.basePath = projectDir;
|
|
302
|
+
|
|
303
|
+
applyRebuildScope(s, projectDir, mid);
|
|
304
|
+
assert.ok(s.scope, "scope should be set");
|
|
305
|
+
|
|
306
|
+
// Build expected scope via lower-level API to verify equivalence
|
|
307
|
+
const ws = createWorkspace(projectDir);
|
|
308
|
+
const expected = scopeMilestone(ws, mid);
|
|
309
|
+
|
|
310
|
+
assert.equal(s.scope.milestoneId, expected.milestoneId);
|
|
311
|
+
assert.equal(s.scope.contextFile(), expected.contextFile());
|
|
312
|
+
assert.equal(s.scope.roadmapFile(), expected.roadmapFile());
|
|
313
|
+
assert.equal(s.scope.stateFile(), expected.stateFile());
|
|
314
|
+
assert.equal(s.scope.dbPath(), expected.dbPath());
|
|
315
|
+
assert.equal(s.scope.milestoneDir(), expected.milestoneDir());
|
|
316
|
+
assert.equal(s.scope.metaJson(), expected.metaJson());
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test("reset() clears scope", () => {
|
|
320
|
+
const mid = "M003";
|
|
321
|
+
s.basePath = projectDir;
|
|
322
|
+
s.originalBasePath = projectDir;
|
|
323
|
+
s.currentMilestoneId = mid;
|
|
324
|
+
|
|
325
|
+
applyRebuildScope(s, projectDir, mid);
|
|
326
|
+
assert.ok(s.scope, "scope should be set before reset");
|
|
327
|
+
|
|
328
|
+
s.reset();
|
|
329
|
+
assert.equal(s.scope, null, "scope must be null after reset()");
|
|
330
|
+
});
|
|
331
|
+
});
|