gsd-pi 2.65.0 → 2.66.0
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/dist/mcp-server.js +6 -2
- package/dist/resources/extensions/browser-tools/capture.js +20 -1
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/dist/resources/extensions/gsd/auto/finalize-timeout.js +2 -0
- package/dist/resources/extensions/gsd/auto/loop.js +2 -2
- package/dist/resources/extensions/gsd/auto/phases.js +48 -5
- package/dist/resources/extensions/gsd/auto/run-unit.js +13 -2
- package/dist/resources/extensions/gsd/auto/session.js +4 -0
- package/dist/resources/extensions/gsd/auto/types.js +2 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +2 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +99 -9
- package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +40 -22
- package/dist/resources/extensions/gsd/auto-start.js +175 -12
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
- package/dist/resources/extensions/gsd/auto.js +21 -15
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +10 -0
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +11 -3
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +31 -1
- package/dist/resources/extensions/gsd/commands/context.js +8 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +1 -1
- package/dist/resources/extensions/gsd/config-overlay.js +312 -0
- package/dist/resources/extensions/gsd/db-writer.js +13 -3
- package/dist/resources/extensions/gsd/detection.js +1 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/dist/resources/extensions/gsd/doctor.js +2 -1
- package/dist/resources/extensions/gsd/files.js +17 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +47 -4
- package/dist/resources/extensions/gsd/guided-flow.js +220 -29
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/json-persistence.js +5 -2
- package/dist/resources/extensions/gsd/md-importer.js +14 -7
- package/dist/resources/extensions/gsd/notification-overlay.js +1 -1
- package/dist/resources/extensions/gsd/notification-widget.js +2 -1
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
- package/dist/resources/extensions/gsd/pre-execution-checks.js +26 -5
- package/dist/resources/extensions/gsd/preferences-types.js +3 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +45 -1
- package/dist/resources/extensions/gsd/preferences.js +9 -2
- package/dist/resources/extensions/gsd/preparation.js +1092 -0
- package/dist/resources/extensions/gsd/prompt-validation.js +67 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/dist/resources/extensions/gsd/prompts/queue.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/dist/resources/extensions/gsd/prompts/system.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/dist/resources/extensions/gsd/quick.js +19 -15
- package/dist/resources/extensions/gsd/reactive-graph.js +12 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +24 -5
- package/dist/resources/extensions/gsd/safety/content-validator.js +3 -3
- package/dist/resources/extensions/gsd/session-lock.js +23 -1
- package/dist/resources/extensions/gsd/state.js +115 -28
- package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +15 -3
- package/dist/resources/extensions/gsd/tools/complete-slice.js +27 -6
- package/dist/resources/extensions/gsd/tools/complete-task.js +31 -7
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -5
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +5 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +119 -0
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +30 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +18 -0
- package/dist/resources/extensions/gsd/triage-resolution.js +33 -16
- package/dist/resources/extensions/gsd/undo.js +3 -2
- package/dist/resources/extensions/gsd/workflow-events.js +1 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +1 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +7 -9
- package/dist/resources/extensions/gsd/workflow-reconcile.js +100 -9
- package/dist/resources/extensions/gsd/workflow-templates.js +11 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +5 -2
- package/dist/resources/extensions/gsd/worktree.js +9 -0
- package/dist/resources/extensions/shared/interview-ui.js +1 -1
- package/dist/resources/extensions/subagent/agents.js +19 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.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/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 +14 -14
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +30 -19
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +51 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -9
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +10 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +20 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +15 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +18 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +80 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +37 -25
- package/packages/pi-coding-agent/src/core/sdk.ts +9 -9
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +20 -4
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +27 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +16 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +5 -0
- package/packages/pi-tui/dist/components/image.d.ts +2 -0
- package/packages/pi-tui/dist/components/image.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/image.js +4 -0
- package/packages/pi-tui/dist/components/image.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
- package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/image.test.js +32 -0
- package/packages/pi-tui/dist/components/image.test.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +3 -1
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/components/image.test.ts +36 -0
- package/packages/pi-tui/src/components/image.ts +5 -0
- package/packages/pi-tui/src/tui.ts +3 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/browser-tools/capture.ts +19 -1
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +93 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +3 -0
- package/src/resources/extensions/gsd/auto/loop.ts +2 -2
- package/src/resources/extensions/gsd/auto/phases.ts +68 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +12 -2
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto/types.ts +5 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +110 -9
- package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +16 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +29 -23
- package/src/resources/extensions/gsd/auto-start.ts +188 -10
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
- package/src/resources/extensions/gsd/auto.ts +19 -8
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +10 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +4 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +36 -1
- package/src/resources/extensions/gsd/commands/context.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +26 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +1 -1
- package/src/resources/extensions/gsd/config-overlay.ts +331 -0
- package/src/resources/extensions/gsd/db-writer.ts +11 -3
- package/src/resources/extensions/gsd/detection.ts +1 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -1
- package/src/resources/extensions/gsd/files.ts +19 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +46 -4
- package/src/resources/extensions/gsd/guided-flow.ts +254 -30
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/json-persistence.ts +6 -3
- package/src/resources/extensions/gsd/md-importer.ts +13 -6
- package/src/resources/extensions/gsd/notification-overlay.ts +1 -1
- package/src/resources/extensions/gsd/notification-widget.ts +2 -1
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
- package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -7
- package/src/resources/extensions/gsd/preferences-types.ts +25 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +45 -1
- package/src/resources/extensions/gsd/preferences.ts +9 -2
- package/src/resources/extensions/gsd/preparation.ts +1419 -0
- package/src/resources/extensions/gsd/prompt-validation.ts +88 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +3 -3
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss-prepared.md +424 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +6 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +5 -4
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +23 -0
- package/src/resources/extensions/gsd/prompts/queue.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +2 -1
- package/src/resources/extensions/gsd/prompts/system.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +56 -23
- package/src/resources/extensions/gsd/quick.ts +20 -15
- package/src/resources/extensions/gsd/reactive-graph.ts +18 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +21 -5
- package/src/resources/extensions/gsd/safety/content-validator.ts +3 -3
- package/src/resources/extensions/gsd/session-lock.ts +17 -1
- package/src/resources/extensions/gsd/state.ts +115 -26
- package/src/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/src/resources/extensions/gsd/tests/adversarial-review-fixes.test.ts +223 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +33 -2
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +28 -30
- package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
- package/src/resources/extensions/gsd/tests/integration-prepared-discussion.test.ts +525 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +11 -10
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +284 -20
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/preparation.test.ts +1211 -0
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/prompt-builder.test.ts +669 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +6 -7
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +3 -4
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +16 -17
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +13 -9
- package/src/resources/extensions/gsd/tests/worktree.test.ts +26 -9
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +127 -2
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +13 -3
- package/src/resources/extensions/gsd/tools/complete-slice.ts +26 -6
- package/src/resources/extensions/gsd/tools/complete-task.ts +29 -7
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +11 -9
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +5 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +27 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +17 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +37 -17
- package/src/resources/extensions/gsd/types.ts +4 -0
- package/src/resources/extensions/gsd/undo.ts +3 -2
- package/src/resources/extensions/gsd/workflow-events.ts +5 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -1
- package/src/resources/extensions/gsd/workflow-projections.ts +7 -8
- package/src/resources/extensions/gsd/workflow-reconcile.ts +109 -8
- package/src/resources/extensions/gsd/workflow-templates.ts +11 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +4 -2
- package/src/resources/extensions/gsd/worktree.ts +10 -0
- package/src/resources/extensions/shared/interview-ui.ts +1 -1
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +8 -10
- package/src/resources/extensions/subagent/agents.ts +30 -6
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
- /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → Bdk1mnQugYZh7ZxuXUYvc}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{MRM3OSYIAa4HMDqVGQ9nt → Bdk1mnQugYZh7ZxuXUYvc}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# {{milestoneId}}: {{milestoneTitle}}
|
|
2
|
+
|
|
3
|
+
**Gathered:** {{date}}
|
|
4
|
+
**Status:** Ready for planning
|
|
5
|
+
|
|
6
|
+
## Project Description
|
|
7
|
+
|
|
8
|
+
{{description}}
|
|
9
|
+
|
|
10
|
+
## Why This Milestone
|
|
11
|
+
|
|
12
|
+
{{whatProblemThisSolves_AND_whyNow}}
|
|
13
|
+
|
|
14
|
+
## Codebase Brief
|
|
15
|
+
|
|
16
|
+
### Technology Stack
|
|
17
|
+
|
|
18
|
+
{{techStack}}
|
|
19
|
+
|
|
20
|
+
### Key Modules
|
|
21
|
+
|
|
22
|
+
{{keyModules}}
|
|
23
|
+
|
|
24
|
+
### Patterns in Use
|
|
25
|
+
|
|
26
|
+
{{patternsInUse}}
|
|
27
|
+
|
|
28
|
+
## User-Visible Outcome
|
|
29
|
+
|
|
30
|
+
### When this milestone is complete, the user can:
|
|
31
|
+
|
|
32
|
+
- {{literalUserActionInRealEnvironment}}
|
|
33
|
+
- {{literalUserActionInRealEnvironment}}
|
|
34
|
+
|
|
35
|
+
### Entry point / environment
|
|
36
|
+
|
|
37
|
+
- Entry point: {{CLI command / URL / bot / extension / service / workflow}}
|
|
38
|
+
- Environment: {{local dev / browser / mobile / launchd / CI / production-like}}
|
|
39
|
+
- Live dependencies involved: {{telegram / database / webhook / rpc subprocess / none}}
|
|
40
|
+
|
|
41
|
+
## Completion Class
|
|
42
|
+
|
|
43
|
+
- Contract complete means: {{what can be proven by tests / fixtures / artifacts}}
|
|
44
|
+
- Integration complete means: {{what must work across real subsystems}}
|
|
45
|
+
- Operational complete means: {{what must work under real lifecycle conditions, or none}}
|
|
46
|
+
|
|
47
|
+
## Architectural Decisions
|
|
48
|
+
|
|
49
|
+
### {{decisionTitle}}
|
|
50
|
+
|
|
51
|
+
**Decision:** {{decisionStatement}}
|
|
52
|
+
|
|
53
|
+
**Rationale:** {{rationale}}
|
|
54
|
+
|
|
55
|
+
**Evidence:** {{evidence}}
|
|
56
|
+
|
|
57
|
+
**Alternatives Considered:**
|
|
58
|
+
- {{alternative1}} — {{whyNotChosen1}}
|
|
59
|
+
- {{alternative2}} — {{whyNotChosen2}}
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
> Add additional decisions as separate `### Decision Title` blocks following the same structure above.
|
|
64
|
+
|
|
65
|
+
## Interface Contracts
|
|
66
|
+
|
|
67
|
+
{{interfaceContracts}}
|
|
68
|
+
|
|
69
|
+
> Document API boundaries, function signatures, data shapes, or protocol agreements that must be honored. Leave blank or remove if not applicable to this milestone.
|
|
70
|
+
|
|
71
|
+
## Error Handling Strategy
|
|
72
|
+
|
|
73
|
+
{{errorHandlingStrategy}}
|
|
74
|
+
|
|
75
|
+
> Describe the approach for handling failures, edge cases, and error propagation. Include retry policies, fallback behaviors, and user-facing error messages where relevant.
|
|
76
|
+
|
|
77
|
+
## Final Integrated Acceptance
|
|
78
|
+
|
|
79
|
+
To call this milestone complete, we must prove:
|
|
80
|
+
|
|
81
|
+
- {{one real end-to-end scenario}}
|
|
82
|
+
- {{one real end-to-end scenario}}
|
|
83
|
+
- {{what cannot be simulated if this milestone is to be considered truly done}}
|
|
84
|
+
|
|
85
|
+
## Testing Requirements
|
|
86
|
+
|
|
87
|
+
{{testingRequirements}}
|
|
88
|
+
|
|
89
|
+
> Specify test types (unit, integration, e2e), coverage expectations, and any specific test scenarios that must pass.
|
|
90
|
+
|
|
91
|
+
## Acceptance Criteria
|
|
92
|
+
|
|
93
|
+
{{acceptanceCriteria}}
|
|
94
|
+
|
|
95
|
+
> Per-slice acceptance criteria gathered during discussion. Each slice should have clear, testable criteria.
|
|
96
|
+
|
|
97
|
+
## Risks and Unknowns
|
|
98
|
+
|
|
99
|
+
- {{riskOrUnknown}} — {{whyItMatters}}
|
|
100
|
+
|
|
101
|
+
## Existing Codebase / Prior Art
|
|
102
|
+
|
|
103
|
+
- `{{fileOrModule}}` — {{howItRelates}}
|
|
104
|
+
- `{{fileOrModule}}` — {{howItRelates}}
|
|
105
|
+
|
|
106
|
+
> See `.gsd/DECISIONS.md` for all architectural and pattern decisions — it is an append-only register; read it during planning, append to it during execution.
|
|
107
|
+
|
|
108
|
+
## Relevant Requirements
|
|
109
|
+
|
|
110
|
+
- {{requirementId}} — {{howThisMilestoneAdvancesIt}}
|
|
111
|
+
|
|
112
|
+
## Scope
|
|
113
|
+
|
|
114
|
+
### In Scope
|
|
115
|
+
|
|
116
|
+
- {{inScopeItem}}
|
|
117
|
+
|
|
118
|
+
### Out of Scope / Non-Goals
|
|
119
|
+
|
|
120
|
+
- {{outOfScopeItem}}
|
|
121
|
+
|
|
122
|
+
## Technical Constraints
|
|
123
|
+
|
|
124
|
+
- {{constraint}}
|
|
125
|
+
|
|
126
|
+
## Integration Points
|
|
127
|
+
|
|
128
|
+
- {{systemOrService}} — {{howThisMilestoneInteractsWithIt}}
|
|
129
|
+
|
|
130
|
+
## Ecosystem Notes
|
|
131
|
+
|
|
132
|
+
{{ecosystemNotes}}
|
|
133
|
+
|
|
134
|
+
> Research findings, best practices, known issues, and relevant external documentation discovered during preparation.
|
|
135
|
+
|
|
136
|
+
## Open Questions
|
|
137
|
+
|
|
138
|
+
- {{question}} — {{currentThinking}}
|
|
@@ -15,7 +15,7 @@ import { invalidateStateCache } from "../state.js";
|
|
|
15
15
|
import { renderAllProjections, stripIdPrefix } from "../workflow-projections.js";
|
|
16
16
|
import { writeManifest } from "../workflow-manifest.js";
|
|
17
17
|
import { appendEvent } from "../workflow-events.js";
|
|
18
|
-
import { logWarning } from "../workflow-logger.js";
|
|
18
|
+
import { logWarning, logError } from "../workflow-logger.js";
|
|
19
19
|
function renderMilestoneSummaryMarkdown(params) {
|
|
20
20
|
const now = new Date().toISOString();
|
|
21
21
|
const displayTitle = stripIdPrefix(params.title, params.milestoneId);
|
|
@@ -156,9 +156,21 @@ export async function handleCompleteMilestone(params, basePath) {
|
|
|
156
156
|
clearPathCache();
|
|
157
157
|
clearParseCache();
|
|
158
158
|
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
159
|
+
// Separate try/catch per step so a projection failure doesn't prevent
|
|
160
|
+
// the event log entry (critical for worktree reconciliation).
|
|
159
161
|
try {
|
|
160
162
|
await renderAllProjections(basePath, params.milestoneId);
|
|
163
|
+
}
|
|
164
|
+
catch (projErr) {
|
|
165
|
+
logWarning("tool", `complete-milestone projection warning: ${projErr.message}`);
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
161
168
|
writeManifest(basePath);
|
|
169
|
+
}
|
|
170
|
+
catch (mfErr) {
|
|
171
|
+
logWarning("tool", `complete-milestone manifest warning: ${mfErr.message}`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
162
174
|
appendEvent(basePath, {
|
|
163
175
|
cmd: "complete-milestone",
|
|
164
176
|
params: { milestoneId: params.milestoneId },
|
|
@@ -168,8 +180,8 @@ export async function handleCompleteMilestone(params, basePath) {
|
|
|
168
180
|
trigger_reason: params.triggerReason,
|
|
169
181
|
});
|
|
170
182
|
}
|
|
171
|
-
catch (
|
|
172
|
-
|
|
183
|
+
catch (eventErr) {
|
|
184
|
+
logError("tool", `complete-milestone event log FAILED — completion invisible to reconciliation`, { error: eventErr.message });
|
|
173
185
|
}
|
|
174
186
|
return {
|
|
175
187
|
milestoneId: params.milestoneId,
|
|
@@ -18,7 +18,7 @@ import { renderRoadmapCheckboxes } from "../markdown-renderer.js";
|
|
|
18
18
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
19
19
|
import { writeManifest } from "../workflow-manifest.js";
|
|
20
20
|
import { appendEvent } from "../workflow-events.js";
|
|
21
|
-
import { logWarning } from "../workflow-logger.js";
|
|
21
|
+
import { logWarning, logError } from "../workflow-logger.js";
|
|
22
22
|
/**
|
|
23
23
|
* Render slice summary markdown matching the template format.
|
|
24
24
|
* YAML frontmatter uses snake_case keys for parseSummary() compatibility.
|
|
@@ -187,8 +187,17 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
187
187
|
if (ownershipErr) {
|
|
188
188
|
return { error: ownershipErr };
|
|
189
189
|
}
|
|
190
|
+
// ── Verification content gate (#3580) ──────────────────────────────────
|
|
191
|
+
// Reject completion when the provided verification/UAT clearly indicates
|
|
192
|
+
// the slice is blocked or failed. Prevents prompt regressions from
|
|
193
|
+
// silently advancing blocked slices.
|
|
194
|
+
const BLOCKED_SIGNALS = /\b(status:\s*blocked|verification_result:\s*failed|slice is blocked|cannot complete|verification failed)\b/i;
|
|
195
|
+
if (BLOCKED_SIGNALS.test(params.verification || "") || BLOCKED_SIGNALS.test(params.uatContent || "")) {
|
|
196
|
+
return { error: `slice verification indicates blocked/failed state — do not complete a slice that has not passed verification. Address the blockers and re-verify first.` };
|
|
197
|
+
}
|
|
190
198
|
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
191
199
|
const completedAt = new Date().toISOString();
|
|
200
|
+
const originalSliceStatus = getSlice(params.milestoneId, params.sliceId)?.status ?? "pending";
|
|
192
201
|
let guardError = null;
|
|
193
202
|
transaction(() => {
|
|
194
203
|
// State machine preconditions (inside txn for atomicity).
|
|
@@ -217,8 +226,8 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
217
226
|
return;
|
|
218
227
|
}
|
|
219
228
|
// All guards passed — perform writes
|
|
220
|
-
insertMilestone({ id: params.milestoneId });
|
|
221
|
-
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
|
|
229
|
+
insertMilestone({ id: params.milestoneId, title: params.milestoneId });
|
|
230
|
+
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
|
|
222
231
|
updateSliceStatus(params.milestoneId, params.sliceId, "complete", completedAt);
|
|
223
232
|
});
|
|
224
233
|
if (guardError) {
|
|
@@ -256,7 +265,7 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
256
265
|
catch (renderErr) {
|
|
257
266
|
// Disk render failed — roll back DB status so state stays consistent
|
|
258
267
|
logWarning("tool", `complete_slice — disk render failed for ${params.milestoneId}/${params.sliceId}, rolling back DB status`, { error: renderErr.message });
|
|
259
|
-
updateSliceStatus(params.milestoneId, params.sliceId,
|
|
268
|
+
updateSliceStatus(params.milestoneId, params.sliceId, originalSliceStatus);
|
|
260
269
|
invalidateStateCache();
|
|
261
270
|
return { error: `disk render failed: ${renderErr.message}` };
|
|
262
271
|
}
|
|
@@ -267,9 +276,21 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
267
276
|
clearPathCache();
|
|
268
277
|
clearParseCache();
|
|
269
278
|
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
279
|
+
// Separate try/catch per step so a projection failure doesn't prevent
|
|
280
|
+
// the event log entry (critical for worktree reconciliation).
|
|
270
281
|
try {
|
|
271
282
|
await renderAllProjections(basePath, params.milestoneId);
|
|
283
|
+
}
|
|
284
|
+
catch (projErr) {
|
|
285
|
+
logWarning("tool", `complete-slice projection warning for ${params.milestoneId}/${params.sliceId}: ${projErr.message}`);
|
|
286
|
+
}
|
|
287
|
+
try {
|
|
272
288
|
writeManifest(basePath);
|
|
289
|
+
}
|
|
290
|
+
catch (mfErr) {
|
|
291
|
+
logWarning("tool", `complete-slice manifest warning: ${mfErr.message}`);
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
273
294
|
appendEvent(basePath, {
|
|
274
295
|
cmd: "complete-slice",
|
|
275
296
|
params: { milestoneId: params.milestoneId, sliceId: params.sliceId },
|
|
@@ -279,8 +300,8 @@ export async function handleCompleteSlice(params, basePath) {
|
|
|
279
300
|
trigger_reason: params.triggerReason,
|
|
280
301
|
});
|
|
281
302
|
}
|
|
282
|
-
catch (
|
|
283
|
-
|
|
303
|
+
catch (eventErr) {
|
|
304
|
+
logError("tool", `complete-slice event log FAILED — completion invisible to reconciliation`, { error: eventErr.message });
|
|
284
305
|
}
|
|
285
306
|
return {
|
|
286
307
|
sliceId: params.sliceId,
|
|
@@ -18,7 +18,19 @@ import { renderPlanCheckboxes } from "../markdown-renderer.js";
|
|
|
18
18
|
import { renderAllProjections, renderSummaryContent } from "../workflow-projections.js";
|
|
19
19
|
import { writeManifest } from "../workflow-manifest.js";
|
|
20
20
|
import { appendEvent } from "../workflow-events.js";
|
|
21
|
-
import { logWarning } from "../workflow-logger.js";
|
|
21
|
+
import { logWarning, logError } from "../workflow-logger.js";
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a list parameter that may arrive as a string (newline-delimited
|
|
24
|
+
* bullet list from the LLM) into a string array (#3361).
|
|
25
|
+
*/
|
|
26
|
+
function normalizeListParam(value) {
|
|
27
|
+
if (Array.isArray(value))
|
|
28
|
+
return value.map(String);
|
|
29
|
+
if (typeof value === "string" && value.trim()) {
|
|
30
|
+
return value.split(/\n/).map(s => s.replace(/^[\s\-*•]+/, "").trim()).filter(Boolean);
|
|
31
|
+
}
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
22
34
|
/**
|
|
23
35
|
* Build a TaskRow-shaped object from CompleteTaskParams so the unified
|
|
24
36
|
* renderSummaryContent() can be used at completion time (#2720).
|
|
@@ -38,8 +50,8 @@ function paramsToTaskRow(params, completedAt) {
|
|
|
38
50
|
blocker_discovered: params.blockerDiscovered ?? false,
|
|
39
51
|
deviations: params.deviations ?? "",
|
|
40
52
|
known_issues: params.knownIssues ?? "",
|
|
41
|
-
key_files: params.keyFiles
|
|
42
|
-
key_decisions: params.keyDecisions
|
|
53
|
+
key_files: normalizeListParam(params.keyFiles),
|
|
54
|
+
key_decisions: normalizeListParam(params.keyDecisions),
|
|
43
55
|
full_summary_md: "",
|
|
44
56
|
description: "",
|
|
45
57
|
estimate: "",
|
|
@@ -101,8 +113,8 @@ export async function handleCompleteTask(params, basePath) {
|
|
|
101
113
|
return;
|
|
102
114
|
}
|
|
103
115
|
// All guards passed — perform writes
|
|
104
|
-
insertMilestone({ id: params.milestoneId });
|
|
105
|
-
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
|
|
116
|
+
insertMilestone({ id: params.milestoneId, title: params.milestoneId });
|
|
117
|
+
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
|
|
106
118
|
insertTask({
|
|
107
119
|
id: params.taskId,
|
|
108
120
|
sliceId: params.sliceId,
|
|
@@ -182,9 +194,21 @@ export async function handleCompleteTask(params, basePath) {
|
|
|
182
194
|
clearPathCache();
|
|
183
195
|
clearParseCache();
|
|
184
196
|
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
197
|
+
// Separate try/catch per step so a projection failure doesn't prevent
|
|
198
|
+
// the event log entry (critical for worktree reconciliation).
|
|
185
199
|
try {
|
|
186
200
|
await renderAllProjections(basePath, params.milestoneId);
|
|
201
|
+
}
|
|
202
|
+
catch (projErr) {
|
|
203
|
+
logWarning("tool", `complete-task projection warning: ${projErr.message}`);
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
187
206
|
writeManifest(basePath);
|
|
207
|
+
}
|
|
208
|
+
catch (mfErr) {
|
|
209
|
+
logWarning("tool", `complete-task manifest warning: ${mfErr.message}`);
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
188
212
|
appendEvent(basePath, {
|
|
189
213
|
cmd: "complete-task",
|
|
190
214
|
params: { milestoneId: params.milestoneId, sliceId: params.sliceId, taskId: params.taskId },
|
|
@@ -194,8 +218,8 @@ export async function handleCompleteTask(params, basePath) {
|
|
|
194
218
|
trigger_reason: params.triggerReason,
|
|
195
219
|
});
|
|
196
220
|
}
|
|
197
|
-
catch (
|
|
198
|
-
|
|
221
|
+
catch (eventErr) {
|
|
222
|
+
logError("tool", `complete-task event log FAILED — completion invisible to reconciliation`, { error: eventErr.message });
|
|
199
223
|
}
|
|
200
224
|
return {
|
|
201
225
|
taskId: params.taskId,
|
|
@@ -113,10 +113,10 @@ function validateParams(params) {
|
|
|
113
113
|
successCriteria: params.successCriteria ? validateStringArray(params.successCriteria, "successCriteria") : [],
|
|
114
114
|
keyRisks: params.keyRisks ? validateRiskEntries(params.keyRisks) : [],
|
|
115
115
|
proofStrategy: params.proofStrategy ? validateProofStrategy(params.proofStrategy) : [],
|
|
116
|
-
verificationContract: params.verificationContract ?? "
|
|
117
|
-
verificationIntegration: params.verificationIntegration ?? "
|
|
118
|
-
verificationOperational: params.verificationOperational ?? "
|
|
119
|
-
verificationUat: params.verificationUat ?? "
|
|
116
|
+
verificationContract: params.verificationContract ?? "",
|
|
117
|
+
verificationIntegration: params.verificationIntegration ?? "",
|
|
118
|
+
verificationOperational: params.verificationOperational ?? "",
|
|
119
|
+
verificationUat: params.verificationUat ?? "",
|
|
120
120
|
definitionOfDone: params.definitionOfDone ? validateStringArray(params.definitionOfDone, "definitionOfDone") : [],
|
|
121
121
|
requirementCoverage: params.requirementCoverage ?? "Not provided.",
|
|
122
122
|
boundaryMapMarkdown: params.boundaryMapMarkdown ?? "Not provided.",
|
|
@@ -191,7 +191,8 @@ export async function handlePlanMilestone(rawParams, basePath) {
|
|
|
191
191
|
requirementCoverage: params.requirementCoverage,
|
|
192
192
|
boundaryMapMarkdown: params.boundaryMapMarkdown,
|
|
193
193
|
});
|
|
194
|
-
for (
|
|
194
|
+
for (let i = 0; i < params.slices.length; i++) {
|
|
195
|
+
const slice = params.slices[i];
|
|
195
196
|
// Preserve completed/done status on re-plan (#2558).
|
|
196
197
|
// Without this, a re-plan after milestone transition would reset
|
|
197
198
|
// already-completed slices back to "pending".
|
|
@@ -207,6 +208,7 @@ export async function handlePlanMilestone(rawParams, basePath) {
|
|
|
207
208
|
risk: slice.risk,
|
|
208
209
|
depends: slice.depends,
|
|
209
210
|
demo: slice.demo,
|
|
211
|
+
sequence: i + 1, // Preserve agent-ordered sequence (#3356)
|
|
210
212
|
});
|
|
211
213
|
upsertSlicePlanning(params.milestoneId, slice.sliceId, {
|
|
212
214
|
goal: slice.goal,
|
|
@@ -129,8 +129,10 @@ export async function handleReassessRoadmap(rawParams, basePath) {
|
|
|
129
129
|
demo: mod.demo,
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
|
-
// Insert new slices
|
|
133
|
-
|
|
132
|
+
// Insert new slices — assign sequence after existing slices (#3356)
|
|
133
|
+
const existingCount = getMilestoneSlices(params.milestoneId).length;
|
|
134
|
+
for (let i = 0; i < params.sliceChanges.added.length; i++) {
|
|
135
|
+
const added = params.sliceChanges.added[i];
|
|
134
136
|
insertSlice({
|
|
135
137
|
id: added.sliceId,
|
|
136
138
|
milestoneId: params.milestoneId,
|
|
@@ -139,6 +141,7 @@ export async function handleReassessRoadmap(rawParams, basePath) {
|
|
|
139
141
|
risk: added.risk,
|
|
140
142
|
depends: added.depends,
|
|
141
143
|
demo: added.demo ?? "",
|
|
144
|
+
sequence: existingCount + i + 1,
|
|
142
145
|
});
|
|
143
146
|
}
|
|
144
147
|
// Delete removed slices
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// GSD — reopen-milestone tool handler
|
|
2
|
+
/**
|
|
3
|
+
* reopen-milestone handler — the core operation behind gsd_milestone_reopen.
|
|
4
|
+
*
|
|
5
|
+
* Resets a closed milestone back to "active", all of its slices to
|
|
6
|
+
* "in_progress", and all tasks to "pending". Cleans up stale filesystem
|
|
7
|
+
* artifacts so the DB-filesystem reconciler does not auto-correct
|
|
8
|
+
* entities back to "complete".
|
|
9
|
+
*/
|
|
10
|
+
import { getMilestone, getMilestoneSlices, getSliceTasks, updateMilestoneStatus, updateSliceStatus, updateTaskStatus, transaction, } from "../gsd-db.js";
|
|
11
|
+
import { invalidateStateCache } from "../state.js";
|
|
12
|
+
import { isClosedStatus } from "../status-guards.js";
|
|
13
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
14
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
15
|
+
import { appendEvent } from "../workflow-events.js";
|
|
16
|
+
import { logWarning } from "../workflow-logger.js";
|
|
17
|
+
import { debugLog } from "../debug-logger.js";
|
|
18
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { resolveMilestonePath, resolveSlicePath, resolveTasksDir, clearPathCache } from "../paths.js";
|
|
21
|
+
export async function handleReopenMilestone(params, basePath) {
|
|
22
|
+
// ── Validate required fields ────────────────────────────────────────────
|
|
23
|
+
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
24
|
+
return { error: "milestoneId is required and must be a non-empty string" };
|
|
25
|
+
}
|
|
26
|
+
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
27
|
+
let guardError = null;
|
|
28
|
+
let slicesResetCount = 0;
|
|
29
|
+
let tasksResetCount = 0;
|
|
30
|
+
transaction(() => {
|
|
31
|
+
const milestone = getMilestone(params.milestoneId);
|
|
32
|
+
if (!milestone) {
|
|
33
|
+
guardError = `milestone not found: ${params.milestoneId}`;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!isClosedStatus(milestone.status)) {
|
|
37
|
+
guardError = `milestone ${params.milestoneId} is not closed (status: ${milestone.status}) — nothing to reopen`;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
updateMilestoneStatus(params.milestoneId, "active", null);
|
|
41
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
42
|
+
slicesResetCount = slices.length;
|
|
43
|
+
for (const slice of slices) {
|
|
44
|
+
updateSliceStatus(params.milestoneId, slice.id, "in_progress");
|
|
45
|
+
const tasks = getSliceTasks(params.milestoneId, slice.id);
|
|
46
|
+
tasksResetCount += tasks.length;
|
|
47
|
+
for (const task of tasks) {
|
|
48
|
+
updateTaskStatus(params.milestoneId, slice.id, task.id, "pending");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (guardError) {
|
|
53
|
+
return { error: guardError };
|
|
54
|
+
}
|
|
55
|
+
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
56
|
+
invalidateStateCache();
|
|
57
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
58
|
+
// Without this, the DB-filesystem reconciler sees SUMMARY.md files and
|
|
59
|
+
// auto-corrects entities back to "complete", making reopen a no-op (#3161).
|
|
60
|
+
try {
|
|
61
|
+
const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
|
|
62
|
+
if (milestoneDir) {
|
|
63
|
+
const milestoneSummary = join(milestoneDir, `${params.milestoneId}-SUMMARY.md`);
|
|
64
|
+
if (existsSync(milestoneSummary))
|
|
65
|
+
unlinkSync(milestoneSummary);
|
|
66
|
+
}
|
|
67
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
68
|
+
for (const slice of slices) {
|
|
69
|
+
const sliceDir = resolveSlicePath(basePath, params.milestoneId, slice.id);
|
|
70
|
+
if (sliceDir) {
|
|
71
|
+
const sliceSummary = join(sliceDir, `${slice.id}-SUMMARY.md`);
|
|
72
|
+
if (existsSync(sliceSummary))
|
|
73
|
+
unlinkSync(sliceSummary);
|
|
74
|
+
const sliceUat = join(sliceDir, `${slice.id}-UAT.md`);
|
|
75
|
+
if (existsSync(sliceUat))
|
|
76
|
+
unlinkSync(sliceUat);
|
|
77
|
+
}
|
|
78
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, slice.id);
|
|
79
|
+
if (tasksDir) {
|
|
80
|
+
const tasks = getSliceTasks(params.milestoneId, slice.id);
|
|
81
|
+
for (const task of tasks) {
|
|
82
|
+
const taskSummary = join(tasksDir, `${task.id}-SUMMARY.md`);
|
|
83
|
+
if (existsSync(taskSummary))
|
|
84
|
+
unlinkSync(taskSummary);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
debugLog("reopen-milestone-cleanup-failed", { milestoneId: params.milestoneId, error: String(err) });
|
|
91
|
+
}
|
|
92
|
+
clearPathCache();
|
|
93
|
+
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
94
|
+
try {
|
|
95
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
96
|
+
writeManifest(basePath);
|
|
97
|
+
appendEvent(basePath, {
|
|
98
|
+
cmd: "reopen-milestone",
|
|
99
|
+
params: {
|
|
100
|
+
milestoneId: params.milestoneId,
|
|
101
|
+
reason: params.reason ?? null,
|
|
102
|
+
slicesReset: slicesResetCount,
|
|
103
|
+
tasksReset: tasksResetCount,
|
|
104
|
+
},
|
|
105
|
+
ts: new Date().toISOString(),
|
|
106
|
+
actor: "agent",
|
|
107
|
+
actor_name: params.actorName,
|
|
108
|
+
trigger_reason: params.triggerReason,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (hookErr) {
|
|
112
|
+
logWarning("tool", `reopen-milestone post-mutation hook warning: ${hookErr.message}`);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
milestoneId: params.milestoneId,
|
|
116
|
+
slicesReset: slicesResetCount,
|
|
117
|
+
tasksReset: tasksResetCount,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
@@ -16,6 +16,9 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
16
16
|
import { writeManifest } from "../workflow-manifest.js";
|
|
17
17
|
import { appendEvent } from "../workflow-events.js";
|
|
18
18
|
import { logWarning } from "../workflow-logger.js";
|
|
19
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { resolveTasksDir, resolveSlicePath, clearPathCache } from "../paths.js";
|
|
19
22
|
export async function handleReopenSlice(params, basePath) {
|
|
20
23
|
// ── Validate required fields ────────────────────────────────────────────
|
|
21
24
|
if (!params.sliceId || typeof params.sliceId !== "string" || params.sliceId.trim() === "") {
|
|
@@ -59,6 +62,33 @@ export async function handleReopenSlice(params, basePath) {
|
|
|
59
62
|
}
|
|
60
63
|
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
61
64
|
invalidateStateCache();
|
|
65
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
66
|
+
// Without this, the DB-filesystem reconciler sees SUMMARY.md files and
|
|
67
|
+
// auto-corrects tasks back to "complete", making reopen a no-op (#3161).
|
|
68
|
+
try {
|
|
69
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
|
|
70
|
+
if (tasksDir) {
|
|
71
|
+
const tasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
72
|
+
for (const task of tasks) {
|
|
73
|
+
const summaryPath = join(tasksDir, `${task.id}-SUMMARY.md`);
|
|
74
|
+
if (existsSync(summaryPath))
|
|
75
|
+
unlinkSync(summaryPath);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const sliceDir = resolveSlicePath(basePath, params.milestoneId, params.sliceId);
|
|
79
|
+
if (sliceDir) {
|
|
80
|
+
const sliceSummary = join(sliceDir, `${params.sliceId}-SUMMARY.md`);
|
|
81
|
+
if (existsSync(sliceSummary))
|
|
82
|
+
unlinkSync(sliceSummary);
|
|
83
|
+
const sliceUat = join(sliceDir, `${params.sliceId}-UAT.md`);
|
|
84
|
+
if (existsSync(sliceUat))
|
|
85
|
+
unlinkSync(sliceUat);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (cleanupErr) {
|
|
89
|
+
logWarning("tool", `reopen-slice artifact cleanup warning: ${cleanupErr.message}`);
|
|
90
|
+
}
|
|
91
|
+
clearPathCache();
|
|
62
92
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
63
93
|
try {
|
|
64
94
|
await renderAllProjections(basePath, params.milestoneId);
|
|
@@ -15,6 +15,9 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
15
15
|
import { writeManifest } from "../workflow-manifest.js";
|
|
16
16
|
import { appendEvent } from "../workflow-events.js";
|
|
17
17
|
import { logWarning } from "../workflow-logger.js";
|
|
18
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
import { resolveTasksDir, clearPathCache } from "../paths.js";
|
|
18
21
|
export async function handleReopenTask(params, basePath) {
|
|
19
22
|
// ── Validate required fields ────────────────────────────────────────────
|
|
20
23
|
if (!params.taskId || typeof params.taskId !== "string" || params.taskId.trim() === "") {
|
|
@@ -63,6 +66,21 @@ export async function handleReopenTask(params, basePath) {
|
|
|
63
66
|
}
|
|
64
67
|
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
65
68
|
invalidateStateCache();
|
|
69
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
70
|
+
// Without this, the DB-filesystem reconciler sees the SUMMARY.md and
|
|
71
|
+
// auto-corrects the task back to "complete", making reopen a no-op (#3161).
|
|
72
|
+
try {
|
|
73
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
|
|
74
|
+
if (tasksDir) {
|
|
75
|
+
const summaryPath = join(tasksDir, `${params.taskId}-SUMMARY.md`);
|
|
76
|
+
if (existsSync(summaryPath))
|
|
77
|
+
unlinkSync(summaryPath);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (cleanupErr) {
|
|
81
|
+
logWarning("tool", `reopen-task artifact cleanup warning: ${cleanupErr.message}`);
|
|
82
|
+
}
|
|
83
|
+
clearPathCache();
|
|
66
84
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
67
85
|
try {
|
|
68
86
|
await renderAllProjections(basePath, params.milestoneId);
|