gsd-pi 2.64.0-dev.f8aad9b → 2.65.0-dev.16e10d7
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/headless.js +3 -1
- package/dist/mcp-server.js +6 -2
- package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +22 -7
- package/dist/resources/extensions/bg-shell/process-manager.js +6 -1
- 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/run-unit.js +13 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +94 -8
- package/dist/resources/extensions/gsd/auto-model-selection.js +7 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +115 -7
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +12 -8
- package/dist/resources/extensions/gsd/auto-start.js +35 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +10 -0
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +29 -7
- package/dist/resources/extensions/gsd/auto.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +34 -13
- package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -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 +12 -1
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +16 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/context.js +8 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +21 -0
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- 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/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/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +220 -29
- package/dist/resources/extensions/gsd/md-importer.js +14 -7
- package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
- package/dist/resources/extensions/gsd/notification-store.js +273 -0
- package/dist/resources/extensions/gsd/notification-widget.js +56 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +17 -11
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +471 -0
- package/dist/resources/extensions/gsd/preferences-types.js +7 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +78 -1
- package/dist/resources/extensions/gsd/preferences.js +13 -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/guided-discuss-milestone.md +4 -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/rethink.md +2 -1
- 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 +100 -12
- package/dist/resources/extensions/gsd/templates/context-enhanced.md +138 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +12 -3
- package/dist/resources/extensions/gsd/tools/complete-task.js +16 -4
- 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 +25 -9
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +4 -7
- package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -4
- 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/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
- 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/routes-manifest.json +6 -0
- 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/api/notifications/route.js +3 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -0
- 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 +18 -17
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- 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/Z3TgDP0c7kG9j8CVQVGcl/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/6502.8874bcae249c02e1.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/notifications/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-a1c1e452c6b32d04.js → webpack-9fed74684e1c5bb1.js} +1 -1
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +26 -9
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +100 -4
- package/packages/pi-agent-core/src/agent-loop.ts +43 -12
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +38 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +11 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +4 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +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 +2 -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 +28 -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 +6 -0
- 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 +40 -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/agent-session-tool-refresh.test.ts +64 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +10 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +42 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +5 -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 +29 -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 +38 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -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/components/loader.d.ts +4 -2
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +27 -9
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/text.js +2 -0
- package/packages/pi-tui/dist/components/text.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +12 -1
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +4 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +35 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
- 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/components/loader.ts +27 -10
- package/packages/pi-tui/src/components/text.ts +1 -0
- package/packages/pi-tui/src/overlay-layout.ts +13 -1
- package/packages/pi-tui/src/tui.ts +34 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
- package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
- 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/run-unit.ts +12 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +105 -8
- package/src/resources/extensions/gsd/auto-model-selection.ts +7 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +138 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +31 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-start.ts +38 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +10 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +28 -7
- package/src/resources/extensions/gsd/auto.ts +2 -1
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +16 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +35 -13
- package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -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 +12 -1
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/context.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +24 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- 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/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/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/gsd-db.ts +13 -2
- package/src/resources/extensions/gsd/guided-flow.ts +254 -30
- package/src/resources/extensions/gsd/md-importer.ts +13 -6
- package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
- package/src/resources/extensions/gsd/notification-store.ts +293 -0
- package/src/resources/extensions/gsd/notification-widget.ts +68 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +19 -11
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +581 -0
- package/src/resources/extensions/gsd/preferences-types.ts +53 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +78 -1
- package/src/resources/extensions/gsd/preferences.ts +13 -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/guided-discuss-milestone.md +4 -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/rethink.md +2 -1
- 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 +101 -11
- 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-string-coercion.test.ts +36 -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/discuss-tool-scope-leak.test.ts +76 -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/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +48 -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 +5 -3
- 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/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/notification-overlay.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -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/post-exec-retry-bypass.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +813 -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 +1197 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +266 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +457 -0
- 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/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/unstructured-continue-context-injection.test.ts +163 -0
- 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/worker-model-override.test.ts +48 -0
- 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/zero-slice-roadmap-guided.test.ts +19 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +13 -3
- package/src/resources/extensions/gsd/tools/complete-task.ts +16 -4
- 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 +29 -10
- package/src/resources/extensions/gsd/types.ts +4 -0
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +4 -6
- package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -3
- 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/dist/web/standalone/.next/static/F1mOwzgCW9R8N3Pt1Et87/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/boot/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/experimental/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-c4cc189e7b117ea2.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-c4cc189e7b117ea2.js +0 -1
- /package/dist/web/standalone/.next/static/{F1mOwzgCW9R8N3Pt1Et87 → Z3TgDP0c7kG9j8CVQVGcl}/_ssgManifest.js +0 -0
|
@@ -233,8 +233,18 @@ export async function handleCompleteSlice(
|
|
|
233
233
|
return { error: ownershipErr };
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
+
// ── Verification content gate (#3580) ──────────────────────────────────
|
|
237
|
+
// Reject completion when the provided verification/UAT clearly indicates
|
|
238
|
+
// the slice is blocked or failed. Prevents prompt regressions from
|
|
239
|
+
// silently advancing blocked slices.
|
|
240
|
+
const BLOCKED_SIGNALS = /\b(status:\s*blocked|verification_result:\s*failed|slice is blocked|cannot complete|verification failed)\b/i;
|
|
241
|
+
if (BLOCKED_SIGNALS.test(params.verification || "") || BLOCKED_SIGNALS.test(params.uatContent || "")) {
|
|
242
|
+
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.` };
|
|
243
|
+
}
|
|
244
|
+
|
|
236
245
|
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
237
246
|
const completedAt = new Date().toISOString();
|
|
247
|
+
const originalSliceStatus = getSlice(params.milestoneId, params.sliceId)?.status ?? "pending";
|
|
238
248
|
let guardError: string | null = null;
|
|
239
249
|
|
|
240
250
|
transaction(() => {
|
|
@@ -268,8 +278,8 @@ export async function handleCompleteSlice(
|
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
// All guards passed — perform writes
|
|
271
|
-
insertMilestone({ id: params.milestoneId });
|
|
272
|
-
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
|
|
281
|
+
insertMilestone({ id: params.milestoneId, title: params.milestoneId });
|
|
282
|
+
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
|
|
273
283
|
updateSliceStatus(params.milestoneId, params.sliceId, "complete", completedAt);
|
|
274
284
|
});
|
|
275
285
|
|
|
@@ -312,7 +322,7 @@ export async function handleCompleteSlice(
|
|
|
312
322
|
} catch (renderErr) {
|
|
313
323
|
// Disk render failed — roll back DB status so state stays consistent
|
|
314
324
|
logWarning("tool", `complete_slice — disk render failed for ${params.milestoneId}/${params.sliceId}, rolling back DB status`, { error: (renderErr as Error).message });
|
|
315
|
-
updateSliceStatus(params.milestoneId, params.sliceId,
|
|
325
|
+
updateSliceStatus(params.milestoneId, params.sliceId, originalSliceStatus);
|
|
316
326
|
invalidateStateCache();
|
|
317
327
|
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
318
328
|
}
|
|
@@ -44,6 +44,18 @@ export interface CompleteTaskResult {
|
|
|
44
44
|
|
|
45
45
|
import type { TaskRow } from "../gsd-db.js";
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a list parameter that may arrive as a string (newline-delimited
|
|
49
|
+
* bullet list from the LLM) into a string array (#3361).
|
|
50
|
+
*/
|
|
51
|
+
function normalizeListParam(value: unknown): string[] {
|
|
52
|
+
if (Array.isArray(value)) return value.map(String);
|
|
53
|
+
if (typeof value === "string" && value.trim()) {
|
|
54
|
+
return value.split(/\n/).map(s => s.replace(/^[\s\-*•]+/, "").trim()).filter(Boolean);
|
|
55
|
+
}
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
47
59
|
/**
|
|
48
60
|
* Build a TaskRow-shaped object from CompleteTaskParams so the unified
|
|
49
61
|
* renderSummaryContent() can be used at completion time (#2720).
|
|
@@ -63,8 +75,8 @@ function paramsToTaskRow(params: CompleteTaskParams, completedAt: string): TaskR
|
|
|
63
75
|
blocker_discovered: params.blockerDiscovered ?? false,
|
|
64
76
|
deviations: params.deviations ?? "",
|
|
65
77
|
known_issues: params.knownIssues ?? "",
|
|
66
|
-
key_files: params.keyFiles
|
|
67
|
-
key_decisions: params.keyDecisions
|
|
78
|
+
key_files: normalizeListParam(params.keyFiles),
|
|
79
|
+
key_decisions: normalizeListParam(params.keyDecisions),
|
|
68
80
|
full_summary_md: "",
|
|
69
81
|
description: "",
|
|
70
82
|
estimate: "",
|
|
@@ -140,8 +152,8 @@ export async function handleCompleteTask(
|
|
|
140
152
|
}
|
|
141
153
|
|
|
142
154
|
// All guards passed — perform writes
|
|
143
|
-
insertMilestone({ id: params.milestoneId });
|
|
144
|
-
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId });
|
|
155
|
+
insertMilestone({ id: params.milestoneId, title: params.milestoneId });
|
|
156
|
+
insertSlice({ id: params.sliceId, milestoneId: params.milestoneId, title: params.sliceId });
|
|
145
157
|
insertTask({
|
|
146
158
|
id: params.taskId,
|
|
147
159
|
sliceId: params.sliceId,
|
|
@@ -48,13 +48,13 @@ export interface PlanMilestoneParams {
|
|
|
48
48
|
keyRisks?: Array<{ risk: string; whyItMatters: string }>;
|
|
49
49
|
/** @optional — defaults to [] when omitted */
|
|
50
50
|
proofStrategy?: Array<{ riskOrUnknown: string; retireIn: string; whatWillBeProven: string }>;
|
|
51
|
-
/** @optional — defaults to "
|
|
51
|
+
/** @optional — defaults to "" when omitted */
|
|
52
52
|
verificationContract?: string;
|
|
53
|
-
/** @optional — defaults to "
|
|
53
|
+
/** @optional — defaults to "" when omitted */
|
|
54
54
|
verificationIntegration?: string;
|
|
55
|
-
/** @optional — defaults to "
|
|
55
|
+
/** @optional — defaults to "" when omitted */
|
|
56
56
|
verificationOperational?: string;
|
|
57
|
-
/** @optional — defaults to "
|
|
57
|
+
/** @optional — defaults to "" when omitted */
|
|
58
58
|
verificationUat?: string;
|
|
59
59
|
/** @optional — defaults to [] when omitted */
|
|
60
60
|
definitionOfDone?: string[];
|
|
@@ -168,10 +168,10 @@ function validateParams(params: PlanMilestoneParams): PlanMilestoneParams {
|
|
|
168
168
|
successCriteria: params.successCriteria ? validateStringArray(params.successCriteria, "successCriteria") : [],
|
|
169
169
|
keyRisks: params.keyRisks ? validateRiskEntries(params.keyRisks) : [],
|
|
170
170
|
proofStrategy: params.proofStrategy ? validateProofStrategy(params.proofStrategy) : [],
|
|
171
|
-
verificationContract: params.verificationContract ?? "
|
|
172
|
-
verificationIntegration: params.verificationIntegration ?? "
|
|
173
|
-
verificationOperational: params.verificationOperational ?? "
|
|
174
|
-
verificationUat: params.verificationUat ?? "
|
|
171
|
+
verificationContract: params.verificationContract ?? "",
|
|
172
|
+
verificationIntegration: params.verificationIntegration ?? "",
|
|
173
|
+
verificationOperational: params.verificationOperational ?? "",
|
|
174
|
+
verificationUat: params.verificationUat ?? "",
|
|
175
175
|
definitionOfDone: params.definitionOfDone ? validateStringArray(params.definitionOfDone, "definitionOfDone") : [],
|
|
176
176
|
requirementCoverage: params.requirementCoverage ?? "Not provided.",
|
|
177
177
|
boundaryMapMarkdown: params.boundaryMapMarkdown ?? "Not provided.",
|
|
@@ -256,7 +256,8 @@ export async function handlePlanMilestone(
|
|
|
256
256
|
boundaryMapMarkdown: params.boundaryMapMarkdown,
|
|
257
257
|
});
|
|
258
258
|
|
|
259
|
-
for (
|
|
259
|
+
for (let i = 0; i < params.slices.length; i++) {
|
|
260
|
+
const slice = params.slices[i]!;
|
|
260
261
|
// Preserve completed/done status on re-plan (#2558).
|
|
261
262
|
// Without this, a re-plan after milestone transition would reset
|
|
262
263
|
// already-completed slices back to "pending".
|
|
@@ -272,6 +273,7 @@ export async function handlePlanMilestone(
|
|
|
272
273
|
risk: slice.risk,
|
|
273
274
|
depends: slice.depends,
|
|
274
275
|
demo: slice.demo,
|
|
276
|
+
sequence: i + 1, // Preserve agent-ordered sequence (#3356)
|
|
275
277
|
});
|
|
276
278
|
upsertSlicePlanning(params.milestoneId, slice.sliceId, {
|
|
277
279
|
goal: slice.goal,
|
|
@@ -186,8 +186,10 @@ export async function handleReassessRoadmap(
|
|
|
186
186
|
});
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
// Insert new slices
|
|
190
|
-
|
|
189
|
+
// Insert new slices — assign sequence after existing slices (#3356)
|
|
190
|
+
const existingCount = getMilestoneSlices(params.milestoneId).length;
|
|
191
|
+
for (let i = 0; i < params.sliceChanges.added.length; i++) {
|
|
192
|
+
const added = params.sliceChanges.added[i]!;
|
|
191
193
|
insertSlice({
|
|
192
194
|
id: added.sliceId,
|
|
193
195
|
milestoneId: params.milestoneId,
|
|
@@ -196,6 +198,7 @@ export async function handleReassessRoadmap(
|
|
|
196
198
|
risk: added.risk,
|
|
197
199
|
depends: added.depends,
|
|
198
200
|
demo: added.demo ?? "",
|
|
201
|
+
sequence: existingCount + i + 1,
|
|
199
202
|
});
|
|
200
203
|
}
|
|
201
204
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// GSD — reopen-milestone tool handler
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* reopen-milestone handler — the core operation behind gsd_milestone_reopen.
|
|
5
|
+
*
|
|
6
|
+
* Resets a closed milestone back to "active", all of its slices to
|
|
7
|
+
* "in_progress", and all tasks to "pending". Cleans up stale filesystem
|
|
8
|
+
* artifacts so the DB-filesystem reconciler does not auto-correct
|
|
9
|
+
* entities back to "complete".
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
getMilestone,
|
|
14
|
+
getMilestoneSlices,
|
|
15
|
+
getSliceTasks,
|
|
16
|
+
updateMilestoneStatus,
|
|
17
|
+
updateSliceStatus,
|
|
18
|
+
updateTaskStatus,
|
|
19
|
+
transaction,
|
|
20
|
+
} from "../gsd-db.js";
|
|
21
|
+
import { invalidateStateCache } from "../state.js";
|
|
22
|
+
import { isClosedStatus } from "../status-guards.js";
|
|
23
|
+
import { renderAllProjections } from "../workflow-projections.js";
|
|
24
|
+
import { writeManifest } from "../workflow-manifest.js";
|
|
25
|
+
import { appendEvent } from "../workflow-events.js";
|
|
26
|
+
import { logWarning } from "../workflow-logger.js";
|
|
27
|
+
import { debugLog } from "../debug-logger.js";
|
|
28
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { resolveMilestonePath, resolveSlicePath, resolveTasksDir, clearPathCache } from "../paths.js";
|
|
31
|
+
|
|
32
|
+
export interface ReopenMilestoneParams {
|
|
33
|
+
milestoneId: string;
|
|
34
|
+
reason?: string;
|
|
35
|
+
/** Optional caller-provided identity for audit trail */
|
|
36
|
+
actorName?: string;
|
|
37
|
+
/** Optional caller-provided reason this action was triggered */
|
|
38
|
+
triggerReason?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ReopenMilestoneResult {
|
|
42
|
+
milestoneId: string;
|
|
43
|
+
slicesReset: number;
|
|
44
|
+
tasksReset: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function handleReopenMilestone(
|
|
48
|
+
params: ReopenMilestoneParams,
|
|
49
|
+
basePath: string,
|
|
50
|
+
): Promise<ReopenMilestoneResult | { error: string }> {
|
|
51
|
+
// ── Validate required fields ────────────────────────────────────────────
|
|
52
|
+
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
53
|
+
return { error: "milestoneId is required and must be a non-empty string" };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
57
|
+
let guardError: string | null = null;
|
|
58
|
+
let slicesResetCount = 0;
|
|
59
|
+
let tasksResetCount = 0;
|
|
60
|
+
|
|
61
|
+
transaction(() => {
|
|
62
|
+
const milestone = getMilestone(params.milestoneId);
|
|
63
|
+
if (!milestone) {
|
|
64
|
+
guardError = `milestone not found: ${params.milestoneId}`;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!isClosedStatus(milestone.status)) {
|
|
68
|
+
guardError = `milestone ${params.milestoneId} is not closed (status: ${milestone.status}) — nothing to reopen`;
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
updateMilestoneStatus(params.milestoneId, "active", null);
|
|
73
|
+
|
|
74
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
75
|
+
slicesResetCount = slices.length;
|
|
76
|
+
|
|
77
|
+
for (const slice of slices) {
|
|
78
|
+
updateSliceStatus(params.milestoneId, slice.id, "in_progress");
|
|
79
|
+
const tasks = getSliceTasks(params.milestoneId, slice.id);
|
|
80
|
+
tasksResetCount += tasks.length;
|
|
81
|
+
for (const task of tasks) {
|
|
82
|
+
updateTaskStatus(params.milestoneId, slice.id, task.id, "pending");
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (guardError) {
|
|
88
|
+
return { error: guardError };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
92
|
+
invalidateStateCache();
|
|
93
|
+
|
|
94
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
95
|
+
// Without this, the DB-filesystem reconciler sees SUMMARY.md files and
|
|
96
|
+
// auto-corrects entities back to "complete", making reopen a no-op (#3161).
|
|
97
|
+
try {
|
|
98
|
+
const milestoneDir = resolveMilestonePath(basePath, params.milestoneId);
|
|
99
|
+
if (milestoneDir) {
|
|
100
|
+
const milestoneSummary = join(milestoneDir, `${params.milestoneId}-SUMMARY.md`);
|
|
101
|
+
if (existsSync(milestoneSummary)) unlinkSync(milestoneSummary);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
105
|
+
for (const slice of slices) {
|
|
106
|
+
const sliceDir = resolveSlicePath(basePath, params.milestoneId, slice.id);
|
|
107
|
+
if (sliceDir) {
|
|
108
|
+
const sliceSummary = join(sliceDir, `${slice.id}-SUMMARY.md`);
|
|
109
|
+
if (existsSync(sliceSummary)) unlinkSync(sliceSummary);
|
|
110
|
+
const sliceUat = join(sliceDir, `${slice.id}-UAT.md`);
|
|
111
|
+
if (existsSync(sliceUat)) unlinkSync(sliceUat);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, slice.id);
|
|
115
|
+
if (tasksDir) {
|
|
116
|
+
const tasks = getSliceTasks(params.milestoneId, slice.id);
|
|
117
|
+
for (const task of tasks) {
|
|
118
|
+
const taskSummary = join(tasksDir, `${task.id}-SUMMARY.md`);
|
|
119
|
+
if (existsSync(taskSummary)) unlinkSync(taskSummary);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} catch (err) { debugLog("reopen-milestone-cleanup-failed", { milestoneId: params.milestoneId, error: String(err) }); }
|
|
124
|
+
clearPathCache();
|
|
125
|
+
|
|
126
|
+
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
127
|
+
try {
|
|
128
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
129
|
+
writeManifest(basePath);
|
|
130
|
+
appendEvent(basePath, {
|
|
131
|
+
cmd: "reopen-milestone",
|
|
132
|
+
params: {
|
|
133
|
+
milestoneId: params.milestoneId,
|
|
134
|
+
reason: params.reason ?? null,
|
|
135
|
+
slicesReset: slicesResetCount,
|
|
136
|
+
tasksReset: tasksResetCount,
|
|
137
|
+
},
|
|
138
|
+
ts: new Date().toISOString(),
|
|
139
|
+
actor: "agent",
|
|
140
|
+
actor_name: params.actorName,
|
|
141
|
+
trigger_reason: params.triggerReason,
|
|
142
|
+
});
|
|
143
|
+
} catch (hookErr) {
|
|
144
|
+
logWarning("tool", `reopen-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
milestoneId: params.milestoneId,
|
|
149
|
+
slicesReset: slicesResetCount,
|
|
150
|
+
tasksReset: tasksResetCount,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -25,6 +25,9 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
25
25
|
import { writeManifest } from "../workflow-manifest.js";
|
|
26
26
|
import { appendEvent } from "../workflow-events.js";
|
|
27
27
|
import { logWarning } from "../workflow-logger.js";
|
|
28
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { resolveTasksDir, resolveSlicePath, clearPathCache } from "../paths.js";
|
|
28
31
|
|
|
29
32
|
export interface ReopenSliceParams {
|
|
30
33
|
milestoneId: string;
|
|
@@ -96,6 +99,30 @@ export async function handleReopenSlice(
|
|
|
96
99
|
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
97
100
|
invalidateStateCache();
|
|
98
101
|
|
|
102
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
103
|
+
// Without this, the DB-filesystem reconciler sees SUMMARY.md files and
|
|
104
|
+
// auto-corrects tasks back to "complete", making reopen a no-op (#3161).
|
|
105
|
+
try {
|
|
106
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
|
|
107
|
+
if (tasksDir) {
|
|
108
|
+
const tasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
109
|
+
for (const task of tasks) {
|
|
110
|
+
const summaryPath = join(tasksDir, `${task.id}-SUMMARY.md`);
|
|
111
|
+
if (existsSync(summaryPath)) unlinkSync(summaryPath);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const sliceDir = resolveSlicePath(basePath, params.milestoneId, params.sliceId);
|
|
115
|
+
if (sliceDir) {
|
|
116
|
+
const sliceSummary = join(sliceDir, `${params.sliceId}-SUMMARY.md`);
|
|
117
|
+
if (existsSync(sliceSummary)) unlinkSync(sliceSummary);
|
|
118
|
+
const sliceUat = join(sliceDir, `${params.sliceId}-UAT.md`);
|
|
119
|
+
if (existsSync(sliceUat)) unlinkSync(sliceUat);
|
|
120
|
+
}
|
|
121
|
+
} catch (cleanupErr) {
|
|
122
|
+
logWarning("tool", `reopen-slice artifact cleanup warning: ${(cleanupErr as Error).message}`);
|
|
123
|
+
}
|
|
124
|
+
clearPathCache();
|
|
125
|
+
|
|
99
126
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
100
127
|
try {
|
|
101
128
|
await renderAllProjections(basePath, params.milestoneId);
|
|
@@ -23,6 +23,9 @@ import { renderAllProjections } from "../workflow-projections.js";
|
|
|
23
23
|
import { writeManifest } from "../workflow-manifest.js";
|
|
24
24
|
import { appendEvent } from "../workflow-events.js";
|
|
25
25
|
import { logWarning } from "../workflow-logger.js";
|
|
26
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
27
|
+
import { join } from "node:path";
|
|
28
|
+
import { resolveTasksDir, clearPathCache } from "../paths.js";
|
|
26
29
|
|
|
27
30
|
export interface ReopenTaskParams {
|
|
28
31
|
milestoneId: string;
|
|
@@ -100,6 +103,20 @@ export async function handleReopenTask(
|
|
|
100
103
|
// ── Invalidate caches ────────────────────────────────────────────────────
|
|
101
104
|
invalidateStateCache();
|
|
102
105
|
|
|
106
|
+
// ── Clean up stale filesystem artifacts (M12 fix) ────────────────────────
|
|
107
|
+
// Without this, the DB-filesystem reconciler sees the SUMMARY.md and
|
|
108
|
+
// auto-corrects the task back to "complete", making reopen a no-op (#3161).
|
|
109
|
+
try {
|
|
110
|
+
const tasksDir = resolveTasksDir(basePath, params.milestoneId, params.sliceId);
|
|
111
|
+
if (tasksDir) {
|
|
112
|
+
const summaryPath = join(tasksDir, `${params.taskId}-SUMMARY.md`);
|
|
113
|
+
if (existsSync(summaryPath)) unlinkSync(summaryPath);
|
|
114
|
+
}
|
|
115
|
+
} catch (cleanupErr) {
|
|
116
|
+
logWarning("tool", `reopen-task artifact cleanup warning: ${(cleanupErr as Error).message}`);
|
|
117
|
+
}
|
|
118
|
+
clearPathCache();
|
|
119
|
+
|
|
103
120
|
// ── Post-mutation hook ───────────────────────────────────────────────────
|
|
104
121
|
try {
|
|
105
122
|
await renderAllProjections(basePath, params.milestoneId);
|
|
@@ -479,15 +479,18 @@ export function executeTriageResolutions(
|
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
-
// Also process deferred
|
|
483
|
-
// milestone
|
|
484
|
-
|
|
485
|
-
|
|
482
|
+
// Also process deferred and milestone-class captures (#3542).
|
|
483
|
+
// A defer/milestone capture's "action" is the triage decision itself —
|
|
484
|
+
// once classified and resolved, the capture is done. The target milestone
|
|
485
|
+
// picks up the work naturally from its planning context.
|
|
486
|
+
const deferrable = loadAllCaptures(basePath).filter(
|
|
487
|
+
c => c.status === "resolved" && !c.executed &&
|
|
488
|
+
(c.classification === "defer" || (c.classification as string) === "milestone"),
|
|
486
489
|
);
|
|
487
|
-
if (
|
|
488
|
-
// Group
|
|
490
|
+
if (deferrable.length > 0) {
|
|
491
|
+
// Group captures that reference a specific milestone — create dirs as needed.
|
|
489
492
|
const byMilestone = new Map<string, CaptureEntry[]>();
|
|
490
|
-
for (const cap of
|
|
493
|
+
for (const cap of deferrable) {
|
|
491
494
|
const target = cap.resolution?.match(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/)?.[1];
|
|
492
495
|
if (target) {
|
|
493
496
|
const list = byMilestone.get(target) ?? [];
|
|
@@ -502,12 +505,28 @@ export function executeTriageResolutions(
|
|
|
502
505
|
if (created) {
|
|
503
506
|
result.deferredMilestones++;
|
|
504
507
|
result.actions.push(`Created milestone ${milestoneId} for ${captures.length} deferred capture(s)`);
|
|
505
|
-
for (const cap of captures) {
|
|
506
|
-
markCaptureExecuted(basePath, cap.id);
|
|
507
|
-
}
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
510
|
}
|
|
511
|
+
// Stamp ALL defer/milestone captures as executed (#3542 gaps 1-3).
|
|
512
|
+
// Previously only captures that triggered dir creation were stamped.
|
|
513
|
+
// Captures without a milestone ID in resolution text, or targeting an
|
|
514
|
+
// existing directory, were silently dropped — never stamped.
|
|
515
|
+
for (const cap of deferrable) {
|
|
516
|
+
if (!cap.executed) {
|
|
517
|
+
markCaptureExecuted(basePath, cap.id);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Mark note captures as executed — they're informational only, no action
|
|
523
|
+
// needed. Without this they stay in "resolved but not executed" limbo (#3578).
|
|
524
|
+
const notes = loadAllCaptures(basePath).filter(
|
|
525
|
+
c => c.status === "resolved" && !c.executed && c.classification === "note",
|
|
526
|
+
);
|
|
527
|
+
for (const cap of notes) {
|
|
528
|
+
markCaptureExecuted(basePath, cap.id);
|
|
529
|
+
result.actions.push(`Note acknowledged: ${cap.id} — "${cap.text}"`);
|
|
511
530
|
}
|
|
512
531
|
|
|
513
532
|
if (actionable.length === 0) return result;
|
|
@@ -453,6 +453,8 @@ export interface ParallelConfig {
|
|
|
453
453
|
budget_ceiling?: number;
|
|
454
454
|
merge_strategy: MergeStrategy;
|
|
455
455
|
auto_merge: AutoMergeMode;
|
|
456
|
+
/** Optional model override for parallel milestone workers (e.g. "claude-haiku-4-5"). */
|
|
457
|
+
worker_model?: string;
|
|
456
458
|
}
|
|
457
459
|
|
|
458
460
|
// ─── Reactive Task Execution Types ───────────────────────────────────────
|
|
@@ -479,6 +481,8 @@ export interface ReactiveExecutionConfig {
|
|
|
479
481
|
max_parallel: number;
|
|
480
482
|
/** Isolation mode for parallel tasks within a slice. Currently only "same-tree" is supported. */
|
|
481
483
|
isolation_mode: "same-tree";
|
|
484
|
+
/** Optional model override for subagents spawned during parallel execution. */
|
|
485
|
+
subagent_model?: string;
|
|
482
486
|
}
|
|
483
487
|
|
|
484
488
|
/** Per-slice reactive execution runtime state, persisted to disk. */
|
|
@@ -52,6 +52,32 @@ export interface BrowserEvidenceJSON {
|
|
|
52
52
|
duration: number;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
export interface PreExecutionCheckJSON {
|
|
56
|
+
/** Check category: package, file, tool, endpoint, schema */
|
|
57
|
+
category: "package" | "file" | "tool" | "endpoint" | "schema";
|
|
58
|
+
/** What was checked (e.g., package name, file path) */
|
|
59
|
+
target: string;
|
|
60
|
+
/** Whether the check passed */
|
|
61
|
+
passed: boolean;
|
|
62
|
+
/** Human-readable message explaining the result */
|
|
63
|
+
message: string;
|
|
64
|
+
/** Whether this failure should block execution (only meaningful when passed=false) */
|
|
65
|
+
blocking?: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PostExecutionCheckJSON {
|
|
69
|
+
/** Check category: import, signature, pattern */
|
|
70
|
+
category: "import" | "signature" | "pattern";
|
|
71
|
+
/** What was checked (e.g., file:line, function name) */
|
|
72
|
+
target: string;
|
|
73
|
+
/** Whether the check passed */
|
|
74
|
+
passed: boolean;
|
|
75
|
+
/** Human-readable message explaining the result */
|
|
76
|
+
message: string;
|
|
77
|
+
/** Whether this failure should block completion (only meaningful when passed=false) */
|
|
78
|
+
blocking?: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
55
81
|
export interface EvidenceJSON {
|
|
56
82
|
schemaVersion: 1;
|
|
57
83
|
taskId: string;
|
|
@@ -65,6 +91,10 @@ export interface EvidenceJSON {
|
|
|
65
91
|
runtimeErrors?: RuntimeErrorJSON[];
|
|
66
92
|
auditWarnings?: AuditWarningJSON[];
|
|
67
93
|
browser?: BrowserEvidenceJSON;
|
|
94
|
+
/** Pre-execution checks run before task execution (package existence, file refs, etc.) */
|
|
95
|
+
preExecutionChecks?: PreExecutionCheckJSON[];
|
|
96
|
+
/** Post-execution checks run after task completion (import resolution, signature drift, pattern consistency) */
|
|
97
|
+
postExecutionChecks?: PostExecutionCheckJSON[];
|
|
68
98
|
}
|
|
69
99
|
|
|
70
100
|
/**
|
|
@@ -124,6 +154,44 @@ export function writeVerificationJSON(
|
|
|
124
154
|
writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
|
|
125
155
|
}
|
|
126
156
|
|
|
157
|
+
// ─── Pre-Execution Evidence ──────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
export interface PreExecutionEvidenceJSON {
|
|
160
|
+
schemaVersion: 1;
|
|
161
|
+
milestoneId: string;
|
|
162
|
+
sliceId: string;
|
|
163
|
+
timestamp: number;
|
|
164
|
+
status: "pass" | "warn" | "fail";
|
|
165
|
+
durationMs: number;
|
|
166
|
+
checks: PreExecutionCheckJSON[];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Write pre-execution check results to a PRE-EXEC-VERIFY.json artifact
|
|
171
|
+
* in the slice directory.
|
|
172
|
+
*/
|
|
173
|
+
export function writePreExecutionEvidence(
|
|
174
|
+
result: { status: "pass" | "warn" | "fail"; checks: PreExecutionCheckJSON[]; durationMs: number },
|
|
175
|
+
sliceDir: string,
|
|
176
|
+
milestoneId: string,
|
|
177
|
+
sliceId: string,
|
|
178
|
+
): void {
|
|
179
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
180
|
+
|
|
181
|
+
const evidence: PreExecutionEvidenceJSON = {
|
|
182
|
+
schemaVersion: 1,
|
|
183
|
+
milestoneId,
|
|
184
|
+
sliceId,
|
|
185
|
+
timestamp: Date.now(),
|
|
186
|
+
status: result.status,
|
|
187
|
+
durationMs: result.durationMs,
|
|
188
|
+
checks: result.checks,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const filePath = join(sliceDir, `${sliceId}-PRE-EXEC-VERIFY.json`);
|
|
192
|
+
writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
|
|
193
|
+
}
|
|
194
|
+
|
|
127
195
|
// ─── Markdown Evidence Table ─────────────────────────────────────────────────
|
|
128
196
|
|
|
129
197
|
/**
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
|
|
22
|
+
import { appendNotification } from "./notification-store.js";
|
|
23
|
+
|
|
22
24
|
// ─── Types ──────────────────────────────────────────────────────────────
|
|
23
25
|
|
|
24
26
|
export type LogSeverity = "warn" | "error";
|
|
@@ -245,6 +247,17 @@ function _push(
|
|
|
245
247
|
const ctxStr = context ? ` ${JSON.stringify(context)}` : "";
|
|
246
248
|
process.stderr.write(`[gsd:${component}] ${prefix}: ${message}${ctxStr}\n`);
|
|
247
249
|
|
|
250
|
+
// Persist to notification store (both warnings and errors)
|
|
251
|
+
try {
|
|
252
|
+
appendNotification(
|
|
253
|
+
`[${component}] ${message}`,
|
|
254
|
+
severity === "error" ? "error" : "warning",
|
|
255
|
+
"workflow-logger",
|
|
256
|
+
);
|
|
257
|
+
} catch (notifErr) {
|
|
258
|
+
process.stderr.write(`[gsd:workflow-logger] notification-store append failed: ${(notifErr as Error).message}\n`);
|
|
259
|
+
}
|
|
260
|
+
|
|
248
261
|
// Buffer for auto-loop to drain
|
|
249
262
|
_buffer.push(entry);
|
|
250
263
|
if (_buffer.length > MAX_BUFFER) {
|
|
@@ -370,12 +370,10 @@ export async function renderAllProjections(basePath: string, milestoneId: string
|
|
|
370
370
|
const sliceRows = getMilestoneSlices(milestoneId);
|
|
371
371
|
|
|
372
372
|
for (const slice of sliceRows) {
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
logWarning("projection", `renderPlanProjection failed for ${milestoneId}/${slice.id}: ${(err as Error).message}`);
|
|
378
|
-
}
|
|
373
|
+
// PLAN.md is rendered by the authoritative markdown-renderer.js in
|
|
374
|
+
// plan-slice/replan-slice tools. Do NOT overwrite it here — the simplified
|
|
375
|
+
// projection is missing key sections (Must-Haves, Verification, Files
|
|
376
|
+
// Likely Touched) and corrupts multi-line task descriptions (#3651).
|
|
379
377
|
|
|
380
378
|
// Render SUMMARY.md for each completed task
|
|
381
379
|
const taskRows = getSliceTasks(milestoneId, slice.id);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
insertVerificationEvidence,
|
|
12
12
|
upsertDecision,
|
|
13
13
|
openDatabase,
|
|
14
|
+
setTaskBlockerDiscovered,
|
|
14
15
|
} from "./gsd-db.js";
|
|
15
16
|
import { isClosedStatus } from "./status-guards.js";
|
|
16
17
|
import { writeManifest } from "./workflow-manifest.js";
|
|
@@ -89,13 +90,11 @@ function replayEvents(events: WorkflowEvent[]): void {
|
|
|
89
90
|
break;
|
|
90
91
|
}
|
|
91
92
|
case "report_blocker": {
|
|
92
|
-
// report_blocker marks the task with blocker_discovered = 1
|
|
93
|
-
// The DB helper updateTaskStatus doesn't handle blockers,
|
|
94
|
-
// so we just update status to "blocked" as a best-effort replay.
|
|
95
93
|
const milestoneId = p["milestoneId"] as string;
|
|
96
94
|
const sliceId = p["sliceId"] as string;
|
|
97
95
|
const taskId = p["taskId"] as string;
|
|
98
96
|
updateTaskStatus(milestoneId, sliceId, taskId, "blocked");
|
|
97
|
+
setTaskBlockerDiscovered(milestoneId, sliceId, taskId, true);
|
|
99
98
|
break;
|
|
100
99
|
}
|
|
101
100
|
case "record_verification": {
|
|
@@ -58,8 +58,17 @@ let cachedRegistry: TemplateRegistry | null = null;
|
|
|
58
58
|
export function loadRegistry(): TemplateRegistry {
|
|
59
59
|
if (cachedRegistry) return cachedRegistry;
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
if (!existsSync(registryPath)) {
|
|
62
|
+
cachedRegistry = { version: 1, templates: {} };
|
|
63
|
+
return cachedRegistry;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const content = readFileSync(registryPath, "utf-8");
|
|
68
|
+
cachedRegistry = JSON.parse(content) as TemplateRegistry;
|
|
69
|
+
} catch {
|
|
70
|
+
cachedRegistry = { version: 1, templates: {} };
|
|
71
|
+
}
|
|
63
72
|
return cachedRegistry;
|
|
64
73
|
}
|
|
65
74
|
|
|
@@ -89,7 +89,9 @@ function normalizePathForComparison(path: string): string {
|
|
|
89
89
|
*/
|
|
90
90
|
export function resolveGitDir(basePath: string): string {
|
|
91
91
|
const gitPath = join(basePath, ".git");
|
|
92
|
-
if (!existsSync(gitPath)) return
|
|
92
|
+
if (!existsSync(gitPath)) return gitPath;
|
|
93
|
+
// In a normal repo .git is a directory — skip the file read (#3597)
|
|
94
|
+
if (lstatSync(gitPath).isDirectory()) return gitPath;
|
|
93
95
|
try {
|
|
94
96
|
const content = readFileSync(gitPath, "utf-8").trim();
|
|
95
97
|
if (content.startsWith("gitdir: ")) {
|
|
@@ -98,7 +100,7 @@ export function resolveGitDir(basePath: string): string {
|
|
|
98
100
|
} catch (e) {
|
|
99
101
|
logWarning("worktree", `.git file read failed: ${(e as Error).message}`);
|
|
100
102
|
}
|
|
101
|
-
return
|
|
103
|
+
return gitPath;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
export function worktreesDir(basePath: string): string {
|