gsd-pi 2.44.0-dev.d25d507 → 2.45.0-dev.1afbdaa
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/help-text.js +1 -1
- package/dist/loader.js +34 -0
- package/dist/resources/extensions/gsd/activity-log.js +7 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +63 -77
- package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
- package/dist/resources/extensions/gsd/auto/session.js +0 -11
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-start.js +23 -5
- package/dist/resources/extensions/gsd/auto-timers.js +57 -3
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
- package/dist/resources/extensions/gsd/auto.js +42 -60
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +170 -11
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/context.js +0 -4
- package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
- package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
- package/dist/resources/extensions/gsd/db-writer.js +40 -22
- package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
- package/dist/resources/extensions/gsd/doctor.js +13 -3
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +28 -4
- package/dist/resources/extensions/gsd/guided-flow.js +1 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
- package/dist/resources/extensions/gsd/preferences-types.js +2 -2
- package/dist/resources/extensions/gsd/preferences.js +8 -4
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
- package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/rethink.md +83 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
- package/dist/resources/extensions/gsd/repo-identity.js +45 -7
- package/dist/resources/extensions/gsd/rethink.js +115 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -3
- package/dist/resources/extensions/gsd/state.js +48 -3
- package/dist/resources/extensions/gsd/sync-lock.js +89 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
- package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
- package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +31 -1
- package/dist/resources/extensions/gsd/tools/plan-task.js +28 -1
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +34 -2
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
- package/dist/resources/extensions/gsd/workflow-events.js +102 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
- package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
- package/dist/resources/extensions/gsd/write-intercept.js +84 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/resources/extensions/voice/index.js +11 -16
- package/dist/resources/extensions/voice/linux-ready.js +67 -0
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +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/4024.11ca5c01938e5948.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/{page-b9367c5ae13b99c6.js → page-6654a8cca61a3d1c.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
- package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
- package/package.json +2 -1
- package/packages/native/dist/stream-process/index.js +2 -2
- package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
- package/packages/native/src/stream-process/index.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +17 -0
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +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 +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.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 +7 -3
- 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/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
- package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/main.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/activity-log.ts +1 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
- package/src/resources/extensions/gsd/auto/phases.ts +69 -91
- package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
- package/src/resources/extensions/gsd/auto/session.ts +0 -18
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-start.ts +26 -5
- package/src/resources/extensions/gsd/auto-timers.ts +64 -3
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
- package/src/resources/extensions/gsd/auto.ts +44 -86
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +162 -11
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/context.ts +0 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
- package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
- package/src/resources/extensions/gsd/db-writer.ts +41 -27
- package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
- package/src/resources/extensions/gsd/doctor-types.ts +7 -1
- package/src/resources/extensions/gsd/doctor.ts +13 -4
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +32 -4
- package/src/resources/extensions/gsd/guided-flow.ts +1 -2
- package/src/resources/extensions/gsd/journal.ts +6 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
- package/src/resources/extensions/gsd/preferences-types.ts +2 -2
- package/src/resources/extensions/gsd/preferences.ts +7 -3
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/src/resources/extensions/gsd/prompts/queue.md +2 -2
- package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/rethink.md +83 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/repo-identity.ts +46 -7
- package/src/resources/extensions/gsd/rethink.ts +154 -0
- package/src/resources/extensions/gsd/session-lock.ts +0 -4
- package/src/resources/extensions/gsd/state.ts +49 -1
- package/src/resources/extensions/gsd/sync-lock.ts +94 -0
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
- package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
- package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +26 -21
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
- package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
- package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +40 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +37 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +41 -1
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/types.ts +8 -0
- package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
- package/src/resources/extensions/gsd/workflow-events.ts +154 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
- package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
- package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
- package/src/resources/extensions/gsd/write-intercept.ts +90 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- package/src/resources/extensions/voice/index.ts +11 -21
- package/src/resources/extensions/voice/linux-ready.ts +87 -0
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
- package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
- package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
- package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
- /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_ssgManifest.js +0 -0
|
@@ -17,12 +17,19 @@ import {
|
|
|
17
17
|
insertSlice,
|
|
18
18
|
insertTask,
|
|
19
19
|
insertVerificationEvidence,
|
|
20
|
+
getMilestone,
|
|
21
|
+
getSlice,
|
|
22
|
+
getTask,
|
|
20
23
|
_getAdapter,
|
|
21
24
|
} from "../gsd-db.js";
|
|
22
25
|
import { resolveSliceFile, resolveTasksDir, clearPathCache } from "../paths.js";
|
|
26
|
+
import { checkOwnership, taskUnitKey } from "../unit-ownership.js";
|
|
23
27
|
import { saveFile, clearParseCache } from "../files.js";
|
|
24
28
|
import { invalidateStateCache } from "../state.js";
|
|
25
29
|
import { renderPlanCheckboxes } from "../markdown-renderer.js";
|
|
30
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
31
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
32
|
+
import { appendEvent } from "../workflow-events.js";
|
|
26
33
|
|
|
27
34
|
export interface CompleteTaskResult {
|
|
28
35
|
taskId: string;
|
|
@@ -131,10 +138,43 @@ export async function handleCompleteTask(
|
|
|
131
138
|
return { error: "milestoneId is required and must be a non-empty string" };
|
|
132
139
|
}
|
|
133
140
|
|
|
134
|
-
// ──
|
|
141
|
+
// ── Ownership check (opt-in: only enforced when claim file exists) ──────
|
|
142
|
+
const ownershipErr = checkOwnership(
|
|
143
|
+
basePath,
|
|
144
|
+
taskUnitKey(params.milestoneId, params.sliceId, params.taskId),
|
|
145
|
+
params.actorName,
|
|
146
|
+
);
|
|
147
|
+
if (ownershipErr) {
|
|
148
|
+
return { error: ownershipErr };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
135
152
|
const completedAt = new Date().toISOString();
|
|
153
|
+
let guardError: string | null = null;
|
|
136
154
|
|
|
137
155
|
transaction(() => {
|
|
156
|
+
// State machine preconditions (inside txn for atomicity).
|
|
157
|
+
// Milestone/slice not existing is OK — insertMilestone/insertSlice below will auto-create.
|
|
158
|
+
// Only block if they exist and are closed.
|
|
159
|
+
const milestone = getMilestone(params.milestoneId);
|
|
160
|
+
if (milestone && (milestone.status === "complete" || milestone.status === "done")) {
|
|
161
|
+
guardError = `cannot complete task in a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const slice = getSlice(params.milestoneId, params.sliceId);
|
|
166
|
+
if (slice && (slice.status === "complete" || slice.status === "done")) {
|
|
167
|
+
guardError = `cannot complete task in a closed slice: ${params.sliceId} (status: ${slice.status})`;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
|
|
172
|
+
if (existingTask && (existingTask.status === "complete" || existingTask.status === "done")) {
|
|
173
|
+
guardError = `task ${params.taskId} is already complete — use gsd_task_reopen first if you need to redo it`;
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// All guards passed — perform writes
|
|
138
178
|
insertMilestone({ id: params.milestoneId });
|
|
139
179
|
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
|
|
140
180
|
insertTask({
|
|
@@ -167,6 +207,10 @@ export async function handleCompleteTask(
|
|
|
167
207
|
}
|
|
168
208
|
});
|
|
169
209
|
|
|
210
|
+
if (guardError) {
|
|
211
|
+
return { error: guardError };
|
|
212
|
+
}
|
|
213
|
+
|
|
170
214
|
// ── Filesystem operations (outside transaction) ─────────────────────────
|
|
171
215
|
// If disk render fails, roll back the DB status so deriveState() and
|
|
172
216
|
// verifyExpectedArtifact() stay consistent (both say "not done").
|
|
@@ -236,6 +280,24 @@ export async function handleCompleteTask(
|
|
|
236
280
|
clearPathCache();
|
|
237
281
|
clearParseCache();
|
|
238
282
|
|
|
283
|
+
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
284
|
+
try {
|
|
285
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
286
|
+
writeManifest(basePath);
|
|
287
|
+
appendEvent(basePath, {
|
|
288
|
+
cmd: "complete-task",
|
|
289
|
+
params: { milestoneId: params.milestoneId, sliceId: params.sliceId, taskId: params.taskId },
|
|
290
|
+
ts: new Date().toISOString(),
|
|
291
|
+
actor: "agent",
|
|
292
|
+
actor_name: params.actorName,
|
|
293
|
+
trigger_reason: params.triggerReason,
|
|
294
|
+
});
|
|
295
|
+
} catch (hookErr) {
|
|
296
|
+
process.stderr.write(
|
|
297
|
+
`gsd: complete-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
239
301
|
return {
|
|
240
302
|
taskId: params.taskId,
|
|
241
303
|
sliceId: params.sliceId,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { clearParseCache } from "../files.js";
|
|
2
2
|
import {
|
|
3
3
|
transaction,
|
|
4
|
+
getMilestone,
|
|
4
5
|
insertMilestone,
|
|
5
6
|
insertSlice,
|
|
6
7
|
upsertMilestonePlanning,
|
|
@@ -9,6 +10,9 @@ import {
|
|
|
9
10
|
} from "../gsd-db.js";
|
|
10
11
|
import { invalidateStateCache } from "../state.js";
|
|
11
12
|
import { renderRoadmapFromDb } from "../markdown-renderer.js";
|
|
13
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
14
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
15
|
+
import { appendEvent } from "../workflow-events.js";
|
|
12
16
|
|
|
13
17
|
export interface PlanMilestoneSliceInput {
|
|
14
18
|
sliceId: string;
|
|
@@ -28,6 +32,10 @@ export interface PlanMilestoneParams {
|
|
|
28
32
|
title: string;
|
|
29
33
|
status?: string;
|
|
30
34
|
dependsOn?: string[];
|
|
35
|
+
/** Optional caller-provided identity for audit trail */
|
|
36
|
+
actorName?: string;
|
|
37
|
+
/** Optional caller-provided reason this action was triggered */
|
|
38
|
+
triggerReason?: string;
|
|
31
39
|
vision: string;
|
|
32
40
|
successCriteria: string[];
|
|
33
41
|
keyRisks: Array<{ risk: string; whyItMatters: string }>;
|
|
@@ -181,6 +189,25 @@ export async function handlePlanMilestone(
|
|
|
181
189
|
return { error: `validation failed: ${(err as Error).message}` };
|
|
182
190
|
}
|
|
183
191
|
|
|
192
|
+
// ── State machine preconditions ─────────────────────────────────────────
|
|
193
|
+
const existingMilestone = getMilestone(params.milestoneId);
|
|
194
|
+
if (existingMilestone && (existingMilestone.status === "complete" || existingMilestone.status === "done")) {
|
|
195
|
+
return { error: `cannot re-plan milestone ${params.milestoneId}: it is already complete` };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Validate depends_on: all dependencies must exist and be complete
|
|
199
|
+
if (params.dependsOn && params.dependsOn.length > 0) {
|
|
200
|
+
for (const depId of params.dependsOn) {
|
|
201
|
+
const dep = getMilestone(depId);
|
|
202
|
+
if (!dep) {
|
|
203
|
+
return { error: `depends_on references unknown milestone: ${depId}` };
|
|
204
|
+
}
|
|
205
|
+
if (dep.status !== "complete" && dep.status !== "done") {
|
|
206
|
+
return { error: `depends_on milestone ${depId} is not yet complete (status: ${dep.status})` };
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
184
211
|
try {
|
|
185
212
|
transaction(() => {
|
|
186
213
|
insertMilestone({
|
|
@@ -242,6 +269,24 @@ export async function handlePlanMilestone(
|
|
|
242
269
|
invalidateStateCache();
|
|
243
270
|
clearParseCache();
|
|
244
271
|
|
|
272
|
+
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
273
|
+
try {
|
|
274
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
275
|
+
writeManifest(basePath);
|
|
276
|
+
appendEvent(basePath, {
|
|
277
|
+
cmd: "plan-milestone",
|
|
278
|
+
params: { milestoneId: params.milestoneId },
|
|
279
|
+
ts: new Date().toISOString(),
|
|
280
|
+
actor: "agent",
|
|
281
|
+
actor_name: params.actorName,
|
|
282
|
+
trigger_reason: params.triggerReason,
|
|
283
|
+
});
|
|
284
|
+
} catch (hookErr) {
|
|
285
|
+
process.stderr.write(
|
|
286
|
+
`gsd: plan-milestone post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
245
290
|
return {
|
|
246
291
|
milestoneId: params.milestoneId,
|
|
247
292
|
roadmapPath,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { clearParseCache } from "../files.js";
|
|
2
2
|
import {
|
|
3
3
|
transaction,
|
|
4
|
+
getMilestone,
|
|
4
5
|
getSlice,
|
|
5
6
|
insertTask,
|
|
6
7
|
upsertSlicePlanning,
|
|
@@ -9,6 +10,9 @@ import {
|
|
|
9
10
|
} from "../gsd-db.js";
|
|
10
11
|
import { invalidateStateCache } from "../state.js";
|
|
11
12
|
import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
13
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
14
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
15
|
+
import { appendEvent } from "../workflow-events.js";
|
|
12
16
|
|
|
13
17
|
export interface PlanSliceTaskInput {
|
|
14
18
|
taskId: string;
|
|
@@ -20,6 +24,7 @@ export interface PlanSliceTaskInput {
|
|
|
20
24
|
inputs: string[];
|
|
21
25
|
expectedOutput: string[];
|
|
22
26
|
observabilityImpact?: string;
|
|
27
|
+
fullPlanMd?: string;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export interface PlanSliceParams {
|
|
@@ -31,6 +36,10 @@ export interface PlanSliceParams {
|
|
|
31
36
|
integrationClosure: string;
|
|
32
37
|
observabilityImpact: string;
|
|
33
38
|
tasks: PlanSliceTaskInput[];
|
|
39
|
+
/** Optional caller-provided identity for audit trail */
|
|
40
|
+
actorName?: string;
|
|
41
|
+
/** Optional caller-provided reason this action was triggered */
|
|
42
|
+
triggerReason?: string;
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
export interface PlanSliceResult {
|
|
@@ -135,10 +144,21 @@ export async function handlePlanSlice(
|
|
|
135
144
|
return { error: `validation failed: ${(err as Error).message}` };
|
|
136
145
|
}
|
|
137
146
|
|
|
147
|
+
const parentMilestone = getMilestone(params.milestoneId);
|
|
148
|
+
if (!parentMilestone) {
|
|
149
|
+
return { error: `milestone not found: ${params.milestoneId}` };
|
|
150
|
+
}
|
|
151
|
+
if (parentMilestone.status === "complete" || parentMilestone.status === "done") {
|
|
152
|
+
return { error: `cannot plan slice in a closed milestone: ${params.milestoneId} (status: ${parentMilestone.status})` };
|
|
153
|
+
}
|
|
154
|
+
|
|
138
155
|
const parentSlice = getSlice(params.milestoneId, params.sliceId);
|
|
139
156
|
if (!parentSlice) {
|
|
140
157
|
return { error: `missing parent slice: ${params.milestoneId}/${params.sliceId}` };
|
|
141
158
|
}
|
|
159
|
+
if (parentSlice.status === "complete" || parentSlice.status === "done") {
|
|
160
|
+
return { error: `cannot re-plan slice ${params.sliceId}: it is already complete — use gsd_slice_reopen first` };
|
|
161
|
+
}
|
|
142
162
|
|
|
143
163
|
try {
|
|
144
164
|
transaction(() => {
|
|
@@ -167,6 +187,7 @@ export async function handlePlanSlice(
|
|
|
167
187
|
inputs: task.inputs,
|
|
168
188
|
expectedOutput: task.expectedOutput,
|
|
169
189
|
observabilityImpact: task.observabilityImpact ?? "",
|
|
190
|
+
fullPlanMd: task.fullPlanMd,
|
|
170
191
|
});
|
|
171
192
|
}
|
|
172
193
|
});
|
|
@@ -178,6 +199,25 @@ export async function handlePlanSlice(
|
|
|
178
199
|
const renderResult = await renderPlanFromDb(basePath, params.milestoneId, params.sliceId);
|
|
179
200
|
invalidateStateCache();
|
|
180
201
|
clearParseCache();
|
|
202
|
+
|
|
203
|
+
// ── Post-mutation hook: projections, manifest, event log ─────────────
|
|
204
|
+
try {
|
|
205
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
206
|
+
writeManifest(basePath);
|
|
207
|
+
appendEvent(basePath, {
|
|
208
|
+
cmd: "plan-slice",
|
|
209
|
+
params: { milestoneId: params.milestoneId, sliceId: params.sliceId },
|
|
210
|
+
ts: new Date().toISOString(),
|
|
211
|
+
actor: "agent",
|
|
212
|
+
actor_name: params.actorName,
|
|
213
|
+
trigger_reason: params.triggerReason,
|
|
214
|
+
});
|
|
215
|
+
} catch (hookErr) {
|
|
216
|
+
process.stderr.write(
|
|
217
|
+
`gsd: plan-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
181
221
|
return {
|
|
182
222
|
milestoneId: params.milestoneId,
|
|
183
223
|
sliceId: params.sliceId,
|
|
@@ -2,6 +2,9 @@ import { clearParseCache } from "../files.js";
|
|
|
2
2
|
import { transaction, getSlice, getTask, insertTask, upsertTaskPlanning } from "../gsd-db.js";
|
|
3
3
|
import { invalidateStateCache } from "../state.js";
|
|
4
4
|
import { renderTaskPlanFromDb } from "../markdown-renderer.js";
|
|
5
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
6
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
7
|
+
import { appendEvent } from "../workflow-events.js";
|
|
5
8
|
|
|
6
9
|
export interface PlanTaskParams {
|
|
7
10
|
milestoneId: string;
|
|
@@ -15,6 +18,11 @@ export interface PlanTaskParams {
|
|
|
15
18
|
inputs: string[];
|
|
16
19
|
expectedOutput: string[];
|
|
17
20
|
observabilityImpact?: string;
|
|
21
|
+
fullPlanMd?: string;
|
|
22
|
+
/** Optional caller-provided identity for audit trail */
|
|
23
|
+
actorName?: string;
|
|
24
|
+
/** Optional caller-provided reason this action was triggered */
|
|
25
|
+
triggerReason?: string;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
export interface PlanTaskResult {
|
|
@@ -73,10 +81,18 @@ export async function handlePlanTask(
|
|
|
73
81
|
if (!parentSlice) {
|
|
74
82
|
return { error: `missing parent slice: ${params.milestoneId}/${params.sliceId}` };
|
|
75
83
|
}
|
|
84
|
+
if (parentSlice.status === "complete" || parentSlice.status === "done") {
|
|
85
|
+
return { error: `cannot plan task in a closed slice: ${params.sliceId} (status: ${parentSlice.status})` };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const existingTask = getTask(params.milestoneId, params.sliceId, params.taskId);
|
|
89
|
+
if (existingTask && (existingTask.status === "complete" || existingTask.status === "done")) {
|
|
90
|
+
return { error: `cannot re-plan task ${params.taskId}: it is already complete — use gsd_task_reopen first` };
|
|
91
|
+
}
|
|
76
92
|
|
|
77
93
|
try {
|
|
78
94
|
transaction(() => {
|
|
79
|
-
if (!
|
|
95
|
+
if (!existingTask) {
|
|
80
96
|
insertTask({
|
|
81
97
|
id: params.taskId,
|
|
82
98
|
sliceId: params.sliceId,
|
|
@@ -94,6 +110,7 @@ export async function handlePlanTask(
|
|
|
94
110
|
inputs: params.inputs,
|
|
95
111
|
expectedOutput: params.expectedOutput,
|
|
96
112
|
observabilityImpact: params.observabilityImpact ?? "",
|
|
113
|
+
fullPlanMd: params.fullPlanMd,
|
|
97
114
|
});
|
|
98
115
|
});
|
|
99
116
|
} catch (err) {
|
|
@@ -104,6 +121,25 @@ export async function handlePlanTask(
|
|
|
104
121
|
const renderResult = await renderTaskPlanFromDb(basePath, params.milestoneId, params.sliceId, params.taskId);
|
|
105
122
|
invalidateStateCache();
|
|
106
123
|
clearParseCache();
|
|
124
|
+
|
|
125
|
+
// ── Post-mutation hook: projections, manifest, event log ─────────────
|
|
126
|
+
try {
|
|
127
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
128
|
+
writeManifest(basePath);
|
|
129
|
+
appendEvent(basePath, {
|
|
130
|
+
cmd: "plan-task",
|
|
131
|
+
params: { milestoneId: params.milestoneId, sliceId: params.sliceId, taskId: params.taskId },
|
|
132
|
+
ts: new Date().toISOString(),
|
|
133
|
+
actor: "agent",
|
|
134
|
+
actor_name: params.actorName,
|
|
135
|
+
trigger_reason: params.triggerReason,
|
|
136
|
+
});
|
|
137
|
+
} catch (hookErr) {
|
|
138
|
+
process.stderr.write(
|
|
139
|
+
`gsd: plan-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
107
143
|
return {
|
|
108
144
|
milestoneId: params.milestoneId,
|
|
109
145
|
sliceId: params.sliceId,
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
transaction,
|
|
4
4
|
getMilestone,
|
|
5
5
|
getMilestoneSlices,
|
|
6
|
+
getSlice,
|
|
6
7
|
insertSlice,
|
|
7
8
|
updateSliceFields,
|
|
8
9
|
insertAssessment,
|
|
@@ -10,6 +11,9 @@ import {
|
|
|
10
11
|
} from "../gsd-db.js";
|
|
11
12
|
import { invalidateStateCache } from "../state.js";
|
|
12
13
|
import { renderRoadmapFromDb, renderAssessmentFromDb } from "../markdown-renderer.js";
|
|
14
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
15
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
16
|
+
import { appendEvent } from "../workflow-events.js";
|
|
13
17
|
import { join } from "node:path";
|
|
14
18
|
|
|
15
19
|
export interface SliceChangeInput {
|
|
@@ -30,6 +34,10 @@ export interface ReassessRoadmapParams {
|
|
|
30
34
|
added: SliceChangeInput[];
|
|
31
35
|
removed: string[];
|
|
32
36
|
};
|
|
37
|
+
/** Optional caller-provided identity for audit trail */
|
|
38
|
+
actorName?: string;
|
|
39
|
+
/** Optional caller-provided reason this action was triggered */
|
|
40
|
+
triggerReason?: string;
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
export interface ReassessRoadmapResult {
|
|
@@ -96,11 +104,23 @@ export async function handleReassessRoadmap(
|
|
|
96
104
|
return { error: `validation failed: ${(err as Error).message}` };
|
|
97
105
|
}
|
|
98
106
|
|
|
99
|
-
// ── Verify milestone exists
|
|
107
|
+
// ── Verify milestone exists and is active ────────────────────────
|
|
100
108
|
const milestone = getMilestone(params.milestoneId);
|
|
101
109
|
if (!milestone) {
|
|
102
110
|
return { error: `milestone not found: ${params.milestoneId}` };
|
|
103
111
|
}
|
|
112
|
+
if (milestone.status === "complete" || milestone.status === "done") {
|
|
113
|
+
return { error: `cannot reassess a closed milestone: ${params.milestoneId} (status: ${milestone.status})` };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ── Verify completedSliceId is actually complete ──────────────────
|
|
117
|
+
const completedSlice = getSlice(params.milestoneId, params.completedSliceId);
|
|
118
|
+
if (!completedSlice) {
|
|
119
|
+
return { error: `completedSliceId not found: ${params.milestoneId}/${params.completedSliceId}` };
|
|
120
|
+
}
|
|
121
|
+
if (completedSlice.status !== "complete" && completedSlice.status !== "done") {
|
|
122
|
+
return { error: `completedSliceId ${params.completedSliceId} is not complete (status: ${completedSlice.status}) — reassess can only be called after a slice finishes` };
|
|
123
|
+
}
|
|
104
124
|
|
|
105
125
|
// ── Structural enforcement ────────────────────────────────────────
|
|
106
126
|
const existingSlices = getMilestoneSlices(params.milestoneId);
|
|
@@ -191,6 +211,24 @@ export async function handleReassessRoadmap(
|
|
|
191
211
|
invalidateStateCache();
|
|
192
212
|
clearParseCache();
|
|
193
213
|
|
|
214
|
+
// ── Post-mutation hook: projections, manifest, event log ─────
|
|
215
|
+
try {
|
|
216
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
217
|
+
writeManifest(basePath);
|
|
218
|
+
appendEvent(basePath, {
|
|
219
|
+
cmd: "reassess-roadmap",
|
|
220
|
+
params: { milestoneId: params.milestoneId, completedSliceId: params.completedSliceId },
|
|
221
|
+
ts: new Date().toISOString(),
|
|
222
|
+
actor: "agent",
|
|
223
|
+
actor_name: params.actorName,
|
|
224
|
+
trigger_reason: params.triggerReason,
|
|
225
|
+
});
|
|
226
|
+
} catch (hookErr) {
|
|
227
|
+
process.stderr.write(
|
|
228
|
+
`gsd: reassess-roadmap post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
194
232
|
return {
|
|
195
233
|
milestoneId: params.milestoneId,
|
|
196
234
|
completedSliceId: params.completedSliceId,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reopen-slice handler — the core operation behind gsd_slice_reopen.
|
|
3
|
+
*
|
|
4
|
+
* Resets a completed slice back to "in_progress" and resets ALL of its
|
|
5
|
+
* tasks back to "pending". This is intentional — if you're reopening a
|
|
6
|
+
* slice, you're re-doing the work. Partial resets create ambiguous state.
|
|
7
|
+
*
|
|
8
|
+
* The parent milestone must still be open (not complete).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// GSD — reopen-slice tool handler
|
|
12
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
getMilestone,
|
|
16
|
+
getSlice,
|
|
17
|
+
getSliceTasks,
|
|
18
|
+
updateSliceStatus,
|
|
19
|
+
updateTaskStatus,
|
|
20
|
+
transaction,
|
|
21
|
+
} from "../gsd-db.js";
|
|
22
|
+
import { invalidateStateCache } from "../state.js";
|
|
23
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
24
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
25
|
+
import { appendEvent } from "../workflow-events.js";
|
|
26
|
+
|
|
27
|
+
export interface ReopenSliceParams {
|
|
28
|
+
milestoneId: string;
|
|
29
|
+
sliceId: string;
|
|
30
|
+
reason?: string;
|
|
31
|
+
/** Optional caller-provided identity for audit trail */
|
|
32
|
+
actorName?: string;
|
|
33
|
+
/** Optional caller-provided reason this action was triggered */
|
|
34
|
+
triggerReason?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface ReopenSliceResult {
|
|
38
|
+
milestoneId: string;
|
|
39
|
+
sliceId: string;
|
|
40
|
+
tasksReset: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function handleReopenSlice(
|
|
44
|
+
params: ReopenSliceParams,
|
|
45
|
+
basePath: string,
|
|
46
|
+
): Promise<ReopenSliceResult | { error: string }> {
|
|
47
|
+
// ── Validate required fields ────────────────────────────────────────────
|
|
48
|
+
if (!params.sliceId || typeof params.sliceId !== "string" || params.sliceId.trim() === "") {
|
|
49
|
+
return { error: "sliceId is required and must be a non-empty string" };
|
|
50
|
+
}
|
|
51
|
+
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
52
|
+
return { error: "milestoneId is required and must be a non-empty string" };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
56
|
+
let guardError: string | null = null;
|
|
57
|
+
let tasksResetCount = 0;
|
|
58
|
+
|
|
59
|
+
transaction(() => {
|
|
60
|
+
const milestone = getMilestone(params.milestoneId);
|
|
61
|
+
if (!milestone) {
|
|
62
|
+
guardError = `milestone not found: ${params.milestoneId}`;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (milestone.status === "complete" || milestone.status === "done") {
|
|
66
|
+
guardError = `cannot reopen slice inside a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const slice = getSlice(params.milestoneId, params.sliceId);
|
|
71
|
+
if (!slice) {
|
|
72
|
+
guardError = `slice not found: ${params.milestoneId}/${params.sliceId}`;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (slice.status !== "complete" && slice.status !== "done") {
|
|
76
|
+
guardError = `slice ${params.sliceId} is not complete (status: ${slice.status}) — nothing to reopen`;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Fetch tasks inside txn so the list is consistent with the slice status check
|
|
81
|
+
const tasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
82
|
+
tasksResetCount = tasks.length;
|
|
83
|
+
|
|
84
|
+
updateSliceStatus(params.milestoneId, params.sliceId, "in_progress");
|
|
85
|
+
for (const task of tasks) {
|
|
86
|
+
updateTaskStatus(params.milestoneId, params.sliceId, task.id, "pending");
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (guardError) {
|
|
91
|
+
return { error: guardError };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
95
|
+
invalidateStateCache();
|
|
96
|
+
|
|
97
|
+
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
98
|
+
try {
|
|
99
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
100
|
+
writeManifest(basePath);
|
|
101
|
+
appendEvent(basePath, {
|
|
102
|
+
cmd: "reopen-slice",
|
|
103
|
+
params: {
|
|
104
|
+
milestoneId: params.milestoneId,
|
|
105
|
+
sliceId: params.sliceId,
|
|
106
|
+
reason: params.reason ?? null,
|
|
107
|
+
tasksReset: tasksResetCount,
|
|
108
|
+
},
|
|
109
|
+
ts: new Date().toISOString(),
|
|
110
|
+
actor: "agent",
|
|
111
|
+
actor_name: params.actorName,
|
|
112
|
+
trigger_reason: params.triggerReason,
|
|
113
|
+
});
|
|
114
|
+
} catch (hookErr) {
|
|
115
|
+
process.stderr.write(
|
|
116
|
+
`gsd: reopen-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
milestoneId: params.milestoneId,
|
|
122
|
+
sliceId: params.sliceId,
|
|
123
|
+
tasksReset: tasksResetCount,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reopen-task handler — the core operation behind gsd_task_reopen.
|
|
3
|
+
*
|
|
4
|
+
* Resets a completed task back to "pending" so it can be re-done
|
|
5
|
+
* without manual SQL surgery. The parent slice and milestone must
|
|
6
|
+
* still be open (not complete) — you cannot reopen tasks inside a
|
|
7
|
+
* closed slice.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// GSD — reopen-task tool handler
|
|
11
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
getMilestone,
|
|
15
|
+
getSlice,
|
|
16
|
+
getTask,
|
|
17
|
+
updateTaskStatus,
|
|
18
|
+
transaction,
|
|
19
|
+
} from "../gsd-db.js";
|
|
20
|
+
import { invalidateStateCache } from "../state.js";
|
|
21
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
22
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
23
|
+
import { appendEvent } from "../workflow-events.js";
|
|
24
|
+
|
|
25
|
+
export interface ReopenTaskParams {
|
|
26
|
+
milestoneId: string;
|
|
27
|
+
sliceId: string;
|
|
28
|
+
taskId: string;
|
|
29
|
+
reason?: string;
|
|
30
|
+
/** Optional caller-provided identity for audit trail */
|
|
31
|
+
actorName?: string;
|
|
32
|
+
/** Optional caller-provided reason this action was triggered */
|
|
33
|
+
triggerReason?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ReopenTaskResult {
|
|
37
|
+
milestoneId: string;
|
|
38
|
+
sliceId: string;
|
|
39
|
+
taskId: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function handleReopenTask(
|
|
43
|
+
params: ReopenTaskParams,
|
|
44
|
+
basePath: string,
|
|
45
|
+
): Promise<ReopenTaskResult | { error: string }> {
|
|
46
|
+
// ── Validate required fields ────────────────────────────────────────────
|
|
47
|
+
if (!params.taskId || typeof params.taskId !== "string" || params.taskId.trim() === "") {
|
|
48
|
+
return { error: "taskId is required and must be a non-empty string" };
|
|
49
|
+
}
|
|
50
|
+
if (!params.sliceId || typeof params.sliceId !== "string" || params.sliceId.trim() === "") {
|
|
51
|
+
return { error: "sliceId is required and must be a non-empty string" };
|
|
52
|
+
}
|
|
53
|
+
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
54
|
+
return { error: "milestoneId is required and must be a non-empty string" };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Guards + DB write inside a single transaction (prevents TOCTOU) ────
|
|
58
|
+
let guardError: string | null = null;
|
|
59
|
+
|
|
60
|
+
transaction(() => {
|
|
61
|
+
const milestone = getMilestone(params.milestoneId);
|
|
62
|
+
if (!milestone) {
|
|
63
|
+
guardError = `milestone not found: ${params.milestoneId}`;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (milestone.status === "complete" || milestone.status === "done") {
|
|
67
|
+
guardError = `cannot reopen task in a closed milestone: ${params.milestoneId} (status: ${milestone.status})`;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const slice = getSlice(params.milestoneId, params.sliceId);
|
|
72
|
+
if (!slice) {
|
|
73
|
+
guardError = `slice not found: ${params.milestoneId}/${params.sliceId}`;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (slice.status === "complete" || slice.status === "done") {
|
|
77
|
+
guardError = `cannot reopen task inside a closed slice: ${params.sliceId} (status: ${slice.status}) — use gsd_slice_reopen first`;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const task = getTask(params.milestoneId, params.sliceId, params.taskId);
|
|
82
|
+
if (!task) {
|
|
83
|
+
guardError = `task not found: ${params.milestoneId}/${params.sliceId}/${params.taskId}`;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (task.status !== "complete" && task.status !== "done") {
|
|
87
|
+
guardError = `task ${params.taskId} is not complete (status: ${task.status}) — nothing to reopen`;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
updateTaskStatus(params.milestoneId, params.sliceId, params.taskId, "pending");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (guardError) {
|
|
95
|
+
return { error: guardError };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
99
|
+
invalidateStateCache();
|
|
100
|
+
|
|
101
|
+
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
102
|
+
try {
|
|
103
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
104
|
+
writeManifest(basePath);
|
|
105
|
+
appendEvent(basePath, {
|
|
106
|
+
cmd: "reopen-task",
|
|
107
|
+
params: {
|
|
108
|
+
milestoneId: params.milestoneId,
|
|
109
|
+
sliceId: params.sliceId,
|
|
110
|
+
taskId: params.taskId,
|
|
111
|
+
reason: params.reason ?? null,
|
|
112
|
+
},
|
|
113
|
+
ts: new Date().toISOString(),
|
|
114
|
+
actor: "agent",
|
|
115
|
+
actor_name: params.actorName,
|
|
116
|
+
trigger_reason: params.triggerReason,
|
|
117
|
+
});
|
|
118
|
+
} catch (hookErr) {
|
|
119
|
+
process.stderr.write(
|
|
120
|
+
`gsd: reopen-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
milestoneId: params.milestoneId,
|
|
126
|
+
sliceId: params.sliceId,
|
|
127
|
+
taskId: params.taskId,
|
|
128
|
+
};
|
|
129
|
+
}
|