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
|
@@ -95,12 +95,24 @@ export async function handleAgentEnd(
|
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
if (lastMsg && "stopReason" in lastMsg && lastMsg.stopReason === "error") {
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
// #3588: errorMessage can be useless (e.g. "success") while the real error
|
|
99
|
+
// is in the assistant message text content. Fall back to content when
|
|
100
|
+
// errorMessage looks uninformative.
|
|
101
|
+
const rawErrorMsg = ("errorMessage" in lastMsg && lastMsg.errorMessage) ? String(lastMsg.errorMessage) : "";
|
|
102
|
+
const isUseless = !rawErrorMsg || /^(success|ok|true|error|unknown)$/i.test(rawErrorMsg.trim());
|
|
103
|
+
// #3588: When errorMessage is uninformative, extract the real error from
|
|
104
|
+
// the assistant message text content for display purposes only.
|
|
105
|
+
// Classification still uses rawErrorMsg to avoid false positives from prose.
|
|
106
|
+
let displayMsg = rawErrorMsg;
|
|
107
|
+
if (isUseless && "content" in lastMsg && Array.isArray(lastMsg.content)) {
|
|
108
|
+
const textBlock = lastMsg.content.find((b: any) => b.type === "text" && b.text);
|
|
109
|
+
if (textBlock) displayMsg = (textBlock as any).text.slice(0, 300);
|
|
110
|
+
}
|
|
111
|
+
const errorDetail = displayMsg ? `: ${displayMsg}` : "";
|
|
100
112
|
const explicitRetryAfterMs = ("retryAfterMs" in lastMsg && typeof lastMsg.retryAfterMs === "number") ? lastMsg.retryAfterMs : undefined;
|
|
101
113
|
|
|
102
|
-
// ── 1. Classify
|
|
103
|
-
const cls = classifyError(
|
|
114
|
+
// ── 1. Classify using rawErrorMsg to avoid prose false-positives ────
|
|
115
|
+
const cls = classifyError(rawErrorMsg, explicitRetryAfterMs);
|
|
104
116
|
|
|
105
117
|
// Cap rate-limit backoff for CLI-style providers (openai-codex, google-gemini-cli)
|
|
106
118
|
// which use per-user quotas with shorter windows (#2922).
|
|
@@ -804,27 +804,39 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
804
804
|
return m ? [m[1].trim(), m[2].trim()] : [s.trim(), ""];
|
|
805
805
|
};
|
|
806
806
|
const coerced = { ...params };
|
|
807
|
-
|
|
807
|
+
// Coerce simple string-array fields: LLMs sometimes pass a plain string
|
|
808
|
+
// instead of a single-element array (#3585).
|
|
809
|
+
const wrapArray = (v: any): any[] =>
|
|
810
|
+
v == null ? [] : Array.isArray(v) ? v : [v];
|
|
811
|
+
coerced.provides = wrapArray(params.provides);
|
|
812
|
+
coerced.keyFiles = wrapArray(params.keyFiles);
|
|
813
|
+
coerced.keyDecisions = wrapArray(params.keyDecisions);
|
|
814
|
+
coerced.patternsEstablished = wrapArray(params.patternsEstablished);
|
|
815
|
+
coerced.observabilitySurfaces = wrapArray(params.observabilitySurfaces);
|
|
816
|
+
coerced.requirementsSurfaced = wrapArray(params.requirementsSurfaced);
|
|
817
|
+
coerced.drillDownPaths = wrapArray(params.drillDownPaths);
|
|
818
|
+
coerced.affects = wrapArray(params.affects);
|
|
819
|
+
coerced.filesModified = wrapArray(params.filesModified).map((f: any) => {
|
|
808
820
|
if (typeof f !== "string") return f;
|
|
809
821
|
const [path, description] = splitPair(f);
|
|
810
822
|
return { path, description };
|
|
811
823
|
});
|
|
812
|
-
coerced.requires = (params.requires
|
|
824
|
+
coerced.requires = wrapArray(params.requires).map((r: any) => {
|
|
813
825
|
if (typeof r !== "string") return r;
|
|
814
826
|
const [slice, provides] = splitPair(r);
|
|
815
827
|
return { slice, provides };
|
|
816
828
|
});
|
|
817
|
-
coerced.requirementsAdvanced = (params.requirementsAdvanced
|
|
829
|
+
coerced.requirementsAdvanced = wrapArray(params.requirementsAdvanced).map((r: any) => {
|
|
818
830
|
if (typeof r !== "string") return r;
|
|
819
831
|
const [id, how] = splitPair(r);
|
|
820
832
|
return { id, how };
|
|
821
833
|
});
|
|
822
|
-
coerced.requirementsValidated = (params.requirementsValidated
|
|
834
|
+
coerced.requirementsValidated = wrapArray(params.requirementsValidated).map((r: any) => {
|
|
823
835
|
if (typeof r !== "string") return r;
|
|
824
836
|
const [id, proof] = splitPair(r);
|
|
825
837
|
return { id, proof };
|
|
826
838
|
});
|
|
827
|
-
coerced.requirementsInvalidated = (params.requirementsInvalidated
|
|
839
|
+
coerced.requirementsInvalidated = wrapArray(params.requirementsInvalidated).map((r: any) => {
|
|
828
840
|
if (typeof r !== "string") return r;
|
|
829
841
|
const [id, what] = splitPair(r);
|
|
830
842
|
return { id, what };
|
|
@@ -884,14 +896,14 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
884
896
|
deviations: Type.Optional(Type.String({ description: "Deviations from the slice plan, or 'None.'" })),
|
|
885
897
|
knownLimitations: Type.Optional(Type.String({ description: "Known limitations or gaps, or 'None.'" })),
|
|
886
898
|
followUps: Type.Optional(Type.String({ description: "Follow-up work discovered during execution, or 'None.'" })),
|
|
887
|
-
keyFiles: Type.Optional(Type.Array(Type.String(), { description: "Key files created or modified" })),
|
|
888
|
-
keyDecisions: Type.Optional(Type.Array(Type.String(), { description: "Key decisions made during this slice" })),
|
|
889
|
-
patternsEstablished: Type.Optional(Type.Array(Type.String(), { description: "Patterns established by this slice" })),
|
|
890
|
-
observabilitySurfaces: Type.Optional(Type.Array(Type.String(), { description: "Observability surfaces added" })),
|
|
891
|
-
provides: Type.Optional(Type.Array(Type.String(), { description: "What this slice provides to downstream slices" })),
|
|
892
|
-
requirementsSurfaced: Type.Optional(Type.Array(Type.String(), { description: "New requirements surfaced" })),
|
|
893
|
-
drillDownPaths: Type.Optional(Type.Array(Type.String(), { description: "Paths to task summaries for drill-down" })),
|
|
894
|
-
affects: Type.Optional(Type.Array(Type.String(), { description: "Downstream slices affected" })),
|
|
899
|
+
keyFiles: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Key files created or modified" })),
|
|
900
|
+
keyDecisions: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Key decisions made during this slice" })),
|
|
901
|
+
patternsEstablished: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Patterns established by this slice" })),
|
|
902
|
+
observabilitySurfaces: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Observability surfaces added" })),
|
|
903
|
+
provides: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "What this slice provides to downstream slices" })),
|
|
904
|
+
requirementsSurfaced: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "New requirements surfaced" })),
|
|
905
|
+
drillDownPaths: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Paths to task summaries for drill-down" })),
|
|
906
|
+
affects: Type.Optional(Type.Union([Type.Array(Type.String()), Type.String()], { description: "Downstream slices affected" })),
|
|
895
907
|
requirementsAdvanced: Type.Optional(Type.Array(
|
|
896
908
|
Type.Union([
|
|
897
909
|
Type.Object({
|
|
@@ -988,6 +1000,16 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
988
1000
|
updateSliceStatus(params.milestoneId, params.sliceId, "skipped");
|
|
989
1001
|
invalidateStateCache();
|
|
990
1002
|
|
|
1003
|
+
// Rebuild STATE.md so it reflects the skip immediately (#3477).
|
|
1004
|
+
// Without this, /gsd auto reads stale STATE.md and resumes the skipped slice.
|
|
1005
|
+
try {
|
|
1006
|
+
const basePath = process.cwd();
|
|
1007
|
+
const { rebuildState } = await import("../doctor.js");
|
|
1008
|
+
await rebuildState(basePath);
|
|
1009
|
+
} catch (err) {
|
|
1010
|
+
logError("tool", `skip_slice rebuildState failed: ${(err as Error).message}`, { tool: "gsd_skip_slice" });
|
|
1011
|
+
}
|
|
1012
|
+
|
|
991
1013
|
return {
|
|
992
1014
|
content: [{ type: "text" as const, text: `Skipped slice ${params.sliceId} (${params.milestoneId}). Reason: ${params.reason ?? "User-directed skip"}. Auto-mode will advance past this slice.` }],
|
|
993
1015
|
details: {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// GSD Extension — Notify Interceptor
|
|
2
|
+
// Wraps ctx.ui.notify() in-place to persist every notification through the
|
|
3
|
+
// notification store. Uses a WeakSet to prevent double-wrapping and handle
|
|
4
|
+
// UI context replacement on /reload gracefully.
|
|
5
|
+
|
|
6
|
+
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
7
|
+
|
|
8
|
+
import { appendNotification, type NotifySeverity } from "../notification-store.js";
|
|
9
|
+
|
|
10
|
+
// Track which ui context objects have been wrapped to prevent double-install.
|
|
11
|
+
// WeakSet allows GC to collect replaced uiContext instances after /reload.
|
|
12
|
+
const _wrappedContexts = new WeakSet<object>();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Install the notify interceptor on a context's UI object.
|
|
16
|
+
* Mutates ctx.ui.notify in place — the original is called after persistence.
|
|
17
|
+
* Safe to call multiple times; no-ops if already installed on the same ui object.
|
|
18
|
+
*/
|
|
19
|
+
export function installNotifyInterceptor(ctx: ExtensionContext): void {
|
|
20
|
+
if (_wrappedContexts.has(ctx.ui)) return;
|
|
21
|
+
|
|
22
|
+
const originalNotify = ctx.ui.notify.bind(ctx.ui);
|
|
23
|
+
|
|
24
|
+
(ctx.ui as any).notify = (message: string, type?: "info" | "warning" | "error" | "success"): void => {
|
|
25
|
+
try {
|
|
26
|
+
appendNotification(message, (type ?? "info") as NotifySeverity, "notify");
|
|
27
|
+
} catch {
|
|
28
|
+
// Non-fatal — never let persistence break the UI
|
|
29
|
+
}
|
|
30
|
+
originalNotify(message, type);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
_wrappedContexts.add(ctx.ui);
|
|
34
|
+
}
|
|
@@ -22,17 +22,18 @@ export function registerQueryTools(pi: ExtensionAPI): void {
|
|
|
22
22
|
}),
|
|
23
23
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
24
24
|
try {
|
|
25
|
-
//
|
|
26
|
-
//
|
|
25
|
+
// Open the DB if not already open — safe for read-only use since
|
|
26
|
+
// ensureDbOpen() only creates/migrates when .gsd/ has content (#3644).
|
|
27
|
+
const { ensureDbOpen } = await import("./dynamic-tools.js");
|
|
28
|
+
const dbAvailable = await ensureDbOpen();
|
|
27
29
|
const {
|
|
28
|
-
isDbAvailable,
|
|
29
30
|
getMilestone,
|
|
30
31
|
getSliceStatusSummary,
|
|
31
32
|
getSliceTaskCounts,
|
|
32
33
|
_getAdapter,
|
|
33
34
|
} = await import("../gsd-db.js");
|
|
34
35
|
|
|
35
|
-
if (!
|
|
36
|
+
if (!dbAvailable) {
|
|
36
37
|
return {
|
|
37
38
|
content: [{ type: "text" as const, text: "Error: GSD database is not available." }],
|
|
38
39
|
details: { operation: "milestone_status", error: "db_unavailable" } as any,
|
|
@@ -36,7 +36,10 @@ function installEpipeGuard(): void {
|
|
|
36
36
|
if (handleRecoverableExtensionProcessError(err)) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
// Log unhandled errors instead of re-throwing — throwing inside an
|
|
40
|
+
// uncaughtException handler is a fatal double-fault in Node.js (#3163).
|
|
41
|
+
process.stderr.write(`[gsd] uncaught extension error (non-fatal): ${err.message}\n`);
|
|
42
|
+
if (err.stack) process.stderr.write(`${err.stack}\n`);
|
|
40
43
|
};
|
|
41
44
|
process.on("uncaughtException", _gsdEpipeGuard);
|
|
42
45
|
}
|
|
@@ -21,6 +21,9 @@ import { resetAskUserQuestionsCache } from "../../ask-user-questions.js";
|
|
|
21
21
|
import { recordToolCall as safetyRecordToolCall, recordToolResult as safetyRecordToolResult } from "../safety/evidence-collector.js";
|
|
22
22
|
import { classifyCommand } from "../safety/destructive-guard.js";
|
|
23
23
|
import { logWarning as safetyLogWarning } from "../workflow-logger.js";
|
|
24
|
+
import { installNotifyInterceptor } from "./notify-interceptor.js";
|
|
25
|
+
import { initNotificationStore } from "../notification-store.js";
|
|
26
|
+
import { initNotificationWidget } from "../notification-widget.js";
|
|
24
27
|
|
|
25
28
|
// Skip the welcome screen on the very first session_start — cli.ts already
|
|
26
29
|
// printed it before the TUI launched. Only re-print on /clear (subsequent sessions).
|
|
@@ -33,6 +36,9 @@ async function syncServiceTierStatus(ctx: ExtensionContext): Promise<void> {
|
|
|
33
36
|
|
|
34
37
|
export function registerHooks(pi: ExtensionAPI): void {
|
|
35
38
|
pi.on("session_start", async (_event, ctx) => {
|
|
39
|
+
initNotificationStore(process.cwd());
|
|
40
|
+
installNotifyInterceptor(ctx);
|
|
41
|
+
initNotificationWidget(ctx);
|
|
36
42
|
resetWriteGateState();
|
|
37
43
|
resetToolCallLoopGuard();
|
|
38
44
|
resetAskUserQuestionsCache();
|
|
@@ -70,6 +76,8 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
70
76
|
});
|
|
71
77
|
|
|
72
78
|
pi.on("session_switch", async (_event, ctx) => {
|
|
79
|
+
initNotificationStore(process.cwd());
|
|
80
|
+
installNotifyInterceptor(ctx);
|
|
73
81
|
resetWriteGateState();
|
|
74
82
|
resetToolCallLoopGuard();
|
|
75
83
|
resetAskUserQuestionsCache();
|
|
@@ -100,7 +108,10 @@ export function registerHooks(pi: ExtensionAPI): void {
|
|
|
100
108
|
});
|
|
101
109
|
|
|
102
110
|
pi.on("session_before_compact", async () => {
|
|
103
|
-
|
|
111
|
+
// Only cancel compaction while auto-mode is actively running.
|
|
112
|
+
// Paused auto-mode should allow compaction — the user may be doing
|
|
113
|
+
// interactive work (#3165).
|
|
114
|
+
if (isAutoActive()) {
|
|
104
115
|
return { cancel: true };
|
|
105
116
|
}
|
|
106
117
|
const basePath = process.cwd();
|
|
@@ -5,6 +5,7 @@ import type { ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
|
5
5
|
import { Key } from "@gsd/pi-tui";
|
|
6
6
|
|
|
7
7
|
import { GSDDashboardOverlay } from "../dashboard-overlay.js";
|
|
8
|
+
import { GSDNotificationOverlay } from "../notification-overlay.js";
|
|
8
9
|
import { ParallelMonitorOverlay } from "../parallel-monitor-overlay.js";
|
|
9
10
|
import { shortcutDesc } from "../../shared/mod.js";
|
|
10
11
|
|
|
@@ -31,6 +32,25 @@ export function registerShortcuts(pi: ExtensionAPI): void {
|
|
|
31
32
|
},
|
|
32
33
|
});
|
|
33
34
|
|
|
35
|
+
pi.registerShortcut(Key.ctrlAlt("n"), {
|
|
36
|
+
description: shortcutDesc("Open notification history", "/gsd notifications"),
|
|
37
|
+
handler: async (ctx) => {
|
|
38
|
+
await ctx.ui.custom<void>(
|
|
39
|
+
(tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done()),
|
|
40
|
+
{
|
|
41
|
+
overlay: true,
|
|
42
|
+
overlayOptions: {
|
|
43
|
+
width: "80%",
|
|
44
|
+
minWidth: 60,
|
|
45
|
+
maxHeight: "88%",
|
|
46
|
+
anchor: "center",
|
|
47
|
+
backdrop: true,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
34
54
|
pi.registerShortcut(Key.ctrlAlt("p"), {
|
|
35
55
|
description: shortcutDesc("Open parallel worker monitor", "/gsd parallel watch"),
|
|
36
56
|
handler: async (ctx) => {
|
|
@@ -264,6 +264,13 @@ function buildWorktreeContextBlock(): string {
|
|
|
264
264
|
return "";
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Low-entropy resume intent patterns — short phrases a user types to
|
|
269
|
+
* continue work after a pause, rate limit, or context reset (#3615).
|
|
270
|
+
* Tested against the trimmed, lowercased prompt with trailing punctuation stripped.
|
|
271
|
+
*/
|
|
272
|
+
const RESUME_INTENT_PATTERNS = /^(continue|resume|ok|go|go ahead|proceed|keep going|carry on|next|yes|yeah|yep|sure|do it|let's go|pick up where you left off)$/;
|
|
273
|
+
|
|
267
274
|
async function buildGuidedExecuteContextInjection(prompt: string, basePath: string): Promise<string | null> {
|
|
268
275
|
const executeMatch = prompt.match(/Execute the next task:\s+(T\d+)\s+\("([^"]+)"\)\s+in slice\s+(S\d+)\s+of milestone\s+(M\d+(?:-[a-z0-9]{6})?)/i);
|
|
269
276
|
if (executeMatch) {
|
|
@@ -280,6 +287,27 @@ async function buildGuidedExecuteContextInjection(prompt: string, basePath: stri
|
|
|
280
287
|
}
|
|
281
288
|
}
|
|
282
289
|
|
|
290
|
+
// Fallback: low-entropy resume prompt (e.g., "continue", "ok", "go ahead")
|
|
291
|
+
// during an active executing task — inject task context so the agent
|
|
292
|
+
// doesn't rebuild from scratch (#3615).
|
|
293
|
+
// Intent-gated: only fire for short, resume-like prompts to avoid hijacking
|
|
294
|
+
// control/help/diagnostic prompts with unrelated execution context.
|
|
295
|
+
// Phase-gated: only fire during "executing" to avoid misrouting during
|
|
296
|
+
// replanning, gate evaluation, or other non-execution phases.
|
|
297
|
+
const trimmed = prompt.trim().toLowerCase().replace(/[.!?,]+$/g, "");
|
|
298
|
+
if (RESUME_INTENT_PATTERNS.test(trimmed)) {
|
|
299
|
+
const state = await deriveState(basePath);
|
|
300
|
+
if (state.phase === "executing" && state.activeTask && state.activeMilestone && state.activeSlice) {
|
|
301
|
+
return buildTaskExecutionContextInjection(
|
|
302
|
+
basePath,
|
|
303
|
+
state.activeMilestone.id,
|
|
304
|
+
state.activeSlice.id,
|
|
305
|
+
state.activeTask.id,
|
|
306
|
+
state.activeTask.title,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
283
311
|
return null;
|
|
284
312
|
}
|
|
285
313
|
|
|
@@ -15,7 +15,7 @@ export interface GsdCommandDefinition {
|
|
|
15
15
|
type CompletionMap = Record<string, readonly GsdCommandDefinition[]>;
|
|
16
16
|
|
|
17
17
|
export const GSD_COMMAND_DESCRIPTION =
|
|
18
|
-
"GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast|mcp|rethink|codebase";
|
|
18
|
+
"GSD — Get Shit Done: /gsd help|start|templates|next|auto|stop|pause|status|widget|visualize|queue|quick|discuss|capture|triage|dispatch|history|undo|undo-task|reset-slice|rate|skip|export|cleanup|mode|prefs|config|keys|hooks|run-hook|skill-health|doctor|logs|forensics|changelog|migrate|remote|steer|knowledge|new-milestone|parallel|cmux|park|unpark|init|setup|inspect|extensions|update|fast|mcp|rethink|codebase|notifications";
|
|
19
19
|
|
|
20
20
|
export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
|
|
21
21
|
{ cmd: "help", desc: "Categorized command reference with descriptions" },
|
|
@@ -48,6 +48,7 @@ export const TOP_LEVEL_SUBCOMMANDS: readonly GsdCommandDefinition[] = [
|
|
|
48
48
|
{ cmd: "hooks", desc: "Show configured post-unit and pre-dispatch hooks" },
|
|
49
49
|
{ cmd: "run-hook", desc: "Manually trigger a specific hook" },
|
|
50
50
|
{ cmd: "skill-health", desc: "Skill lifecycle dashboard" },
|
|
51
|
+
{ cmd: "notifications", desc: "View, filter, and clear persistent notification history" },
|
|
51
52
|
{ cmd: "doctor", desc: "Runtime health checks with auto-fix" },
|
|
52
53
|
{ cmd: "logs", desc: "Browse activity logs, debug logs, and metrics" },
|
|
53
54
|
{ cmd: "forensics", desc: "Examine execution logs" },
|
|
@@ -110,6 +111,11 @@ const NESTED_COMPLETIONS: CompletionMap = {
|
|
|
110
111
|
{ cmd: "keys", desc: "Manage API keys" },
|
|
111
112
|
{ cmd: "prefs", desc: "Configure global preferences" },
|
|
112
113
|
],
|
|
114
|
+
notifications: [
|
|
115
|
+
{ cmd: "clear", desc: "Clear all notifications" },
|
|
116
|
+
{ cmd: "tail", desc: "Show last N notifications (default: 20)" },
|
|
117
|
+
{ cmd: "filter", desc: "Filter by severity (error|warning|info|success)" },
|
|
118
|
+
],
|
|
113
119
|
logs: [
|
|
114
120
|
{ cmd: "debug", desc: "List or view debug log files" },
|
|
115
121
|
{ cmd: "tail", desc: "Show last N activity log summaries" },
|
|
@@ -13,7 +13,13 @@ export interface GsdDispatchContext {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function projectRoot(): string {
|
|
16
|
-
|
|
16
|
+
let cwd: string;
|
|
17
|
+
try {
|
|
18
|
+
cwd = process.cwd();
|
|
19
|
+
} catch {
|
|
20
|
+
// cwd directory was deleted (e.g. worktree teardown) — fall back to HOME (#3598)
|
|
21
|
+
cwd = process.env.HOME ?? "/";
|
|
22
|
+
}
|
|
17
23
|
const root = resolveProjectRoot(cwd);
|
|
18
24
|
if (root !== cwd) {
|
|
19
25
|
assertSafeDirectory(cwd);
|
|
@@ -29,6 +29,7 @@ export function showHelp(ctx: ExtensionCommandContext): void {
|
|
|
29
29
|
" /gsd queue Show queued/dispatched units and execution order",
|
|
30
30
|
" /gsd history View execution history [--cost] [--phase] [--model] [N]",
|
|
31
31
|
" /gsd changelog Show categorized release notes [version]",
|
|
32
|
+
" /gsd notifications View persistent notification history [clear|tail|filter] (Ctrl+Alt+N)",
|
|
32
33
|
"",
|
|
33
34
|
"COURSE CORRECTION",
|
|
34
35
|
" /gsd steer <desc> Apply user override to active work",
|
|
@@ -51,6 +52,7 @@ export function showHelp(ctx: ExtensionCommandContext): void {
|
|
|
51
52
|
" /gsd cmux Manage cmux integration [status|on|off|notifications|sidebar|splits|browser]",
|
|
52
53
|
" /gsd config Set API keys for external tools",
|
|
53
54
|
" /gsd keys API key manager [list|add|remove|test|rotate|doctor]",
|
|
55
|
+
" /gsd show-config Show effective configuration (models, routing, toggles)",
|
|
54
56
|
" /gsd hooks Show post-unit hook configuration",
|
|
55
57
|
" /gsd extensions Manage extensions [list|enable|disable|info]",
|
|
56
58
|
" /gsd fast Toggle OpenAI service tier [on|off|flex|status]",
|
|
@@ -70,6 +72,9 @@ export function showHelp(ctx: ExtensionCommandContext): void {
|
|
|
70
72
|
|
|
71
73
|
export async function handleStatus(ctx: ExtensionCommandContext): Promise<void> {
|
|
72
74
|
const basePath = projectRoot();
|
|
75
|
+
// Open DB in cold sessions so status uses DB-backed state, not filesystem fallback (#3385)
|
|
76
|
+
const { ensureDbOpen } = await import("../../bootstrap/dynamic-tools.js");
|
|
77
|
+
await ensureDbOpen();
|
|
73
78
|
const state = await deriveState(basePath);
|
|
74
79
|
|
|
75
80
|
if (state.registry.length === 0) {
|
|
@@ -213,6 +218,25 @@ export async function handleCoreCommand(trimmed: string, ctx: ExtensionCommandCo
|
|
|
213
218
|
await handleCmux(trimmed.replace(/^cmux\s*/, "").trim(), ctx);
|
|
214
219
|
return true;
|
|
215
220
|
}
|
|
221
|
+
if (trimmed === "show-config") {
|
|
222
|
+
const { GSDConfigOverlay, formatConfigText } = await import("../../config-overlay.js");
|
|
223
|
+
const result = await ctx.ui.custom<void>(
|
|
224
|
+
(tui, theme, _kb, done) => new GSDConfigOverlay(tui, theme, () => done()),
|
|
225
|
+
{
|
|
226
|
+
overlay: true,
|
|
227
|
+
overlayOptions: {
|
|
228
|
+
width: "65%",
|
|
229
|
+
minWidth: 55,
|
|
230
|
+
maxHeight: "85%",
|
|
231
|
+
anchor: "center",
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
if (result === undefined) {
|
|
236
|
+
ctx.ui.notify(formatConfigText(), "info");
|
|
237
|
+
}
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
216
240
|
if (trimmed === "setup" || trimmed.startsWith("setup ")) {
|
|
217
241
|
await handleSetup(trimmed.replace(/^setup\s*/, "").trim(), ctx);
|
|
218
242
|
return true;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// GSD Extension — /gsd notifications Command Handler
|
|
2
|
+
// View, filter, and clear the persistent notification history.
|
|
3
|
+
|
|
4
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
readNotifications,
|
|
8
|
+
clearNotifications,
|
|
9
|
+
getUnreadCount,
|
|
10
|
+
suppressPersistence,
|
|
11
|
+
unsuppressPersistence,
|
|
12
|
+
type NotifySeverity,
|
|
13
|
+
} from "../../notification-store.js";
|
|
14
|
+
import { GSDNotificationOverlay } from "../../notification-overlay.js";
|
|
15
|
+
|
|
16
|
+
function severityIcon(severity: NotifySeverity): string {
|
|
17
|
+
switch (severity) {
|
|
18
|
+
case "error": return "✗";
|
|
19
|
+
case "warning": return "⚠";
|
|
20
|
+
case "success": return "✓";
|
|
21
|
+
case "info":
|
|
22
|
+
default: return "●";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function formatTimestamp(ts: string): string {
|
|
27
|
+
try {
|
|
28
|
+
const d = new Date(ts);
|
|
29
|
+
return d.toLocaleString("en-US", { hour12: false, month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
30
|
+
} catch {
|
|
31
|
+
return ts.slice(0, 19);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function handleNotificationsCommand(
|
|
36
|
+
args: string,
|
|
37
|
+
ctx: ExtensionCommandContext,
|
|
38
|
+
pi: ExtensionAPI,
|
|
39
|
+
): Promise<boolean> {
|
|
40
|
+
// /gsd notifications clear
|
|
41
|
+
if (args === "clear") {
|
|
42
|
+
clearNotifications();
|
|
43
|
+
// Suppress persistence so the confirmation toast doesn't re-populate the store
|
|
44
|
+
suppressPersistence();
|
|
45
|
+
try {
|
|
46
|
+
ctx.ui.notify("All notifications cleared.", "success");
|
|
47
|
+
} finally {
|
|
48
|
+
unsuppressPersistence();
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// /gsd notifications tail [N]
|
|
54
|
+
if (args === "tail" || args.startsWith("tail ")) {
|
|
55
|
+
const countStr = args.replace(/^tail\s*/, "").trim();
|
|
56
|
+
const count = countStr ? parseInt(countStr, 10) : 20;
|
|
57
|
+
const n = isNaN(count) || count < 1 ? 20 : Math.min(count, 100);
|
|
58
|
+
const entries = readNotifications().slice(0, n);
|
|
59
|
+
|
|
60
|
+
if (entries.length === 0) {
|
|
61
|
+
ctx.ui.notify("No notifications.", "info");
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const lines = entries.map((e) =>
|
|
66
|
+
`${severityIcon(e.severity)} [${formatTimestamp(e.ts)}] ${e.message}`,
|
|
67
|
+
);
|
|
68
|
+
ctx.ui.notify(`Last ${entries.length} notification(s):\n${lines.join("\n")}`, "info");
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// /gsd notifications filter <severity>
|
|
73
|
+
if (args.startsWith("filter ")) {
|
|
74
|
+
const severity = args.replace(/^filter\s+/, "").trim().toLowerCase();
|
|
75
|
+
if (!["error", "warning", "info", "success"].includes(severity)) {
|
|
76
|
+
ctx.ui.notify("Usage: /gsd notifications filter <error|warning|info|success>", "warning");
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
const entries = readNotifications().filter((e) => e.severity === severity);
|
|
80
|
+
|
|
81
|
+
if (entries.length === 0) {
|
|
82
|
+
ctx.ui.notify(`No ${severity} notifications.`, "info");
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const lines = entries.slice(0, 20).map((e) =>
|
|
87
|
+
`${severityIcon(e.severity)} [${formatTimestamp(e.ts)}] ${e.message}`,
|
|
88
|
+
);
|
|
89
|
+
const suffix = entries.length > 20 ? `\n... and ${entries.length - 20} more` : "";
|
|
90
|
+
ctx.ui.notify(`${severity} notifications (${entries.length}):\n${lines.join("\n")}${suffix}`, "info");
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// /gsd notifications (no args) — open overlay in TUI, or print summary
|
|
95
|
+
if (args === "" || args === "status") {
|
|
96
|
+
// Try overlay first (TUI mode)
|
|
97
|
+
if (ctx.hasUI) {
|
|
98
|
+
try {
|
|
99
|
+
await ctx.ui.custom<void>(
|
|
100
|
+
(tui, theme, _kb, done) => new GSDNotificationOverlay(tui, theme, () => done()),
|
|
101
|
+
{
|
|
102
|
+
overlay: true,
|
|
103
|
+
overlayOptions: {
|
|
104
|
+
width: "80%",
|
|
105
|
+
minWidth: 60,
|
|
106
|
+
maxHeight: "88%",
|
|
107
|
+
anchor: "center",
|
|
108
|
+
backdrop: true,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
return true;
|
|
113
|
+
} catch {
|
|
114
|
+
// Fall through to text output if overlay fails
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Text fallback (RPC/headless mode)
|
|
119
|
+
const unread = getUnreadCount();
|
|
120
|
+
const entries = readNotifications().slice(0, 10);
|
|
121
|
+
if (entries.length === 0) {
|
|
122
|
+
ctx.ui.notify("No notifications.", "info");
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const lines = entries.map((e) =>
|
|
127
|
+
`${severityIcon(e.severity)} [${formatTimestamp(e.ts)}] ${e.message}`,
|
|
128
|
+
);
|
|
129
|
+
const header = unread > 0 ? `${unread} unread — ` : "";
|
|
130
|
+
ctx.ui.notify(`${header}Recent notifications:\n${lines.join("\n")}`, "info");
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Unknown subcommand
|
|
135
|
+
ctx.ui.notify(
|
|
136
|
+
"Usage: /gsd notifications [clear|tail [N]|filter <severity>]",
|
|
137
|
+
"warning",
|
|
138
|
+
);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
@@ -178,6 +178,11 @@ Examples:
|
|
|
178
178
|
await dispatchDirectPhase(ctx, pi, phase, projectRoot());
|
|
179
179
|
return true;
|
|
180
180
|
}
|
|
181
|
+
if (trimmed === "notifications" || trimmed.startsWith("notifications ")) {
|
|
182
|
+
const { handleNotificationsCommand } = await import("./notifications-handler.js");
|
|
183
|
+
await handleNotificationsCommand(trimmed.replace(/^notifications\s*/, "").trim(), ctx, pi);
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
181
186
|
if (trimmed === "inspect") {
|
|
182
187
|
await handleInspect(ctx);
|
|
183
188
|
return true;
|
|
@@ -105,7 +105,7 @@ function discoverManifests(): Map<string, ExtensionManifest> {
|
|
|
105
105
|
const manifests = new Map<string, ExtensionManifest>();
|
|
106
106
|
if (!existsSync(extDir)) return manifests;
|
|
107
107
|
for (const entry of readdirSync(extDir, { withFileTypes: true })) {
|
|
108
|
-
if (!entry.isDirectory()) continue;
|
|
108
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
109
109
|
const m = readManifest(join(extDir, entry.name));
|
|
110
110
|
if (m) manifests.set(m.id, m);
|
|
111
111
|
}
|