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
package/README.md
CHANGED
|
@@ -310,7 +310,9 @@ This is what makes GSD different. Run it, walk away, come back to built software
|
|
|
310
310
|
/gsd auto
|
|
311
311
|
```
|
|
312
312
|
|
|
313
|
-
Auto mode is a state machine driven by
|
|
313
|
+
Auto mode is a state machine driven by the GSD database at the project root. It derives the next unit of work from authoritative SQLite state, creates a fresh agent session, injects a focused prompt with all relevant context pre-inlined, and lets the LLM execute. When the LLM finishes, auto mode persists the result to the database, refreshes markdown projections such as `STATE.md`, and dispatches the next unit.
|
|
314
|
+
|
|
315
|
+
The database is authoritative for milestones, slices, tasks, requirements, decisions, summaries, and completion status. Markdown under `.gsd/` is a rendered projection for review, prompts, and git-friendly history; it is not a runtime fallback unless you explicitly run a recovery/import command. In worktree mode, project-root DB state remains authoritative and worktree markdown projections are not synced back as state.
|
|
314
316
|
|
|
315
317
|
**What happens under the hood:**
|
|
316
318
|
|
|
@@ -499,6 +501,7 @@ Every dispatch is carefully constructed. The LLM never wastes tool calls on orie
|
|
|
499
501
|
|
|
500
502
|
| Artifact | Purpose |
|
|
501
503
|
| ------------------ | --------------------------------------------------------------- |
|
|
504
|
+
| `gsd.db` | Authoritative runtime state for hierarchy and completion |
|
|
502
505
|
| `PROJECT.md` | Living doc — what the project is right now |
|
|
503
506
|
| `REQUIREMENTS.md` | Project-level capability contract and out-of-scope list |
|
|
504
507
|
| `DECISIONS.md` | Append-only register of architectural decisions |
|
|
@@ -506,7 +509,7 @@ Every dispatch is carefully constructed. The LLM never wastes tool calls on orie
|
|
|
506
509
|
| `RUNTIME.md` | Runtime context — API endpoints, env vars, services (v2.39) |
|
|
507
510
|
| `runtime/research-decision.json` | Deep-mode marker for project research vs skip |
|
|
508
511
|
| `research/*.md` | Optional deep-mode project research: stack, features, architecture, pitfalls |
|
|
509
|
-
| `STATE.md` | Quick-glance dashboard
|
|
512
|
+
| `STATE.md` | Quick-glance dashboard rendered from the database |
|
|
510
513
|
| `M001-ROADMAP.md` | Milestone plan with slice checkboxes, risk levels, dependencies |
|
|
511
514
|
| `M001-CONTEXT.md` | User decisions from the discuss phase |
|
|
512
515
|
| `M001-RESEARCH.md` | Codebase and ecosystem research |
|
|
@@ -708,7 +711,7 @@ The best practice for working in teams is to ensure unique milestone names acros
|
|
|
708
711
|
.gsd/completed-units*.json
|
|
709
712
|
# State manifest — workflow state for recovery
|
|
710
713
|
.gsd/state-manifest.json
|
|
711
|
-
# Derived state
|
|
714
|
+
# Derived state projection — regenerated from the authoritative database
|
|
712
715
|
.gsd/STATE.md
|
|
713
716
|
# Per-developer token/cost accumulator
|
|
714
717
|
.gsd/metrics.json
|
|
@@ -720,7 +723,7 @@ The best practice for working in teams is to ensure unique milestone names acros
|
|
|
720
723
|
.gsd/worktrees/
|
|
721
724
|
# Parallel orchestration IPC and worker status
|
|
722
725
|
.gsd/parallel/
|
|
723
|
-
# SQLite database and WAL sidecars —
|
|
726
|
+
# SQLite database and WAL sidecars — authoritative runtime state, local only
|
|
724
727
|
.gsd/gsd.db*
|
|
725
728
|
# Daily-rotated event journal — structured event log for forensics
|
|
726
729
|
.gsd/journal/
|
|
@@ -785,7 +788,7 @@ gsd (CLI binary)
|
|
|
785
788
|
- **`pkg/` shim directory** — `PI_PACKAGE_DIR` points here (not project root) to avoid Pi's theme resolution collision with our `src/` directory. Contains only `piConfig` and theme assets.
|
|
786
789
|
- **Two-file loader pattern** — `loader.ts` sets all env vars with zero SDK imports, then dynamic-imports `cli.ts` which does static SDK imports. This ensures `PI_PACKAGE_DIR` is set before any SDK code evaluates.
|
|
787
790
|
- **Always-overwrite sync** — `npm update -g` takes effect immediately. Bundled extensions and agents are synced to `~/.gsd/agent/` on every launch, not just first run.
|
|
788
|
-
- **
|
|
791
|
+
- **DB-authoritative state** — the project-root GSD database is the runtime source of truth. `.gsd/` markdown files are rendered projections for review, prompt context, and git history. No in-memory state survives across sessions.
|
|
789
792
|
|
|
790
793
|
---
|
|
791
794
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless Recover — `gsd headless recover`
|
|
3
|
+
*
|
|
4
|
+
* Non-interactive parallel of the `/gsd recover` slash command. Clears the
|
|
5
|
+
* milestones / slices / tasks tables and re-imports them from the on-disk
|
|
6
|
+
* markdown projections (ROADMAP.md, PLAN.md, SUMMARY.md, …) via
|
|
7
|
+
* migrateHierarchyToDb. Mutating: this is the one headless subcommand that
|
|
8
|
+
* writes to the DB. Required for CI / automation flows that need to
|
|
9
|
+
* reconcile DB state from markdown without launching an LLM session or a
|
|
10
|
+
* TTY-bound interactive runtime.
|
|
11
|
+
*
|
|
12
|
+
* Output: `gsd-recover: recovered <N>M/<N>S/<N>T hierarchy\n` to stderr on
|
|
13
|
+
* success — same marker emitted by handleRecover (commands-maintenance.ts)
|
|
14
|
+
* so callers can distinguish the success path from a silent no-op.
|
|
15
|
+
*
|
|
16
|
+
* Exit codes:
|
|
17
|
+
* 0 — recovery succeeded
|
|
18
|
+
* 1 — `.gsd/` missing, DB could not be opened, or migration threw
|
|
19
|
+
*/
|
|
20
|
+
export interface RecoverResult {
|
|
21
|
+
exitCode: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function handleRecover(basePath: string): Promise<RecoverResult>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// gsd-pi — Headless Recover entrypoint
|
|
2
|
+
/**
|
|
3
|
+
* Headless Recover — `gsd headless recover`
|
|
4
|
+
*
|
|
5
|
+
* Non-interactive parallel of the `/gsd recover` slash command. Clears the
|
|
6
|
+
* milestones / slices / tasks tables and re-imports them from the on-disk
|
|
7
|
+
* markdown projections (ROADMAP.md, PLAN.md, SUMMARY.md, …) via
|
|
8
|
+
* migrateHierarchyToDb. Mutating: this is the one headless subcommand that
|
|
9
|
+
* writes to the DB. Required for CI / automation flows that need to
|
|
10
|
+
* reconcile DB state from markdown without launching an LLM session or a
|
|
11
|
+
* TTY-bound interactive runtime.
|
|
12
|
+
*
|
|
13
|
+
* Output: `gsd-recover: recovered <N>M/<N>S/<N>T hierarchy\n` to stderr on
|
|
14
|
+
* success — same marker emitted by handleRecover (commands-maintenance.ts)
|
|
15
|
+
* so callers can distinguish the success path from a silent no-op.
|
|
16
|
+
*
|
|
17
|
+
* Exit codes:
|
|
18
|
+
* 0 — recovery succeeded
|
|
19
|
+
* 1 — `.gsd/` missing, DB could not be opened, or migration threw
|
|
20
|
+
*/
|
|
21
|
+
import { createJiti } from '@mariozechner/jiti';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { resolveGsdAgentExtensionsDir, shouldUseAgentExtensionsDir } from './headless-query.js';
|
|
24
|
+
import { resolveBundledGsdExtensionModule } from './bundled-resource-path.js';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { existsSync } from 'node:fs';
|
|
27
|
+
const jiti = createJiti(fileURLToPath(import.meta.url), { interopDefault: true, debug: false });
|
|
28
|
+
const agentExtensionsDir = resolveGsdAgentExtensionsDir();
|
|
29
|
+
const { useAgentDir } = shouldUseAgentExtensionsDir({ env: process.env });
|
|
30
|
+
const gsdExtensionPath = (...segments) => useAgentDir
|
|
31
|
+
? resolveAgentExtensionModule(agentExtensionsDir, segments)
|
|
32
|
+
: resolveBundledGsdExtensionModule(import.meta.url, segments.join('/'));
|
|
33
|
+
function resolveAgentExtensionModule(agentDir, segments) {
|
|
34
|
+
const requested = join(agentDir, ...segments);
|
|
35
|
+
if (existsSync(requested))
|
|
36
|
+
return requested;
|
|
37
|
+
if (segments.length === 1 && segments[0].endsWith('.ts')) {
|
|
38
|
+
const jsPath = join(agentDir, segments[0].replace(/\.ts$/, '.js'));
|
|
39
|
+
if (existsSync(jsPath))
|
|
40
|
+
return jsPath;
|
|
41
|
+
}
|
|
42
|
+
return requested;
|
|
43
|
+
}
|
|
44
|
+
async function loadExtensionModules() {
|
|
45
|
+
const stateModule = await jiti.import(gsdExtensionPath('state.ts'), {});
|
|
46
|
+
const dbModule = await jiti.import(gsdExtensionPath('gsd-db.ts'), {});
|
|
47
|
+
const importerModule = await jiti.import(gsdExtensionPath('md-importer.ts'), {});
|
|
48
|
+
const dynamicToolsModule = await jiti.import(gsdExtensionPath('bootstrap/dynamic-tools.ts'), {});
|
|
49
|
+
return {
|
|
50
|
+
ensureDbOpen: dynamicToolsModule.ensureDbOpen,
|
|
51
|
+
isDbAvailable: dbModule.isDbAvailable,
|
|
52
|
+
clearEngineHierarchy: dbModule.clearEngineHierarchy,
|
|
53
|
+
transaction: dbModule.transaction,
|
|
54
|
+
migrateHierarchyToDb: importerModule.migrateHierarchyToDb,
|
|
55
|
+
invalidateStateCache: stateModule.invalidateStateCache,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export async function handleRecover(basePath) {
|
|
59
|
+
const gsdDir = join(basePath, '.gsd');
|
|
60
|
+
if (!existsSync(gsdDir)) {
|
|
61
|
+
process.stderr.write(`[headless] recover: no .gsd/ directory at ${basePath}\n`);
|
|
62
|
+
return { exitCode: 1 };
|
|
63
|
+
}
|
|
64
|
+
let modules;
|
|
65
|
+
try {
|
|
66
|
+
modules = await loadExtensionModules();
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
70
|
+
process.stderr.write(`[headless] recover: failed to load extension modules: ${msg}\n`);
|
|
71
|
+
return { exitCode: 1 };
|
|
72
|
+
}
|
|
73
|
+
const opened = await modules.ensureDbOpen(basePath);
|
|
74
|
+
if (!opened || !modules.isDbAvailable()) {
|
|
75
|
+
process.stderr.write(`[headless] recover: failed to open or create the GSD database at ${basePath}\n`);
|
|
76
|
+
return { exitCode: 1 };
|
|
77
|
+
}
|
|
78
|
+
let counts;
|
|
79
|
+
try {
|
|
80
|
+
counts = modules.transaction(() => {
|
|
81
|
+
modules.clearEngineHierarchy();
|
|
82
|
+
return modules.migrateHierarchyToDb(basePath);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
87
|
+
process.stderr.write(`[headless] recover failed: ${msg}\n`);
|
|
88
|
+
return { exitCode: 1 };
|
|
89
|
+
}
|
|
90
|
+
modules.invalidateStateCache();
|
|
91
|
+
process.stderr.write(`gsd-recover: recovered ${counts.milestones}M/${counts.slices}S/${counts.tasks}T hierarchy\n`);
|
|
92
|
+
return { exitCode: 0 };
|
|
93
|
+
}
|
package/dist/headless.js
CHANGED
|
@@ -265,6 +265,15 @@ async function runHeadlessOnce(options, restartCount) {
|
|
|
265
265
|
const result = await handleQuery(process.cwd());
|
|
266
266
|
return { exitCode: result.exitCode, interrupted: false };
|
|
267
267
|
}
|
|
268
|
+
// Recover: rebuild DB hierarchy from on-disk markdown projections, no RPC
|
|
269
|
+
// child needed. This is the one mutating headless subcommand — required for
|
|
270
|
+
// CI / automation that needs to reconcile DB state from markdown without
|
|
271
|
+
// launching an interactive TTY-bound runtime.
|
|
272
|
+
if (options.command === 'recover') {
|
|
273
|
+
const { handleRecover } = await import('./headless-recover.js');
|
|
274
|
+
const result = await handleRecover(process.cwd());
|
|
275
|
+
process.exit(result.exitCode);
|
|
276
|
+
}
|
|
268
277
|
// Doctor: read-only health check, no RPC child needed (#4904 live-regression).
|
|
269
278
|
// The interactive `/gsd doctor` command lives in the GSD extension; this CLI
|
|
270
279
|
// path lets non-interactive callers (CI, recovery scripts, the live-regression
|
package/dist/help-text.js
CHANGED
|
@@ -156,6 +156,7 @@ const SUBCOMMAND_HELP = {
|
|
|
156
156
|
' gsd headless --answers answers.json auto With pre-supplied answers',
|
|
157
157
|
' gsd headless --events agent_end,extension_ui_request auto Filtered event stream',
|
|
158
158
|
' gsd headless query Instant JSON state snapshot',
|
|
159
|
+
' gsd headless recover Rebuild DB hierarchy from markdown (mutating)',
|
|
159
160
|
'',
|
|
160
161
|
'Exit codes: 0 = success, 1 = error/timeout, 10 = blocked, 11 = cancelled',
|
|
161
162
|
].join('\n'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3cb2810818585c65
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
-
import { StringEnum } from "@gsd/pi-ai";
|
|
3
2
|
import { diffCompactStates } from "../core.js";
|
|
4
3
|
import { setLastActionBeforeState, setLastActionAfterState, } from "../state.js";
|
|
5
4
|
// ---------------------------------------------------------------------------
|
|
@@ -15,6 +14,14 @@ const INTENTS = [
|
|
|
15
14
|
"auth_action",
|
|
16
15
|
"back_navigation",
|
|
17
16
|
];
|
|
17
|
+
function StringEnum(values, options) {
|
|
18
|
+
return Type.Unsafe({
|
|
19
|
+
type: "string",
|
|
20
|
+
enum: values,
|
|
21
|
+
...(options?.description && { description: options.description }),
|
|
22
|
+
...(options?.default && { default: options.default }),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
18
25
|
// ---------------------------------------------------------------------------
|
|
19
26
|
// Scoring evaluate script — runs entirely in-browser via page.evaluate()
|
|
20
27
|
// ---------------------------------------------------------------------------
|
|
@@ -12,7 +12,7 @@ import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from ".
|
|
|
12
12
|
import { detectStuck } from "./detect-stuck.js";
|
|
13
13
|
import { runUnit } from "./run-unit.js";
|
|
14
14
|
import { debugLog } from "../debug-logger.js";
|
|
15
|
-
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
15
|
+
import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
|
|
16
16
|
import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
|
|
17
17
|
import { MergeConflictError } from "../git-service.js";
|
|
18
18
|
import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
|
|
@@ -37,6 +37,11 @@ import { parseUnitId } from "../unit-id.js";
|
|
|
37
37
|
import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
|
|
38
38
|
import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
|
|
39
39
|
import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, supportsStructuredQuestions, } from "../workflow-mcp.js";
|
|
40
|
+
// ─── Path Comparison Helper ───────────────────────────────────────────────
|
|
41
|
+
/** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
|
|
42
|
+
function isSamePathLocal(a, b) {
|
|
43
|
+
return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
|
|
44
|
+
}
|
|
40
45
|
// ─── Session timeout auto-resume state ────────────────────────────────────────
|
|
41
46
|
let consecutiveSessionTimeouts = 0;
|
|
42
47
|
const MAX_SESSION_TIMEOUT_AUTO_RESUMES = 3;
|
|
@@ -280,7 +285,7 @@ export async function runPreDispatch(ic, loopState) {
|
|
|
280
285
|
}
|
|
281
286
|
// Sync project root artifacts into worktree
|
|
282
287
|
if (s.originalBasePath &&
|
|
283
|
-
s.basePath
|
|
288
|
+
!isSamePathLocal(s.basePath, s.originalBasePath) &&
|
|
284
289
|
s.currentMilestoneId) {
|
|
285
290
|
deps.syncProjectRootToWorktree(s.originalBasePath, s.basePath, s.currentMilestoneId);
|
|
286
291
|
}
|
|
@@ -32,6 +32,8 @@ export class AutoSession {
|
|
|
32
32
|
// ── Paths ────────────────────────────────────────────────────────────────
|
|
33
33
|
basePath = "";
|
|
34
34
|
originalBasePath = "";
|
|
35
|
+
// TODO(C8): remove basePath/originalBasePath once all readers use s.scope
|
|
36
|
+
scope = null;
|
|
35
37
|
previousProjectRootEnv = null;
|
|
36
38
|
hadProjectRootEnv = false;
|
|
37
39
|
projectRootEnvCaptured = false;
|
|
@@ -173,6 +175,7 @@ export class AutoSession {
|
|
|
173
175
|
// Paths
|
|
174
176
|
this.basePath = "";
|
|
175
177
|
this.originalBasePath = "";
|
|
178
|
+
this.scope = null;
|
|
176
179
|
this.previousProjectRootEnv = null;
|
|
177
180
|
this.hadProjectRootEnv = false;
|
|
178
181
|
this.projectRootEnvCaptured = false;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* without modifying orchestration code.
|
|
10
10
|
*/
|
|
11
11
|
import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
|
|
12
|
-
import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted, getMilestone
|
|
12
|
+
import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted, getMilestone } from "./gsd-db.js";
|
|
13
13
|
import { isClosedStatus } from "./status-guards.js";
|
|
14
14
|
import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
|
|
15
15
|
import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
|
|
@@ -19,7 +19,6 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "
|
|
|
19
19
|
import { logWarning, logError } from "./workflow-logger.js";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import { hasImplementationArtifacts } from "./auto-recovery.js";
|
|
22
|
-
import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
|
|
23
22
|
import { buildDiscussMilestonePrompt, buildDiscussProjectPrompt, buildDiscussRequirementsPrompt, buildResearchDecisionPrompt, buildResearchProjectPrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
|
|
24
23
|
import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
|
|
25
24
|
import { resolveUokFlags } from "./uok/flags.js";
|
|
@@ -32,6 +31,7 @@ import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
|
|
|
32
31
|
import { MILESTONE_ID_RE } from "./milestone-ids.js";
|
|
33
32
|
import { PROJECT_RESEARCH_INFLIGHT_MARKER, } from "./project-research-policy.js";
|
|
34
33
|
import { isWorkflowPrefsCaptured, resolveDeepProjectSetupState, } from "./deep-project-setup-policy.js";
|
|
34
|
+
import { annotateBackgroundable } from "./delegation-policy.js";
|
|
35
35
|
let reassessmentChecker = checkNeedsReassessment;
|
|
36
36
|
let researchProjectPromptBuilder = buildResearchProjectPrompt;
|
|
37
37
|
function shouldBypassMilestoneDepthGateInAuto(prefs) {
|
|
@@ -720,13 +720,9 @@ export const DISPATCH_RULES = [
|
|
|
720
720
|
// while a slice is still `is_sketch=1`, fall through to a standard
|
|
721
721
|
// plan-slice so the loop doesn't dead-end.
|
|
722
722
|
//
|
|
723
|
-
// Note on the flag-OFF downgrade:
|
|
724
|
-
//
|
|
725
|
-
//
|
|
726
|
-
// next iteration. That implicit coupling is the sole mechanism that
|
|
727
|
-
// reconciles `is_sketch=1` on the plan-slice path — do not remove the
|
|
728
|
-
// auto-heal without either adding an explicit `setSliceSketchFlag(..., false)`
|
|
729
|
-
// call here or doing so inside the plan-slice tool handler.
|
|
723
|
+
// Note on the flag-OFF downgrade: DB slice metadata is authoritative.
|
|
724
|
+
// PLAN.md is only a projection, so plan-slice/refine-slice handlers must
|
|
725
|
+
// explicitly clear `is_sketch` when a sketch becomes a full plan.
|
|
730
726
|
name: "refining → refine-slice",
|
|
731
727
|
match: async ({ state, mid, midTitle, basePath, prefs, sessionContextWindow, modelRegistry, sessionProvider }) => {
|
|
732
728
|
if (state.phase !== "refining")
|
|
@@ -1037,14 +1033,6 @@ export const DISPATCH_RULES = [
|
|
|
1037
1033
|
return { action: "skip" };
|
|
1038
1034
|
}
|
|
1039
1035
|
}
|
|
1040
|
-
const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
|
|
1041
|
-
let summaryOutcome = "unknown";
|
|
1042
|
-
if (existingSummary) {
|
|
1043
|
-
const summaryContent = await loadFile(existingSummary);
|
|
1044
|
-
if (summaryContent) {
|
|
1045
|
-
summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
1036
|
// Safety guard (#2675): block completion when VALIDATION verdict is
|
|
1049
1037
|
// needs-remediation. The state machine treats needs-remediation as
|
|
1050
1038
|
// terminal (to prevent validate-milestone loops per #832), but
|
|
@@ -1121,45 +1109,6 @@ export const DISPATCH_RULES = [
|
|
|
1121
1109
|
catch (err) { /* fall through — don't block on DB errors */
|
|
1122
1110
|
logWarning("dispatch", `verification class check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1123
1111
|
}
|
|
1124
|
-
// Disk/DB mismatch handling (#4658): SUMMARY presence alone is not enough.
|
|
1125
|
-
// Apply post-gate policy:
|
|
1126
|
-
// - success summary: reconcile DB and skip re-dispatch
|
|
1127
|
-
// - failure summary: pause/fail-closed
|
|
1128
|
-
// - unknown summary: pause/fail-closed
|
|
1129
|
-
if (existingSummary) {
|
|
1130
|
-
const milestone = isDbAvailable() ? getMilestone(mid) : null;
|
|
1131
|
-
const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
|
|
1132
|
-
if (summaryOutcome === "success") {
|
|
1133
|
-
if (!isDbAvailable()) {
|
|
1134
|
-
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
|
|
1135
|
-
return { action: "skip" };
|
|
1136
|
-
}
|
|
1137
|
-
try {
|
|
1138
|
-
updateMilestoneStatus(mid, "complete", new Date().toISOString());
|
|
1139
|
-
logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);
|
|
1140
|
-
return { action: "skip" };
|
|
1141
|
-
}
|
|
1142
|
-
catch (err) {
|
|
1143
|
-
return {
|
|
1144
|
-
action: "stop",
|
|
1145
|
-
level: "warning",
|
|
1146
|
-
reason: `Milestone ${mid} SUMMARY indicates completion but DB reconciliation failed (${err instanceof Error ? err.message : String(err)}). Auto-mode paused for manual review.`,
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
if (summaryOutcome === "failure") {
|
|
1151
|
-
return {
|
|
1152
|
-
action: "stop",
|
|
1153
|
-
level: "warning",
|
|
1154
|
-
reason: `Milestone ${mid} has a failure-path SUMMARY while DB status is "${status}". Auto-mode will not promote completion from failure artifacts. Re-run complete-milestone only after blockers are resolved and verification passes.`,
|
|
1155
|
-
};
|
|
1156
|
-
}
|
|
1157
|
-
return {
|
|
1158
|
-
action: "stop",
|
|
1159
|
-
level: "warning",
|
|
1160
|
-
reason: `Milestone ${mid} has an ambiguous SUMMARY while DB status is "${status}". Auto-mode paused instead of promoting completion from file presence alone.`,
|
|
1161
|
-
};
|
|
1162
|
-
}
|
|
1163
1112
|
return {
|
|
1164
1113
|
action: "dispatch",
|
|
1165
1114
|
unitType: "complete-milestone",
|
|
@@ -1204,7 +1153,7 @@ export async function resolveDispatch(ctx) {
|
|
|
1204
1153
|
// Delegate to registry when available
|
|
1205
1154
|
try {
|
|
1206
1155
|
const registry = getRegistry();
|
|
1207
|
-
return await registry.evaluateDispatch(ctx);
|
|
1156
|
+
return annotateBackgroundable(await registry.evaluateDispatch(ctx));
|
|
1208
1157
|
}
|
|
1209
1158
|
catch (err) {
|
|
1210
1159
|
// Registry not initialized — fall back to inline loop
|
|
@@ -1215,7 +1164,7 @@ export async function resolveDispatch(ctx) {
|
|
|
1215
1164
|
if (result) {
|
|
1216
1165
|
if (result.action !== "skip")
|
|
1217
1166
|
result.matchedRule = rule.name;
|
|
1218
|
-
return result;
|
|
1167
|
+
return annotateBackgroundable(result);
|
|
1219
1168
|
}
|
|
1220
1169
|
}
|
|
1221
1170
|
// No rule matched — unhandled phase.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Post-unit processing for auto-loop — auto-commit, doctor run,
|
|
3
|
-
* state rebuild,
|
|
3
|
+
* state rebuild, projection checks, DB tool closeout, hooks, triage, and
|
|
4
4
|
* quick-task dispatch.
|
|
5
5
|
*
|
|
6
6
|
* Split into two functions called sequentially by auto-loop with
|
|
@@ -24,7 +24,8 @@ import { runTurnGitAction, } from "./git-service.js";
|
|
|
24
24
|
import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, } from "./auto-recovery.js";
|
|
25
25
|
import { regenerateIfMissing } from "./workflow-projections.js";
|
|
26
26
|
import { syncStateToProjectRoot } from "./auto-worktree.js";
|
|
27
|
-
import {
|
|
27
|
+
import { normalizeWorktreePathForCompare } from "./worktree-root.js";
|
|
28
|
+
import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
|
|
28
29
|
import { renderPlanCheckboxes } from "./markdown-renderer.js";
|
|
29
30
|
import { consumeSignal } from "./session-status-io.js";
|
|
30
31
|
import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
|
|
@@ -51,6 +52,11 @@ import { detectAbandonMilestone } from "./abandon-detect.js";
|
|
|
51
52
|
import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
|
|
52
53
|
import { clearProjectResearchInflightMarker, finalizeProjectResearchTimeout, } from "./project-research-policy.js";
|
|
53
54
|
import { validateArtifact } from "./schemas/validate.js";
|
|
55
|
+
// ─── Path Comparison Helper ───────────────────────────────────────────────
|
|
56
|
+
/** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
|
|
57
|
+
function isSamePathLocal(a, b) {
|
|
58
|
+
return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
|
|
59
|
+
}
|
|
54
60
|
/** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
|
|
55
61
|
const MAX_VERIFICATION_RETRIES = 3;
|
|
56
62
|
/** Keep failure toasts short while still showing concrete examples. */
|
|
@@ -109,9 +115,8 @@ import { autoCommitCurrentBranch } from "./worktree.js";
|
|
|
109
115
|
* the completion tool. A "rogue" file is one that exists on disk but has
|
|
110
116
|
* no corresponding DB row with status "complete".
|
|
111
117
|
*
|
|
112
|
-
* This is a safety-net diagnostic (D003).
|
|
113
|
-
*
|
|
114
|
-
* detection provides immediate diagnostics so operators know the prompt failed.
|
|
118
|
+
* This is a safety-net diagnostic (D003). Runtime detection never imports
|
|
119
|
+
* markdown into the DB; explicit migration/import/recovery commands own that.
|
|
115
120
|
*/
|
|
116
121
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
122
|
function hasNonEmptyFields(row, fields) {
|
|
@@ -145,15 +150,7 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
|
|
|
145
150
|
return [];
|
|
146
151
|
const dbRow = getSlice(mid, sid);
|
|
147
152
|
if (!dbRow || dbRow.status !== "complete") {
|
|
148
|
-
|
|
149
|
-
// match filesystem instead of reporting as rogue (#3633).
|
|
150
|
-
try {
|
|
151
|
-
updateSliceStatus(mid, sid, "complete", new Date().toISOString());
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
// If DB update fails, fall back to rogue detection so the issue is visible
|
|
155
|
-
rogues.push({ path: summaryPath, unitType, unitId });
|
|
156
|
-
}
|
|
153
|
+
rogues.push({ path: summaryPath, unitType, unitId });
|
|
157
154
|
}
|
|
158
155
|
}
|
|
159
156
|
else if (unitType === "plan-milestone") {
|
|
@@ -519,7 +516,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
519
516
|
await rebuildState(s.basePath);
|
|
520
517
|
});
|
|
521
518
|
// Sync worktree state back to project root (skipped for lightweight sidecars)
|
|
522
|
-
if (!opts?.skipWorktreeSync && s.originalBasePath && s.originalBasePath
|
|
519
|
+
if (!opts?.skipWorktreeSync && s.originalBasePath && !isSamePathLocal(s.originalBasePath, s.basePath)) {
|
|
523
520
|
await runSafely("postUnit", "worktree-sync", () => {
|
|
524
521
|
syncStateToProjectRoot(s.basePath, s.originalBasePath, s.currentMilestoneId);
|
|
525
522
|
});
|
|
@@ -628,7 +625,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
628
625
|
ctx.ui.notify(`slice-cadence merge conflict in ${sid}: ${err.conflictedFiles.join(", ")}. ` +
|
|
629
626
|
`Resolve manually on main and run \`/gsd auto\` to resume.`, "error");
|
|
630
627
|
// Stop auto AND signal the outer postUnit flow to exit early.
|
|
631
|
-
// Without the flag, subsequent hooks (triage,
|
|
628
|
+
// Without the flag, subsequent hooks (triage,
|
|
632
629
|
// DB writes) would keep running against a conflicted main
|
|
633
630
|
// checkout after the loop was already told to stop.
|
|
634
631
|
const { stopAuto } = await import("./auto.js");
|
|
@@ -648,7 +645,7 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
648
645
|
}
|
|
649
646
|
});
|
|
650
647
|
// Exit early after stopAuto so the rest of post-unit processing
|
|
651
|
-
// (triage,
|
|
648
|
+
// (triage, hook dispatch, DB writes) doesn't run
|
|
652
649
|
// against a conflicted main checkout. Return "dispatched" to match
|
|
653
650
|
// the convention used by other stop/pauseAuto paths in this function
|
|
654
651
|
// (see signal handling earlier: stop/pause also return "dispatched").
|
|
@@ -689,17 +686,6 @@ export async function postUnitPreVerification(pctx, opts) {
|
|
|
689
686
|
logError("engine", "triage resolution failed", { error: err.message });
|
|
690
687
|
}
|
|
691
688
|
}
|
|
692
|
-
// Rogue file detection — safety net for LLM bypassing completion tools (D003)
|
|
693
|
-
try {
|
|
694
|
-
const rogueFiles = detectRogueFileWrites(s.currentUnit.type, s.currentUnit.id, s.basePath);
|
|
695
|
-
for (const rogue of rogueFiles) {
|
|
696
|
-
logWarning("engine", "rogue file write detected", { path: rogue.path, unitId: rogue.unitId });
|
|
697
|
-
ctx.ui.notify(`Rogue file write detected: ${rogue.path}`, "warning");
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
catch (e) {
|
|
701
|
-
debugLog("postUnit", { phase: "rogue-detection", error: String(e) });
|
|
702
|
-
}
|
|
703
689
|
// ── Safety harness: post-unit validation ──
|
|
704
690
|
try {
|
|
705
691
|
const { loadEffectiveGSDPreferences } = await import("./preferences.js");
|
|
@@ -649,19 +649,12 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
|
|
|
649
649
|
const gsdDbPath = resolveProjectRootDbPath(s.basePath);
|
|
650
650
|
const gsdDirPath = join(s.basePath, ".gsd");
|
|
651
651
|
if (existsSync(gsdDirPath) && !existsSync(gsdDbPath)) {
|
|
652
|
-
const hasDecisions = existsSync(join(gsdDirPath, "DECISIONS.md"));
|
|
653
|
-
const hasRequirements = existsSync(join(gsdDirPath, "REQUIREMENTS.md"));
|
|
654
|
-
const hasMilestones = existsSync(join(gsdDirPath, "milestones"));
|
|
655
652
|
try {
|
|
656
653
|
const { openDatabase: openDb } = await import("./gsd-db.js");
|
|
657
654
|
openDb(gsdDbPath);
|
|
658
|
-
if (hasDecisions || hasRequirements || hasMilestones) {
|
|
659
|
-
const { migrateFromMarkdown } = await import("./md-importer.js");
|
|
660
|
-
migrateFromMarkdown(s.basePath);
|
|
661
|
-
}
|
|
662
655
|
}
|
|
663
656
|
catch (err) {
|
|
664
|
-
logError("engine", `
|
|
657
|
+
logError("engine", `failed to initialize project database: ${err.message}`);
|
|
665
658
|
}
|
|
666
659
|
}
|
|
667
660
|
if (existsSync(gsdDbPath) && !isDbAvailable()) {
|