gsd-pi 2.70.1 → 2.71.0-dev.4c35d99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -17
- package/dist/cli.js +29 -3
- package/dist/headless-events.d.ts +2 -0
- package/dist/headless-events.js +7 -0
- package/dist/headless.js +16 -3
- package/dist/mcp-server.js +40 -17
- package/dist/provider-migrations.d.ts +10 -0
- package/dist/provider-migrations.js +12 -0
- package/dist/resource-loader.js +139 -13
- package/dist/resources/GSD-WORKFLOW.md +1 -1
- package/dist/resources/agents/debugger.md +58 -0
- package/dist/resources/agents/doc-writer.md +43 -0
- package/dist/resources/agents/git-ops.md +56 -0
- package/dist/resources/agents/javascript-pro.md +46 -271
- package/dist/resources/agents/planner.md +55 -0
- package/dist/resources/agents/refactorer.md +47 -0
- package/dist/resources/agents/reviewer.md +48 -0
- package/dist/resources/agents/security.md +59 -0
- package/dist/resources/agents/tester.md +50 -0
- package/dist/resources/agents/typescript-pro.md +41 -235
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +242 -40
- package/dist/resources/extensions/get-secrets-from-user.js +17 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +34 -0
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +5 -1
- package/dist/resources/extensions/gsd/auto/session.js +11 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +22 -16
- package/dist/resources/extensions/gsd/auto-model-selection.js +10 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +88 -33
- package/dist/resources/extensions/gsd/auto-start.js +37 -18
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +1 -1
- package/dist/resources/extensions/gsd/auto-worktree.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +56 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +6 -0
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +63 -51
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -0
- package/dist/resources/extensions/gsd/commands/context.js +15 -6
- package/dist/resources/extensions/gsd/commands/dispatcher.js +12 -2
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -33
- package/dist/resources/extensions/gsd/commands/handlers/core.js +56 -11
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +15 -6
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +4 -10
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +16 -12
- package/dist/resources/extensions/gsd/dashboard-overlay.js +8 -3
- package/dist/resources/extensions/gsd/dispatch-guard.js +18 -1
- package/dist/resources/extensions/gsd/doctor-providers.js +23 -0
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/file-lock.js +60 -0
- package/dist/resources/extensions/gsd/forensics.js +19 -6
- package/dist/resources/extensions/gsd/gate-registry.js +208 -0
- package/dist/resources/extensions/gsd/gsd-db.js +41 -0
- package/dist/resources/extensions/gsd/guided-flow.js +17 -20
- package/dist/resources/extensions/gsd/init-wizard.js +3 -11
- package/dist/resources/extensions/gsd/metrics.js +1 -0
- package/dist/resources/extensions/gsd/milestone-actions.js +10 -4
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +11 -12
- package/dist/resources/extensions/gsd/notification-overlay.js +42 -13
- package/dist/resources/extensions/gsd/notification-store.js +56 -5
- package/dist/resources/extensions/gsd/notification-widget.js +5 -13
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +8 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +35 -2
- package/dist/resources/extensions/gsd/prompt-validation.js +126 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +5 -3
- package/dist/resources/extensions/gsd/prompts/discuss.md +33 -13
- package/dist/resources/extensions/gsd/prompts/execute-task.md +22 -19
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/queue.md +3 -2
- package/dist/resources/extensions/gsd/prompts/system.md +1 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
- package/dist/resources/extensions/gsd/session-model-override.js +25 -0
- package/dist/resources/extensions/gsd/shortcut-defs.js +40 -0
- package/dist/resources/extensions/gsd/state.js +241 -332
- package/dist/resources/extensions/gsd/tools/complete-slice.js +52 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +51 -1
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +38 -1
- package/dist/resources/extensions/gsd/workflow-events.js +25 -13
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +56 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +1 -1
- package/dist/resources/extensions/ollama/index.js +13 -5
- package/dist/resources/extensions/shared/gsd-phase-state.js +35 -0
- package/dist/resources/extensions/subagent/agents.js +8 -0
- package/dist/resources/extensions/subagent/index.js +17 -0
- package/dist/resources/skills/create-skill/SKILL.md +2 -0
- package/dist/startup-model-validation.d.ts +0 -1
- package/dist/startup-model-validation.js +6 -2
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.dd3dc8bbd3025fa5.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-6e4d7e9a4f57bed4.js → webpack-b868033a5834586d.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/env-writer.d.ts +39 -0
- package/packages/mcp-server/dist/env-writer.d.ts.map +1 -0
- package/packages/mcp-server/dist/env-writer.js +158 -0
- package/packages/mcp-server/dist/env-writer.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +23 -3
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +192 -44
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -12
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/env-writer.test.ts +280 -0
- package/packages/mcp-server/src/env-writer.ts +183 -0
- package/packages/mcp-server/src/secure-env-collect.test.ts +265 -0
- package/packages/mcp-server/src/server.ts +247 -41
- package/packages/mcp-server/src/workflow-tools.test.ts +110 -0
- package/packages/mcp-server/src/workflow-tools.ts +32 -12
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +11 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +20 -0
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts +4 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +8 -3
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +44 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +2 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +7 -4
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +11 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +13 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +32 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +55 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +14 -3
- package/packages/pi-ai/src/providers/anthropic.ts +8 -4
- package/packages/pi-ai/src/providers/openai-completions.ts +14 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.test.js +61 -0
- package/packages/pi-coding-agent/dist/core/agent-session-renderable-tools.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 +2 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +27 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +85 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +388 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js +64 -0
- package/packages/pi-coding-agent/dist/core/model-resolver-initial-model-auth.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +22 -18
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts +8 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js +75 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +38 -5
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js +71 -0
- package/packages/pi-coding-agent/dist/core/sdk.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js +13 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/login-dialog.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +19 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +50 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +24 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +4 -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 +43 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +175 -25
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js +6 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/model-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.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 +62 -5
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +4 -2
- package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +2 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +108 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +468 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -0
- package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
- package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +22 -18
- package/packages/pi-coding-agent/src/core/sdk.test.ts +89 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +45 -9
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +58 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +30 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +15 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +47 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +205 -31
- package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +6 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +70 -5
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +4 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +1 -1
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +1 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js +9 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +66 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
- package/packages/pi-tui/dist/components/input.d.ts +2 -0
- package/packages/pi-tui/dist/components/input.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/input.js +7 -4
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/components/markdown.d.ts +3 -0
- package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/markdown.js +17 -1
- package/packages/pi-tui/dist/components/markdown.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/input.test.ts +11 -0
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +75 -0
- package/packages/pi-tui/src/components/input.ts +7 -4
- package/packages/pi-tui/src/components/markdown.ts +22 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +1 -1
- package/src/resources/agents/debugger.md +58 -0
- package/src/resources/agents/doc-writer.md +43 -0
- package/src/resources/agents/git-ops.md +56 -0
- package/src/resources/agents/javascript-pro.md +46 -271
- package/src/resources/agents/planner.md +55 -0
- package/src/resources/agents/refactorer.md +47 -0
- package/src/resources/agents/reviewer.md +48 -0
- package/src/resources/agents/security.md +59 -0
- package/src/resources/agents/tester.md +50 -0
- package/src/resources/agents/typescript-pro.md +41 -235
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +288 -39
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +330 -2
- package/src/resources/extensions/get-secrets-from-user.ts +24 -1
- package/src/resources/extensions/gsd/auto/infra-errors.ts +38 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +45 -1
- package/src/resources/extensions/gsd/auto/phases.ts +6 -0
- package/src/resources/extensions/gsd/auto/session.ts +11 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +29 -18
- package/src/resources/extensions/gsd/auto-model-selection.ts +9 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +111 -33
- package/src/resources/extensions/gsd/auto-start.ts +44 -20
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +1 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +72 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +6 -0
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +79 -60
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +7 -0
- package/src/resources/extensions/gsd/commands/context.ts +16 -5
- package/src/resources/extensions/gsd/commands/dispatcher.ts +14 -2
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +10 -36
- package/src/resources/extensions/gsd/commands/handlers/core.ts +58 -11
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +17 -7
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +4 -10
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +19 -14
- package/src/resources/extensions/gsd/dashboard-overlay.ts +10 -3
- package/src/resources/extensions/gsd/dispatch-guard.ts +18 -1
- package/src/resources/extensions/gsd/doctor-providers.ts +24 -0
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/file-lock.ts +59 -0
- package/src/resources/extensions/gsd/forensics.ts +23 -7
- package/src/resources/extensions/gsd/gate-registry.ts +251 -0
- package/src/resources/extensions/gsd/gsd-db.ts +51 -0
- package/src/resources/extensions/gsd/guided-flow.ts +17 -19
- package/src/resources/extensions/gsd/init-wizard.ts +3 -13
- package/src/resources/extensions/gsd/interrupted-session.ts +1 -0
- package/src/resources/extensions/gsd/metrics.ts +12 -1
- package/src/resources/extensions/gsd/milestone-actions.ts +10 -3
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +11 -13
- package/src/resources/extensions/gsd/notification-overlay.ts +47 -14
- package/src/resources/extensions/gsd/notification-store.ts +54 -5
- package/src/resources/extensions/gsd/notification-widget.ts +5 -14
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +39 -2
- package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +5 -3
- package/src/resources/extensions/gsd/prompts/discuss.md +33 -13
- package/src/resources/extensions/gsd/prompts/execute-task.md +22 -19
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/queue.md +3 -2
- package/src/resources/extensions/gsd/prompts/system.md +1 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -1
- package/src/resources/extensions/gsd/session-model-override.ts +36 -0
- package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
- package/src/resources/extensions/gsd/state.ts +285 -344
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +25 -9
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +66 -1
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +36 -51
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +63 -5
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +155 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +22 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +63 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +63 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +64 -26
- package/src/resources/extensions/gsd/types.ts +26 -0
- package/src/resources/extensions/gsd/workflow-events.ts +34 -25
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +76 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +1 -1
- package/src/resources/extensions/ollama/index.ts +13 -3
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +28 -0
- package/src/resources/extensions/shared/gsd-phase-state.ts +42 -0
- package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +48 -0
- package/src/resources/extensions/subagent/agents.ts +10 -0
- package/src/resources/extensions/subagent/index.ts +18 -0
- package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
- package/src/resources/skills/create-skill/SKILL.md +2 -0
- package/dist/web/standalone/.next/static/chunks/2826.821e01b07d92e948.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{9pw9EXtXjdM7EFrCXUEPf → OI4n_CKC-lM8IQbvGJ_tK}/_ssgManifest.js +0 -0
|
@@ -15,7 +15,7 @@ import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
|
15
15
|
import { buildSkillActivationBlock } from "./auto-prompts.js";
|
|
16
16
|
import { deriveState } from "./state.js";
|
|
17
17
|
import { invalidateAllCaches } from "./cache.js";
|
|
18
|
-
import {
|
|
18
|
+
import { startAutoDetached } from "./auto.js";
|
|
19
19
|
import { clearLock } from "./crash-recovery.js";
|
|
20
20
|
import {
|
|
21
21
|
assessInterruptedSession,
|
|
@@ -67,7 +67,6 @@ export {
|
|
|
67
67
|
showQueue, handleQueueReorder, showQueueAdd,
|
|
68
68
|
buildExistingMilestonesContext,
|
|
69
69
|
} from "./guided-flow-queue.js";
|
|
70
|
-
import { getErrorMessage } from "./error-utils.js";
|
|
71
70
|
import { logWarning } from "./workflow-logger.js";
|
|
72
71
|
|
|
73
72
|
// ─── ID Generation with Reservation ─────────────────────────────────────────
|
|
@@ -244,11 +243,7 @@ export function checkAutoStartAfterDiscuss(): boolean {
|
|
|
244
243
|
|
|
245
244
|
pendingAutoStartMap.delete(basePath);
|
|
246
245
|
ctx.ui.notify(`Milestone ${milestoneId} ready.`, "info");
|
|
247
|
-
|
|
248
|
-
ctx.ui.notify(`Auto-start failed: ${getErrorMessage(err)}`, "error");
|
|
249
|
-
logWarning("guided", `auto start error: ${getErrorMessage(err)}`);
|
|
250
|
-
debugLog("auto-start-failed", { error: getErrorMessage(err) });
|
|
251
|
-
});
|
|
246
|
+
startAutoDetached(ctx, pi, basePath, false, { step });
|
|
252
247
|
return true;
|
|
253
248
|
}
|
|
254
249
|
|
|
@@ -426,8 +421,9 @@ function resolveAvailableModel<T extends { id: string; provider: string }>(
|
|
|
426
421
|
* Build the discuss-and-plan prompt for a new milestone.
|
|
427
422
|
* Used by all three "new milestone" paths (first ever, no active, all complete).
|
|
428
423
|
*/
|
|
429
|
-
function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string, preparationContext?: string): string {
|
|
424
|
+
function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string, pi: ExtensionAPI, ctx: ExtensionCommandContext, preparationContext?: string): string {
|
|
430
425
|
const milestoneRel = `.gsd/milestones/${nextId}`;
|
|
426
|
+
const structuredQuestionsAvailable = getStructuredQuestionsAvailability(pi, ctx);
|
|
431
427
|
const inlinedTemplates = [
|
|
432
428
|
inlineTemplate("project", "Project"),
|
|
433
429
|
inlineTemplate("requirements", "Requirements"),
|
|
@@ -439,6 +435,7 @@ function buildDiscussPrompt(nextId: string, preamble: string, _basePath: string,
|
|
|
439
435
|
milestoneId: nextId,
|
|
440
436
|
preamble,
|
|
441
437
|
preparationContext: preparationContext ?? "",
|
|
438
|
+
structuredQuestionsAvailable,
|
|
442
439
|
contextPath: `${milestoneRel}/${nextId}-CONTEXT.md`,
|
|
443
440
|
roadmapPath: `${milestoneRel}/${nextId}-ROADMAP.md`,
|
|
444
441
|
inlinedTemplates,
|
|
@@ -486,6 +483,7 @@ function buildHeadlessDiscussPrompt(nextId: string, seedContext: string, _basePa
|
|
|
486
483
|
*/
|
|
487
484
|
async function prepareAndBuildDiscussPrompt(
|
|
488
485
|
ctx: ExtensionCommandContext,
|
|
486
|
+
pi: ExtensionAPI,
|
|
489
487
|
nextId: string,
|
|
490
488
|
preamble: string,
|
|
491
489
|
basePath: string,
|
|
@@ -520,7 +518,7 @@ async function prepareAndBuildDiscussPrompt(
|
|
|
520
518
|
}
|
|
521
519
|
}
|
|
522
520
|
|
|
523
|
-
return buildDiscussPrompt(nextId, preamble, basePath, preparationContext);
|
|
521
|
+
return buildDiscussPrompt(nextId, preamble, basePath, pi, ctx, preparationContext);
|
|
524
522
|
}
|
|
525
523
|
|
|
526
524
|
/**
|
|
@@ -780,7 +778,7 @@ export async function showDiscuss(
|
|
|
780
778
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
781
779
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
782
780
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: false, createdAt: Date.now() });
|
|
783
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
781
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId, `New milestone ${nextId}.`, basePath), "gsd-run", ctx, "discuss-milestone");
|
|
784
782
|
}
|
|
785
783
|
return;
|
|
786
784
|
}
|
|
@@ -1185,7 +1183,7 @@ async function handleMilestoneActions(
|
|
|
1185
1183
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1186
1184
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1187
1185
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1188
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1186
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1189
1187
|
`New milestone ${nextId}.`,
|
|
1190
1188
|
basePath
|
|
1191
1189
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1302,7 +1300,7 @@ export async function showSmartEntry(
|
|
|
1302
1300
|
],
|
|
1303
1301
|
});
|
|
1304
1302
|
if (resume === "resume") {
|
|
1305
|
-
|
|
1303
|
+
startAutoDetached(ctx, pi, basePath, false, {
|
|
1306
1304
|
interrupted,
|
|
1307
1305
|
step: interrupted.pausedSession?.stepMode ?? false,
|
|
1308
1306
|
});
|
|
@@ -1375,7 +1373,7 @@ export async function showSmartEntry(
|
|
|
1375
1373
|
if (isFirst) {
|
|
1376
1374
|
// First ever — skip wizard, just ask directly
|
|
1377
1375
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1378
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1376
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1379
1377
|
`New project, milestone ${nextId}. Do NOT read or explore .gsd/ — it's empty scaffolding.`,
|
|
1380
1378
|
basePath
|
|
1381
1379
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1396,7 +1394,7 @@ export async function showSmartEntry(
|
|
|
1396
1394
|
|
|
1397
1395
|
if (choice === "new_milestone") {
|
|
1398
1396
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1399
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1397
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1400
1398
|
`New milestone ${nextId}.`,
|
|
1401
1399
|
basePath
|
|
1402
1400
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1435,7 +1433,7 @@ export async function showSmartEntry(
|
|
|
1435
1433
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1436
1434
|
|
|
1437
1435
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1438
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1436
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1439
1437
|
`New milestone ${nextId}.`,
|
|
1440
1438
|
basePath
|
|
1441
1439
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1502,7 +1500,7 @@ export async function showSmartEntry(
|
|
|
1502
1500
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1503
1501
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1504
1502
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1505
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1503
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1506
1504
|
`New milestone ${nextId}.`,
|
|
1507
1505
|
basePath
|
|
1508
1506
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1599,7 +1597,7 @@ export async function showSmartEntry(
|
|
|
1599
1597
|
const uniqueMilestoneIds = !!loadEffectiveGSDPreferences()?.preferences?.unique_milestone_ids;
|
|
1600
1598
|
const nextId = nextMilestoneIdReserved(milestoneIds, uniqueMilestoneIds);
|
|
1601
1599
|
pendingAutoStartMap.set(basePath, { ctx, pi, basePath, milestoneId: nextId, step: stepMode, createdAt: Date.now() });
|
|
1602
|
-
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, nextId,
|
|
1600
|
+
await dispatchWorkflow(pi, await prepareAndBuildDiscussPrompt(ctx, pi, nextId,
|
|
1603
1601
|
`New milestone ${nextId}.`,
|
|
1604
1602
|
basePath
|
|
1605
1603
|
), "gsd-run", ctx, "discuss-milestone");
|
|
@@ -1644,7 +1642,7 @@ export async function showSmartEntry(
|
|
|
1644
1642
|
});
|
|
1645
1643
|
|
|
1646
1644
|
if (choice === "auto") {
|
|
1647
|
-
|
|
1645
|
+
startAutoDetached(ctx, pi, basePath, false);
|
|
1648
1646
|
} else if (choice === "status") {
|
|
1649
1647
|
const { fireStatusViaCommand } = await import("./commands.js");
|
|
1650
1648
|
await fireStatusViaCommand(ctx);
|
|
@@ -1856,7 +1854,7 @@ export async function showSmartEntry(
|
|
|
1856
1854
|
});
|
|
1857
1855
|
|
|
1858
1856
|
if (choice === "auto") {
|
|
1859
|
-
|
|
1857
|
+
startAutoDetached(ctx, pi, basePath, false);
|
|
1860
1858
|
return;
|
|
1861
1859
|
}
|
|
1862
1860
|
|
|
@@ -274,19 +274,9 @@ export async function showProjectInit(
|
|
|
274
274
|
// Non-fatal — STATE.md will be regenerated on next /gsd invocation
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const result = ensureProjectWorkflowMcpConfig(basePath);
|
|
281
|
-
if (result.status !== "unchanged") {
|
|
282
|
-
ctx.ui.notify(`Claude Code MCP prepared at ${result.configPath}`, "info");
|
|
283
|
-
}
|
|
284
|
-
} catch (err) {
|
|
285
|
-
ctx.ui.notify(
|
|
286
|
-
`Claude Code MCP prep failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
287
|
-
"warning",
|
|
288
|
-
);
|
|
289
|
-
}
|
|
277
|
+
{
|
|
278
|
+
const { prepareWorkflowMcpForProject } = await import("./workflow-mcp-auto-prep.js");
|
|
279
|
+
prepareWorkflowMcpForProject(ctx, basePath);
|
|
290
280
|
}
|
|
291
281
|
|
|
292
282
|
ctx.ui.notify("GSD initialized. Starting your first milestone...", "info");
|
|
@@ -41,6 +41,7 @@ export interface UnitMetrics {
|
|
|
41
41
|
model: string; // model ID used
|
|
42
42
|
startedAt: number; // ms timestamp
|
|
43
43
|
finishedAt: number; // ms timestamp
|
|
44
|
+
autoSessionKey?: string; // identifies one auto-mode run across pause/resume
|
|
44
45
|
tokens: TokenCounts;
|
|
45
46
|
cost: number; // total USD cost
|
|
46
47
|
toolCalls: number;
|
|
@@ -133,7 +134,16 @@ export function snapshotUnitMetrics(
|
|
|
133
134
|
unitId: string,
|
|
134
135
|
startedAt: number,
|
|
135
136
|
model: string,
|
|
136
|
-
opts?: {
|
|
137
|
+
opts?: {
|
|
138
|
+
tier?: string;
|
|
139
|
+
modelDowngraded?: boolean;
|
|
140
|
+
contextWindowTokens?: number;
|
|
141
|
+
truncationSections?: number;
|
|
142
|
+
continueHereFired?: boolean;
|
|
143
|
+
promptCharCount?: number;
|
|
144
|
+
baselineCharCount?: number;
|
|
145
|
+
autoSessionKey?: string;
|
|
146
|
+
},
|
|
137
147
|
): UnitMetrics | null {
|
|
138
148
|
if (!ledger) return null;
|
|
139
149
|
|
|
@@ -181,6 +191,7 @@ export function snapshotUnitMetrics(
|
|
|
181
191
|
model,
|
|
182
192
|
startedAt,
|
|
183
193
|
finishedAt: Date.now(),
|
|
194
|
+
...(opts?.autoSessionKey ? { autoSessionKey: opts.autoSessionKey } : {}),
|
|
184
195
|
tokens,
|
|
185
196
|
cost,
|
|
186
197
|
toolCalls,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "./paths.js";
|
|
21
21
|
import { invalidateAllCaches } from "./cache.js";
|
|
22
22
|
import { loadQueueOrder, saveQueueOrder } from "./queue-order.js";
|
|
23
|
-
import { isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
23
|
+
import { getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
24
24
|
import { logWarning } from "./workflow-logger.js";
|
|
25
25
|
|
|
26
26
|
// ─── Park ──────────────────────────────────────────────────────────────────
|
|
@@ -77,9 +77,16 @@ export function unparkMilestone(basePath: string, milestoneId: string): boolean
|
|
|
77
77
|
if (!mDir || !existsSync(mDir)) return false;
|
|
78
78
|
|
|
79
79
|
const parkedPath = join(mDir, buildMilestoneFileName(milestoneId, "PARKED"));
|
|
80
|
-
|
|
80
|
+
const hadParkedFile = existsSync(parkedPath);
|
|
81
|
+
const dbThinksParked = isDbAvailable() && getMilestone(milestoneId)?.status === "parked";
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
// Recover the reverse desync too: DB can still say "parked" even when the
|
|
84
|
+
// PARKED marker was lost on disk, and /gsd unpark should repair that state.
|
|
85
|
+
if (!hadParkedFile && !dbThinksParked) return false;
|
|
86
|
+
|
|
87
|
+
if (hadParkedFile) {
|
|
88
|
+
unlinkSync(parkedPath);
|
|
89
|
+
}
|
|
83
90
|
// Sync DB status so deriveStateFromDb picks up the unparked milestone (#2694)
|
|
84
91
|
if (isDbAvailable()) {
|
|
85
92
|
try {
|
|
@@ -6,19 +6,13 @@
|
|
|
6
6
|
* records in the DB. This module inserts milestone-level validation gates
|
|
7
7
|
* that correspond to the validation checks performed.
|
|
8
8
|
*
|
|
9
|
-
* Gate IDs for milestone validation
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* MV03 — Cross-slice integration
|
|
13
|
-
* MV04 — Requirement coverage
|
|
14
|
-
*
|
|
15
|
-
* These use the existing quality_gates table with scope "milestone".
|
|
9
|
+
* Gate IDs for milestone validation (MV01–MV04) are sourced from the
|
|
10
|
+
* gate registry so the definitions stay in lockstep with prompt builders,
|
|
11
|
+
* dispatch rules, and state derivation. See gate-registry.ts.
|
|
16
12
|
*/
|
|
17
13
|
|
|
18
14
|
import { _getAdapter } from "./gsd-db.js";
|
|
19
|
-
|
|
20
|
-
/** Milestone validation gate IDs. */
|
|
21
|
-
const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"] as const;
|
|
15
|
+
import { getGatesForTurn } from "./gate-registry.js";
|
|
22
16
|
|
|
23
17
|
/**
|
|
24
18
|
* Insert milestone-level quality_gates records for a validation run.
|
|
@@ -27,6 +21,9 @@ const MILESTONE_GATE_IDS = ["MV01", "MV02", "MV03", "MV04"] as const;
|
|
|
27
21
|
* from the overall milestone validation verdict. Individual gate-level
|
|
28
22
|
* verdicts are not available (the handler receives a single verdict),
|
|
29
23
|
* so all gates share the overall verdict.
|
|
24
|
+
*
|
|
25
|
+
* Gate IDs come from the registry — adding/removing an MV-scoped gate
|
|
26
|
+
* in gate-registry.ts automatically flows through here.
|
|
30
27
|
*/
|
|
31
28
|
export function insertMilestoneValidationGates(
|
|
32
29
|
milestoneId: string,
|
|
@@ -38,8 +35,9 @@ export function insertMilestoneValidationGates(
|
|
|
38
35
|
if (!db) return;
|
|
39
36
|
|
|
40
37
|
const gateVerdict = verdict === "pass" ? "pass" : "flag";
|
|
38
|
+
const milestoneGates = getGatesForTurn("validate-milestone");
|
|
41
39
|
|
|
42
|
-
for (const
|
|
40
|
+
for (const def of milestoneGates) {
|
|
43
41
|
db.prepare(
|
|
44
42
|
`INSERT OR REPLACE INTO quality_gates
|
|
45
43
|
(milestone_id, slice_id, gate_id, scope, task_id, status, verdict, rationale, findings, evaluated_at)
|
|
@@ -47,9 +45,9 @@ export function insertMilestoneValidationGates(
|
|
|
47
45
|
).run({
|
|
48
46
|
":mid": milestoneId,
|
|
49
47
|
":sid": sliceId,
|
|
50
|
-
":gid":
|
|
48
|
+
":gid": def.id,
|
|
51
49
|
":verdict": gateVerdict,
|
|
52
|
-
":rationale":
|
|
50
|
+
":rationale": `${def.promptSection} — milestone validation verdict: ${verdict}`,
|
|
53
51
|
":evaluated_at": evaluatedAt,
|
|
54
52
|
});
|
|
55
53
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// GSD Extension — Notification History Overlay
|
|
2
2
|
// Scrollable panel showing all persisted notifications with severity filtering.
|
|
3
|
-
// Toggled with Ctrl+Alt+N (⌃⌥N on macOS)
|
|
3
|
+
// Toggled with Ctrl+Alt+N (⌃⌥N on macOS), Ctrl+Shift+N fallback, or /gsd notifications.
|
|
4
4
|
|
|
5
5
|
import type { Theme } from "@gsd/pi-coding-agent";
|
|
6
6
|
import { truncateToWidth, visibleWidth, matchesKey, Key } from "@gsd/pi-tui";
|
|
@@ -9,11 +9,12 @@ import {
|
|
|
9
9
|
readNotifications,
|
|
10
10
|
markAllRead,
|
|
11
11
|
clearNotifications,
|
|
12
|
-
|
|
12
|
+
onNotificationStoreChange,
|
|
13
13
|
type NotificationEntry,
|
|
14
14
|
type NotifySeverity,
|
|
15
15
|
} from "./notification-store.js";
|
|
16
|
-
import {
|
|
16
|
+
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
17
|
+
import { padRight, joinColumns } from "../shared/mod.js";
|
|
17
18
|
|
|
18
19
|
type FilterMode = "all" | "error" | "warning" | "info";
|
|
19
20
|
const FILTER_CYCLE: FilterMode[] = ["all", "error", "warning", "info"];
|
|
@@ -63,6 +64,12 @@ function formatTimestamp(ts: string): string {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
function notificationSignature(entries: readonly NotificationEntry[]): string {
|
|
68
|
+
return entries
|
|
69
|
+
.map((entry) => `${entry.ts}|${entry.severity}|${entry.read ? 1 : 0}|${entry.message}`)
|
|
70
|
+
.join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
66
73
|
export class GSDNotificationOverlay {
|
|
67
74
|
private tui: { requestRender: () => void };
|
|
68
75
|
private theme: Theme;
|
|
@@ -72,9 +79,11 @@ export class GSDNotificationOverlay {
|
|
|
72
79
|
private scrollOffset = 0;
|
|
73
80
|
private filterIndex = 0;
|
|
74
81
|
private entries: NotificationEntry[] = [];
|
|
82
|
+
private entriesSignature = "";
|
|
75
83
|
private refreshTimer: ReturnType<typeof setInterval>;
|
|
76
84
|
private disposed = false;
|
|
77
85
|
private resizeHandler: (() => void) | null = null;
|
|
86
|
+
private unsubscribeStore: (() => void) | null = null;
|
|
78
87
|
|
|
79
88
|
constructor(
|
|
80
89
|
tui: { requestRender: () => void },
|
|
@@ -88,6 +97,7 @@ export class GSDNotificationOverlay {
|
|
|
88
97
|
// Mark all as read on open
|
|
89
98
|
markAllRead();
|
|
90
99
|
this.entries = readNotifications();
|
|
100
|
+
this.entriesSignature = notificationSignature(this.entries);
|
|
91
101
|
|
|
92
102
|
// Resize handler
|
|
93
103
|
this.resizeHandler = () => {
|
|
@@ -97,17 +107,17 @@ export class GSDNotificationOverlay {
|
|
|
97
107
|
};
|
|
98
108
|
process.stdout.on("resize", this.resizeHandler);
|
|
99
109
|
|
|
100
|
-
//
|
|
110
|
+
// Subscribe to store mutations for immediate updates
|
|
111
|
+
this.unsubscribeStore = onNotificationStoreChange(() => {
|
|
112
|
+
if (this.disposed) return;
|
|
113
|
+
this._refreshFromDisk();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 30s safety-net for cross-process edits (web subprocess, parallel workers)
|
|
101
117
|
this.refreshTimer = setInterval(() => {
|
|
102
118
|
if (this.disposed) return;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
this.entries = fresh;
|
|
106
|
-
markAllRead();
|
|
107
|
-
this.invalidate();
|
|
108
|
-
this.tui.requestRender();
|
|
109
|
-
}
|
|
110
|
-
}, 3000);
|
|
119
|
+
this._refreshFromDisk();
|
|
120
|
+
}, 30_000);
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
private get filter(): FilterMode {
|
|
@@ -120,7 +130,12 @@ export class GSDNotificationOverlay {
|
|
|
120
130
|
}
|
|
121
131
|
|
|
122
132
|
handleInput(data: string): void {
|
|
123
|
-
if (
|
|
133
|
+
if (
|
|
134
|
+
matchesKey(data, Key.escape) ||
|
|
135
|
+
matchesKey(data, Key.ctrl("c")) ||
|
|
136
|
+
matchesKey(data, Key.ctrlAlt("n")) ||
|
|
137
|
+
matchesKey(data, Key.ctrlShift("n"))
|
|
138
|
+
) {
|
|
124
139
|
this.dispose();
|
|
125
140
|
this.onClose();
|
|
126
141
|
return;
|
|
@@ -165,6 +180,7 @@ export class GSDNotificationOverlay {
|
|
|
165
180
|
if (data === "c") {
|
|
166
181
|
clearNotifications();
|
|
167
182
|
this.entries = [];
|
|
183
|
+
this.entriesSignature = notificationSignature(this.entries);
|
|
168
184
|
this.scrollOffset = 0;
|
|
169
185
|
this.invalidate();
|
|
170
186
|
this.tui.requestRender();
|
|
@@ -199,12 +215,28 @@ export class GSDNotificationOverlay {
|
|
|
199
215
|
dispose(): void {
|
|
200
216
|
this.disposed = true;
|
|
201
217
|
clearInterval(this.refreshTimer);
|
|
218
|
+
if (this.unsubscribeStore) {
|
|
219
|
+
this.unsubscribeStore();
|
|
220
|
+
this.unsubscribeStore = null;
|
|
221
|
+
}
|
|
202
222
|
if (this.resizeHandler) {
|
|
203
223
|
process.stdout.removeListener("resize", this.resizeHandler);
|
|
204
224
|
this.resizeHandler = null;
|
|
205
225
|
}
|
|
206
226
|
}
|
|
207
227
|
|
|
228
|
+
private _refreshFromDisk(): void {
|
|
229
|
+
const fresh = readNotifications();
|
|
230
|
+
const signature = notificationSignature(fresh);
|
|
231
|
+
if (signature !== this.entriesSignature) {
|
|
232
|
+
markAllRead();
|
|
233
|
+
this.entries = readNotifications();
|
|
234
|
+
this.entriesSignature = notificationSignature(this.entries);
|
|
235
|
+
this.invalidate();
|
|
236
|
+
this.tui.requestRender();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
208
240
|
private wrapInBox(inner: string[], width: number): string[] {
|
|
209
241
|
const th = this.theme;
|
|
210
242
|
const border = (s: string) => th.fg("borderAccent", s);
|
|
@@ -250,7 +282,8 @@ export class GSDNotificationOverlay {
|
|
|
250
282
|
lines.push(hr());
|
|
251
283
|
|
|
252
284
|
// Controls
|
|
253
|
-
|
|
285
|
+
const closeShortcut = formattedShortcutPair("notifications");
|
|
286
|
+
lines.push(row(th.fg("dim", `↑/↓ scroll f filter c clear Esc close (${closeShortcut})`)));
|
|
254
287
|
lines.push(blank());
|
|
255
288
|
|
|
256
289
|
// Entries
|
|
@@ -26,12 +26,16 @@ export interface NotificationEntry {
|
|
|
26
26
|
const MAX_ENTRIES = 500;
|
|
27
27
|
const FILENAME = "notifications.jsonl";
|
|
28
28
|
const LOCKFILE = "notifications.lock";
|
|
29
|
+
const DEDUP_WINDOW_MS = 30_000;
|
|
30
|
+
const DEDUP_PRUNE_THRESHOLD = 200;
|
|
29
31
|
|
|
30
32
|
// ─── Module State ───────────────────────────────────────────────────────
|
|
31
33
|
|
|
32
34
|
let _basePath: string | null = null;
|
|
33
35
|
let _lineCount = 0; // Hint for rotation — not authoritative for public API
|
|
34
36
|
let _suppressCount = 0;
|
|
37
|
+
let _recentMessageTimestamps = new Map<string, number>();
|
|
38
|
+
const _changeListeners = new Set<() => void>();
|
|
35
39
|
|
|
36
40
|
// ─── Public API ─────────────────────────────────────────────────────────
|
|
37
41
|
|
|
@@ -40,6 +44,9 @@ let _suppressCount = 0;
|
|
|
40
44
|
* project root. Seeds in-memory counters from the existing file on disk.
|
|
41
45
|
*/
|
|
42
46
|
export function initNotificationStore(basePath: string): void {
|
|
47
|
+
if (_basePath !== basePath) {
|
|
48
|
+
_recentMessageTimestamps.clear();
|
|
49
|
+
}
|
|
43
50
|
_basePath = basePath;
|
|
44
51
|
// Seed line count hint for rotation — public counters read from disk
|
|
45
52
|
_lineCount = _readEntriesFromDisk(basePath).length;
|
|
@@ -56,12 +63,23 @@ export function appendNotification(
|
|
|
56
63
|
): void {
|
|
57
64
|
if (!_basePath) return;
|
|
58
65
|
if (_suppressCount > 0) return;
|
|
66
|
+
const persistedMessage = message.length > 500 ? message.slice(0, 500) + "…" : message;
|
|
67
|
+
const dedupKey = `${_basePath}:${severity}:${source}:${persistedMessage}`;
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const lastSeen = _recentMessageTimestamps.get(dedupKey);
|
|
70
|
+
if (lastSeen !== undefined && now - lastSeen < DEDUP_WINDOW_MS) return;
|
|
71
|
+
_recentMessageTimestamps.set(dedupKey, now);
|
|
72
|
+
if (_recentMessageTimestamps.size > DEDUP_PRUNE_THRESHOLD) {
|
|
73
|
+
for (const [key, ts] of _recentMessageTimestamps) {
|
|
74
|
+
if (now - ts > DEDUP_WINDOW_MS) _recentMessageTimestamps.delete(key);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
59
77
|
|
|
60
78
|
const entry: NotificationEntry = {
|
|
61
79
|
id: randomUUID(),
|
|
62
80
|
ts: new Date().toISOString(),
|
|
63
81
|
severity,
|
|
64
|
-
message:
|
|
82
|
+
message: persistedMessage,
|
|
65
83
|
source,
|
|
66
84
|
read: false,
|
|
67
85
|
};
|
|
@@ -76,6 +94,7 @@ export function appendNotification(
|
|
|
76
94
|
if (_lineCount > MAX_ENTRIES) {
|
|
77
95
|
_rotate();
|
|
78
96
|
}
|
|
97
|
+
_emitChange();
|
|
79
98
|
} catch {
|
|
80
99
|
// Non-fatal — never let persistence break the caller
|
|
81
100
|
}
|
|
@@ -104,6 +123,7 @@ export function markAllRead(basePath?: string): void {
|
|
|
104
123
|
const hasUnread = entries.some((e) => !e.read);
|
|
105
124
|
if (!hasUnread) return;
|
|
106
125
|
|
|
126
|
+
let changed = false;
|
|
107
127
|
try {
|
|
108
128
|
_withLock(bp, () => {
|
|
109
129
|
// Re-read inside lock to get freshest state
|
|
@@ -111,10 +131,12 @@ export function markAllRead(basePath?: string): void {
|
|
|
111
131
|
if (fresh.length === 0 || !fresh.some((e) => !e.read)) return;
|
|
112
132
|
const lines = fresh.map((e) => JSON.stringify({ ...e, read: true }));
|
|
113
133
|
_atomicWrite(bp, lines.join("\n") + "\n");
|
|
134
|
+
changed = true;
|
|
114
135
|
});
|
|
115
136
|
} catch {
|
|
116
137
|
// Non-fatal
|
|
117
138
|
}
|
|
139
|
+
if (changed) _emitChange();
|
|
118
140
|
}
|
|
119
141
|
|
|
120
142
|
/**
|
|
@@ -128,6 +150,8 @@ export function clearNotifications(basePath?: string): void {
|
|
|
128
150
|
_withLock(bp, () => {
|
|
129
151
|
_atomicWrite(bp, "");
|
|
130
152
|
});
|
|
153
|
+
_lineCount = 0;
|
|
154
|
+
_emitChange();
|
|
131
155
|
} catch {
|
|
132
156
|
// Non-fatal
|
|
133
157
|
}
|
|
@@ -172,6 +196,17 @@ export function unsuppressPersistence(): void {
|
|
|
172
196
|
_suppressCount = Math.max(0, _suppressCount - 1);
|
|
173
197
|
}
|
|
174
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Subscribe to notification-store mutations (append, mark-read, clear).
|
|
201
|
+
* Returns an unsubscribe function.
|
|
202
|
+
*/
|
|
203
|
+
export function onNotificationStoreChange(listener: () => void): () => void {
|
|
204
|
+
_changeListeners.add(listener);
|
|
205
|
+
return () => {
|
|
206
|
+
_changeListeners.delete(listener);
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
175
210
|
// ─── Test Helpers ───────────────────────────────────────────────────────
|
|
176
211
|
|
|
177
212
|
/**
|
|
@@ -181,6 +216,8 @@ export function _resetNotificationStore(): void {
|
|
|
181
216
|
_basePath = null;
|
|
182
217
|
_lineCount = 0;
|
|
183
218
|
_suppressCount = 0;
|
|
219
|
+
_recentMessageTimestamps = new Map();
|
|
220
|
+
_changeListeners.clear();
|
|
184
221
|
}
|
|
185
222
|
|
|
186
223
|
// ─── Internal ───────────────────────────────────────────────────────────
|
|
@@ -216,12 +253,23 @@ function _rotate(): void {
|
|
|
216
253
|
const trimmed = entries.slice(entries.length - MAX_ENTRIES);
|
|
217
254
|
const lines = trimmed.map((e) => JSON.stringify(e));
|
|
218
255
|
_atomicWrite(_basePath!, lines.join("\n") + "\n");
|
|
256
|
+
_lineCount = trimmed.length;
|
|
219
257
|
});
|
|
220
258
|
} catch {
|
|
221
259
|
// Non-fatal
|
|
222
260
|
}
|
|
223
261
|
}
|
|
224
262
|
|
|
263
|
+
function _emitChange(): void {
|
|
264
|
+
for (const listener of _changeListeners) {
|
|
265
|
+
try {
|
|
266
|
+
listener();
|
|
267
|
+
} catch {
|
|
268
|
+
// Non-fatal
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
225
273
|
/**
|
|
226
274
|
* Atomic file rewrite via temp-file + rename. Prevents partial reads
|
|
227
275
|
* by other processes (web API subprocess, parallel workers).
|
|
@@ -275,10 +323,11 @@ function _withLock<T>(basePath: string, fn: () => T): T {
|
|
|
275
323
|
}
|
|
276
324
|
}
|
|
277
325
|
|
|
278
|
-
//
|
|
279
|
-
|
|
326
|
+
// Best-effort: mutation runs regardless of lock status (idempotent overwrites).
|
|
327
|
+
// createdLock gates cleanup only — never skip fn() on lock failure.
|
|
328
|
+
const createdLock = fd !== null;
|
|
280
329
|
try {
|
|
281
|
-
if (
|
|
330
|
+
if (createdLock && fd !== null) {
|
|
282
331
|
// Write our PID timestamp into the lock for stale detection
|
|
283
332
|
writeFileSync(lockPath, String(Date.now()), "utf-8");
|
|
284
333
|
closeSync(fd);
|
|
@@ -286,7 +335,7 @@ function _withLock<T>(basePath: string, fn: () => T): T {
|
|
|
286
335
|
return fn();
|
|
287
336
|
} finally {
|
|
288
337
|
// Only delete the lock if we created it — never remove another process's lock
|
|
289
|
-
if (
|
|
338
|
+
if (createdLock) {
|
|
290
339
|
try { unlinkSync(lockPath); } catch { /* best-effort cleanup */ }
|
|
291
340
|
}
|
|
292
341
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
7
7
|
|
|
8
|
-
import { getUnreadCount,
|
|
9
|
-
import {
|
|
8
|
+
import { getUnreadCount, onNotificationStoreChange } from "./notification-store.js";
|
|
9
|
+
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
10
10
|
|
|
11
11
|
// ─── Pure rendering ──���────────────────────────���─────────────────────────
|
|
12
12
|
|
|
@@ -14,18 +14,7 @@ export function buildNotificationWidgetLines(): string[] {
|
|
|
14
14
|
const unread = getUnreadCount();
|
|
15
15
|
if (unread === 0) return [];
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
const latest = entries[0]; // newest-first
|
|
19
|
-
if (!latest) return [];
|
|
20
|
-
|
|
21
|
-
const icon = latest.severity === "error" ? "✗" : latest.severity === "warning" ? "⚠" : "●";
|
|
22
|
-
const badge = `${unread} unread`;
|
|
23
|
-
const msgMax = 80;
|
|
24
|
-
const truncated = latest.message.length > msgMax
|
|
25
|
-
? latest.message.slice(0, msgMax - 1) + "…"
|
|
26
|
-
: latest.message;
|
|
27
|
-
|
|
28
|
-
return [` ${icon} [${badge}] ${truncated} (${formatShortcut("Ctrl+Alt+N")} to view)`];
|
|
17
|
+
return [` 🔔 Notifications: ${unread} unread (${formattedShortcutPair("notifications")})`];
|
|
29
18
|
}
|
|
30
19
|
|
|
31
20
|
// ─── Widget init ────────────────────────────────────────────────────────
|
|
@@ -51,6 +40,7 @@ export function initNotificationWidget(ctx: ExtensionContext): void {
|
|
|
51
40
|
_tui.requestRender();
|
|
52
41
|
};
|
|
53
42
|
|
|
43
|
+
const unsubscribe = onNotificationStoreChange(refresh);
|
|
54
44
|
const refreshTimer = setInterval(refresh, REFRESH_INTERVAL_MS);
|
|
55
45
|
|
|
56
46
|
return {
|
|
@@ -62,6 +52,7 @@ export function initNotificationWidget(ctx: ExtensionContext): void {
|
|
|
62
52
|
cachedLines = undefined;
|
|
63
53
|
},
|
|
64
54
|
dispose(): void {
|
|
55
|
+
unsubscribe();
|
|
65
56
|
clearInterval(refreshTimer);
|
|
66
57
|
},
|
|
67
58
|
};
|