gsd-pi 2.63.0-dev.d04bbc5 → 2.64.0-dev.05b8a94
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/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/gsd/auto-dashboard.js +5 -5
- package/dist/resources/extensions/gsd/auto-post-unit.js +98 -1
- package/dist/resources/extensions/gsd/auto-verification.js +138 -1
- package/dist/resources/extensions/gsd/auto.js +5 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +24 -13
- package/dist/resources/extensions/gsd/bootstrap/notify-interceptor.js +28 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +8 -0
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +15 -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/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +103 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +224 -0
- package/dist/resources/extensions/gsd/notification-store.js +268 -0
- package/dist/resources/extensions/gsd/notification-widget.js +56 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +407 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +464 -0
- package/dist/resources/extensions/gsd/preferences-types.js +4 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +33 -0
- package/dist/resources/extensions/gsd/preferences.js +4 -0
- package/dist/resources/extensions/gsd/verification-evidence.js +18 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +8 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +20 -19
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.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 +20 -19
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- 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/Vbx2-SrSBOgta6576xj9m/_buildManifest.js +1 -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/server.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/modes/interactive/components/tool-execution.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +8 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.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 +36 -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/modes/interactive/components/tool-execution.ts +9 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +33 -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/tui.d.ts +2 -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/components/loader.ts +27 -10
- package/packages/pi-tui/src/components/text.ts +1 -0
- package/packages/pi-tui/src/tui.ts +32 -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/gsd/auto-dashboard.ts +5 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +122 -0
- package/src/resources/extensions/gsd/auto-verification.ts +190 -2
- package/src/resources/extensions/gsd/auto.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +25 -13
- package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +8 -0
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +19 -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/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +139 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +267 -0
- package/src/resources/extensions/gsd/notification-store.ts +288 -0
- package/src/resources/extensions/gsd/notification-widget.ts +68 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +539 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +573 -0
- package/src/resources/extensions/gsd/preferences-types.ts +28 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +33 -0
- package/src/resources/extensions/gsd/preferences.ts +4 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +526 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +249 -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-execution-checks.test.ts +999 -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/unstructured-continue-context-injection.test.ts +163 -0
- package/src/resources/extensions/gsd/verification-evidence.ts +68 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +13 -0
- 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/vIq9fmvRUaFOpguoX5j4W/_buildManifest.js +0 -1
- /package/dist/web/standalone/.next/static/{vIq9fmvRUaFOpguoX5j4W → Vbx2-SrSBOgta6576xj9m}/_ssgManifest.js +0 -0
|
@@ -18,6 +18,7 @@ import { loadFile, parseSummary, resolveAllOverrides } from "./files.js";
|
|
|
18
18
|
import { loadPrompt } from "./prompt-loader.js";
|
|
19
19
|
import {
|
|
20
20
|
resolveSliceFile,
|
|
21
|
+
resolveSlicePath,
|
|
21
22
|
resolveTaskFile,
|
|
22
23
|
resolveMilestoneFile,
|
|
23
24
|
resolveTasksDir,
|
|
@@ -59,6 +60,10 @@ import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
|
59
60
|
import { validateContent } from "./safety/content-validator.js";
|
|
60
61
|
import { resolveSafetyHarnessConfig } from "./safety/safety-harness.js";
|
|
61
62
|
import { resolveExpectedArtifactPath as resolveArtifactForContent } from "./auto-artifact-paths.js";
|
|
63
|
+
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
64
|
+
import { getSliceTasks } from "./gsd-db.js";
|
|
65
|
+
import { runPreExecutionChecks, type PreExecutionResult } from "./pre-execution-checks.js";
|
|
66
|
+
import { writePreExecutionEvidence } from "./verification-evidence.js";
|
|
62
67
|
|
|
63
68
|
/** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
|
|
64
69
|
const MAX_VERIFICATION_RETRIES = 3;
|
|
@@ -772,6 +777,123 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
772
777
|
}
|
|
773
778
|
}
|
|
774
779
|
|
|
780
|
+
// ── Pre-execution checks (after plan-slice completes) ──
|
|
781
|
+
if (
|
|
782
|
+
s.currentUnit &&
|
|
783
|
+
s.currentUnit.type === "plan-slice"
|
|
784
|
+
) {
|
|
785
|
+
let preExecPauseNeeded = false;
|
|
786
|
+
await runSafely("postUnitPostVerification", "pre-execution-checks", async () => {
|
|
787
|
+
try {
|
|
788
|
+
// Check preferences — respect enhanced_verification and enhanced_verification_pre
|
|
789
|
+
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
790
|
+
const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
|
|
791
|
+
const preEnabled = prefs?.enhanced_verification_pre !== false; // default true
|
|
792
|
+
|
|
793
|
+
if (!enhancedEnabled || !preEnabled) {
|
|
794
|
+
debugLog("postUnitPostVerification", {
|
|
795
|
+
phase: "pre-execution-checks",
|
|
796
|
+
skipped: true,
|
|
797
|
+
reason: "disabled by preferences",
|
|
798
|
+
});
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Parse the unit ID to get milestone/slice IDs
|
|
803
|
+
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit!.id);
|
|
804
|
+
if (!mid || !sid) {
|
|
805
|
+
debugLog("postUnitPostVerification", {
|
|
806
|
+
phase: "pre-execution-checks",
|
|
807
|
+
skipped: true,
|
|
808
|
+
reason: "could not parse milestone/slice from unit ID",
|
|
809
|
+
});
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Get tasks for this slice from DB
|
|
814
|
+
const tasks = getSliceTasks(mid, sid);
|
|
815
|
+
if (tasks.length === 0) {
|
|
816
|
+
debugLog("postUnitPostVerification", {
|
|
817
|
+
phase: "pre-execution-checks",
|
|
818
|
+
skipped: true,
|
|
819
|
+
reason: "no tasks found for slice",
|
|
820
|
+
});
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// Run pre-execution checks
|
|
825
|
+
const result: PreExecutionResult = await runPreExecutionChecks(tasks, s.basePath);
|
|
826
|
+
|
|
827
|
+
// Log summary to stderr in existing verification output format
|
|
828
|
+
const emoji = result.status === "pass" ? "✅" : result.status === "warn" ? "⚠️" : "❌";
|
|
829
|
+
process.stderr.write(
|
|
830
|
+
`gsd-pre-exec: ${emoji} Pre-execution checks ${result.status} for ${mid}/${sid} (${result.durationMs}ms)\n`,
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
// Log individual check results
|
|
834
|
+
for (const check of result.checks) {
|
|
835
|
+
const checkEmoji = check.passed ? "✓" : check.blocking ? "✗" : "⚠";
|
|
836
|
+
process.stderr.write(
|
|
837
|
+
`gsd-pre-exec: ${checkEmoji} [${check.category}] ${check.target}: ${check.message}\n`,
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// Write evidence JSON to slice artifacts directory
|
|
842
|
+
const slicePath = resolveSlicePath(s.basePath, mid, sid);
|
|
843
|
+
if (slicePath) {
|
|
844
|
+
writePreExecutionEvidence(result, slicePath, mid, sid);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// Notify UI
|
|
848
|
+
if (result.status === "fail") {
|
|
849
|
+
const blockingCount = result.checks.filter(c => !c.passed && c.blocking).length;
|
|
850
|
+
ctx.ui.notify(
|
|
851
|
+
`Pre-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`,
|
|
852
|
+
"error",
|
|
853
|
+
);
|
|
854
|
+
preExecPauseNeeded = true;
|
|
855
|
+
} else if (result.status === "warn") {
|
|
856
|
+
ctx.ui.notify(
|
|
857
|
+
`Pre-execution checks passed with warnings`,
|
|
858
|
+
"warning",
|
|
859
|
+
);
|
|
860
|
+
// Strict mode: treat warnings as blocking
|
|
861
|
+
if (prefs?.enhanced_verification_strict === true) {
|
|
862
|
+
preExecPauseNeeded = true;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
debugLog("postUnitPostVerification", {
|
|
867
|
+
phase: "pre-execution-checks",
|
|
868
|
+
status: result.status,
|
|
869
|
+
checkCount: result.checks.length,
|
|
870
|
+
durationMs: result.durationMs,
|
|
871
|
+
});
|
|
872
|
+
} catch (preExecError) {
|
|
873
|
+
// Fail-closed: if runPreExecutionChecks throws, pause auto-mode instead of silently continuing
|
|
874
|
+
const errorMessage = preExecError instanceof Error ? preExecError.message : String(preExecError);
|
|
875
|
+
debugLog("postUnitPostVerification", {
|
|
876
|
+
phase: "pre-execution-checks",
|
|
877
|
+
error: errorMessage,
|
|
878
|
+
failClosed: true,
|
|
879
|
+
});
|
|
880
|
+
logError("engine", `gsd-pre-exec: Pre-execution checks threw an error: ${errorMessage}`);
|
|
881
|
+
ctx.ui.notify(
|
|
882
|
+
`Pre-execution checks error: ${errorMessage} — pausing for human review`,
|
|
883
|
+
"error",
|
|
884
|
+
);
|
|
885
|
+
preExecPauseNeeded = true;
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
// Check for blocking failures after runSafely completes
|
|
890
|
+
if (preExecPauseNeeded) {
|
|
891
|
+
debugLog("postUnitPostVerification", { phase: "pre-execution-checks", pausing: true, reason: "blocking failures detected" });
|
|
892
|
+
await pauseAuto(ctx, pi);
|
|
893
|
+
return "stopped";
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
775
897
|
// ── Triage check ──
|
|
776
898
|
if (
|
|
777
899
|
!s.stepMode &&
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import type { ExtensionContext, ExtensionAPI } from "@gsd/pi-coding-agent";
|
|
14
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
14
15
|
import { resolveSliceFile, resolveSlicePath } from "./paths.js";
|
|
15
16
|
import { parseUnitId } from "./unit-id.js";
|
|
16
|
-
import { isDbAvailable, getTask } from "./gsd-db.js";
|
|
17
|
+
import { isDbAvailable, getTask, getSliceTasks, type TaskRow } from "./gsd-db.js";
|
|
17
18
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
18
19
|
import {
|
|
19
20
|
runVerificationGate,
|
|
@@ -21,9 +22,11 @@ import {
|
|
|
21
22
|
captureRuntimeErrors,
|
|
22
23
|
runDependencyAudit,
|
|
23
24
|
} from "./verification-gate.js";
|
|
24
|
-
import { writeVerificationJSON } from "./verification-evidence.js";
|
|
25
|
+
import { writeVerificationJSON, type PostExecutionCheckJSON, type EvidenceJSON } from "./verification-evidence.js";
|
|
25
26
|
import { logWarning } from "./workflow-logger.js";
|
|
27
|
+
import { runPostExecutionChecks, type PostExecutionResult } from "./post-execution-checks.js";
|
|
26
28
|
import type { AutoSession } from "./auto/session.js";
|
|
29
|
+
import type { VerificationResult as VerificationGateResult } from "./types.js";
|
|
27
30
|
import { join } from "node:path";
|
|
28
31
|
|
|
29
32
|
export interface VerificationContext {
|
|
@@ -183,11 +186,140 @@ export async function runPostUnitVerification(
|
|
|
183
186
|
return "continue";
|
|
184
187
|
}
|
|
185
188
|
|
|
189
|
+
// ── Post-execution checks (run after main verification passes for execute-task units) ──
|
|
190
|
+
let postExecChecks: PostExecutionCheckJSON[] | undefined;
|
|
191
|
+
let postExecBlockingFailure = false;
|
|
192
|
+
|
|
193
|
+
if (result.passed && mid && sid && tid) {
|
|
194
|
+
// Check preferences — respect enhanced_verification and enhanced_verification_post
|
|
195
|
+
const enhancedEnabled = prefs?.enhanced_verification !== false; // default true
|
|
196
|
+
const postEnabled = prefs?.enhanced_verification_post !== false; // default true
|
|
197
|
+
|
|
198
|
+
if (enhancedEnabled && postEnabled && isDbAvailable()) {
|
|
199
|
+
try {
|
|
200
|
+
// Get the completed task from DB
|
|
201
|
+
const taskRow = getTask(mid, sid, tid);
|
|
202
|
+
if (taskRow && taskRow.key_files && taskRow.key_files.length > 0) {
|
|
203
|
+
// Get all tasks in the slice
|
|
204
|
+
const allTasks = getSliceTasks(mid, sid);
|
|
205
|
+
// Filter to prior completed tasks (status = 'complete' or 'done', before current task)
|
|
206
|
+
const priorTasks = allTasks.filter(
|
|
207
|
+
(t: TaskRow) =>
|
|
208
|
+
(t.status === "complete" || t.status === "done") &&
|
|
209
|
+
t.id !== tid &&
|
|
210
|
+
t.sequence < taskRow.sequence
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
// Run post-execution checks
|
|
214
|
+
const postExecResult: PostExecutionResult = runPostExecutionChecks(
|
|
215
|
+
taskRow,
|
|
216
|
+
priorTasks,
|
|
217
|
+
s.basePath
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Store checks for evidence JSON
|
|
221
|
+
postExecChecks = postExecResult.checks;
|
|
222
|
+
|
|
223
|
+
// Log summary to stderr with gsd-post-exec: prefix
|
|
224
|
+
const emoji =
|
|
225
|
+
postExecResult.status === "pass"
|
|
226
|
+
? "✅"
|
|
227
|
+
: postExecResult.status === "warn"
|
|
228
|
+
? "⚠️"
|
|
229
|
+
: "❌";
|
|
230
|
+
process.stderr.write(
|
|
231
|
+
`gsd-post-exec: ${emoji} Post-execution checks ${postExecResult.status} for ${mid}/${sid}/${tid} (${postExecResult.durationMs}ms)\n`
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
// Log individual check results
|
|
235
|
+
for (const check of postExecResult.checks) {
|
|
236
|
+
const checkEmoji = check.passed
|
|
237
|
+
? "✓"
|
|
238
|
+
: check.blocking
|
|
239
|
+
? "✗"
|
|
240
|
+
: "⚠";
|
|
241
|
+
process.stderr.write(
|
|
242
|
+
`gsd-post-exec: ${checkEmoji} [${check.category}] ${check.target}: ${check.message}\n`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check for blocking failures
|
|
247
|
+
if (postExecResult.status === "fail") {
|
|
248
|
+
postExecBlockingFailure = true;
|
|
249
|
+
const blockingCount = postExecResult.checks.filter(
|
|
250
|
+
(c) => !c.passed && c.blocking
|
|
251
|
+
).length;
|
|
252
|
+
ctx.ui.notify(
|
|
253
|
+
`Post-execution checks failed: ${blockingCount} blocking issue${blockingCount === 1 ? "" : "s"} found`,
|
|
254
|
+
"error"
|
|
255
|
+
);
|
|
256
|
+
} else if (postExecResult.status === "warn") {
|
|
257
|
+
ctx.ui.notify(
|
|
258
|
+
`Post-execution checks passed with warnings`,
|
|
259
|
+
"warning"
|
|
260
|
+
);
|
|
261
|
+
// Strict mode: treat warnings as blocking
|
|
262
|
+
if (prefs?.enhanced_verification_strict === true) {
|
|
263
|
+
postExecBlockingFailure = true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} catch (postExecErr) {
|
|
268
|
+
// Post-execution check errors are non-fatal — log and continue
|
|
269
|
+
logWarning("engine", `gsd-post-exec: error — ${(postExecErr as Error).message}`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Re-write verification evidence JSON with post-execution checks
|
|
275
|
+
if (postExecChecks && postExecChecks.length > 0 && mid && sid && tid) {
|
|
276
|
+
try {
|
|
277
|
+
const sDir = resolveSlicePath(s.basePath, mid, sid);
|
|
278
|
+
if (sDir) {
|
|
279
|
+
const tasksDir = join(sDir, "tasks");
|
|
280
|
+
// Add postExecutionChecks to the result for the JSON write
|
|
281
|
+
const resultWithPostExec = {
|
|
282
|
+
...result,
|
|
283
|
+
// Mark as failed if there was a blocking post-exec failure
|
|
284
|
+
passed: result.passed && !postExecBlockingFailure,
|
|
285
|
+
};
|
|
286
|
+
// Manually write with postExecutionChecks field
|
|
287
|
+
writeVerificationJSONWithPostExec(
|
|
288
|
+
resultWithPostExec,
|
|
289
|
+
tasksDir,
|
|
290
|
+
tid,
|
|
291
|
+
s.currentUnit.id,
|
|
292
|
+
postExecChecks,
|
|
293
|
+
postExecBlockingFailure ? attempt + 1 : undefined,
|
|
294
|
+
postExecBlockingFailure ? maxRetries : undefined
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
} catch (evidenceErr) {
|
|
298
|
+
logWarning("engine", `verification-evidence: post-exec write error — ${(evidenceErr as Error).message}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Update result.passed based on post-execution checks
|
|
303
|
+
if (postExecBlockingFailure) {
|
|
304
|
+
result.passed = false;
|
|
305
|
+
}
|
|
306
|
+
|
|
186
307
|
// ── Auto-fix retry logic ──
|
|
187
308
|
if (result.passed) {
|
|
188
309
|
s.verificationRetryCount.delete(s.currentUnit.id);
|
|
189
310
|
s.pendingVerificationRetry = null;
|
|
190
311
|
return "continue";
|
|
312
|
+
} else if (postExecBlockingFailure) {
|
|
313
|
+
// Post-execution failures are cross-task consistency issues — retrying the same task won't fix them.
|
|
314
|
+
// Skip retry and pause immediately for human review.
|
|
315
|
+
s.verificationRetryCount.delete(s.currentUnit.id);
|
|
316
|
+
s.pendingVerificationRetry = null;
|
|
317
|
+
ctx.ui.notify(
|
|
318
|
+
`Post-execution checks failed — cross-task consistency issue detected, pausing for human review`,
|
|
319
|
+
"error",
|
|
320
|
+
);
|
|
321
|
+
await pauseAuto(ctx, pi);
|
|
322
|
+
return "pause";
|
|
191
323
|
} else if (autoFixEnabled && attempt + 1 <= maxRetries) {
|
|
192
324
|
const nextAttempt = attempt + 1;
|
|
193
325
|
s.verificationRetryCount.set(s.currentUnit.id, nextAttempt);
|
|
@@ -231,3 +363,59 @@ export async function runPostUnitVerification(
|
|
|
231
363
|
return "continue";
|
|
232
364
|
}
|
|
233
365
|
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Write verification evidence JSON with post-execution checks included.
|
|
369
|
+
* This is a variant of writeVerificationJSON that adds the postExecutionChecks field.
|
|
370
|
+
*/
|
|
371
|
+
function writeVerificationJSONWithPostExec(
|
|
372
|
+
result: VerificationGateResult,
|
|
373
|
+
tasksDir: string,
|
|
374
|
+
taskId: string,
|
|
375
|
+
unitId: string,
|
|
376
|
+
postExecutionChecks: PostExecutionCheckJSON[],
|
|
377
|
+
retryAttempt?: number,
|
|
378
|
+
maxRetries?: number,
|
|
379
|
+
): void {
|
|
380
|
+
mkdirSync(tasksDir, { recursive: true });
|
|
381
|
+
|
|
382
|
+
const evidence: EvidenceJSON = {
|
|
383
|
+
schemaVersion: 1,
|
|
384
|
+
taskId,
|
|
385
|
+
unitId: unitId ?? taskId,
|
|
386
|
+
timestamp: result.timestamp,
|
|
387
|
+
passed: result.passed,
|
|
388
|
+
discoverySource: result.discoverySource,
|
|
389
|
+
checks: result.checks.map((check) => ({
|
|
390
|
+
command: check.command,
|
|
391
|
+
exitCode: check.exitCode,
|
|
392
|
+
durationMs: check.durationMs,
|
|
393
|
+
verdict: check.exitCode === 0 ? "pass" : "fail",
|
|
394
|
+
})),
|
|
395
|
+
...(retryAttempt !== undefined ? { retryAttempt } : {}),
|
|
396
|
+
...(maxRetries !== undefined ? { maxRetries } : {}),
|
|
397
|
+
postExecutionChecks,
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
if (result.runtimeErrors && result.runtimeErrors.length > 0) {
|
|
401
|
+
evidence.runtimeErrors = result.runtimeErrors.map(e => ({
|
|
402
|
+
source: e.source,
|
|
403
|
+
severity: e.severity,
|
|
404
|
+
message: e.message,
|
|
405
|
+
blocking: e.blocking,
|
|
406
|
+
}));
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (result.auditWarnings && result.auditWarnings.length > 0) {
|
|
410
|
+
evidence.auditWarnings = result.auditWarnings.map(w => ({
|
|
411
|
+
name: w.name,
|
|
412
|
+
severity: w.severity,
|
|
413
|
+
title: w.title,
|
|
414
|
+
url: w.url,
|
|
415
|
+
fixAvailable: w.fixAvailable,
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const filePath = join(tasksDir, `${taskId}-VERIFY.json`);
|
|
420
|
+
writeFileSync(filePath, JSON.stringify(evidence, null, 2) + "\n", "utf-8");
|
|
421
|
+
}
|
|
@@ -895,6 +895,7 @@ export async function pauseAuto(
|
|
|
895
895
|
sessionFile: s.pausedSessionFile,
|
|
896
896
|
activeEngineId: s.activeEngineId,
|
|
897
897
|
activeRunDir: s.activeRunDir,
|
|
898
|
+
autoStartTime: s.autoStartTime,
|
|
898
899
|
};
|
|
899
900
|
const runtimeDir = join(gsdRoot(s.originalBasePath || s.basePath), "runtime");
|
|
900
901
|
mkdirSync(runtimeDir, { recursive: true });
|
|
@@ -1137,6 +1138,7 @@ export async function startAuto(
|
|
|
1137
1138
|
s.activeRunDir = meta.activeRunDir ?? null;
|
|
1138
1139
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1139
1140
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1141
|
+
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1140
1142
|
s.paused = true;
|
|
1141
1143
|
try { unlinkSync(pausedPath); } catch (err) { /* non-fatal */
|
|
1142
1144
|
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
@@ -1162,6 +1164,7 @@ export async function startAuto(
|
|
|
1162
1164
|
s.currentMilestoneId = meta.milestoneId;
|
|
1163
1165
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1164
1166
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1167
|
+
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1165
1168
|
s.paused = true;
|
|
1166
1169
|
// Clean up the persisted file — we're consuming it
|
|
1167
1170
|
try { unlinkSync(pausedPath); } catch (err) { /* non-fatal */
|
|
@@ -1194,6 +1197,7 @@ export async function startAuto(
|
|
|
1194
1197
|
s.cmdCtx = ctx;
|
|
1195
1198
|
s.basePath = base;
|
|
1196
1199
|
setLogBasePath(base);
|
|
1200
|
+
if (!s.autoStartTime || s.autoStartTime <= 0) s.autoStartTime = Date.now();
|
|
1197
1201
|
s.unitDispatchCount.clear();
|
|
1198
1202
|
s.unitLifetimeDispatches.clear();
|
|
1199
1203
|
if (!getLedger()) initMetrics(base);
|
|
@@ -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({
|
|
@@ -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
|
+
}
|
|
@@ -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();
|
|
@@ -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,24 @@ 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
|
+
},
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
34
53
|
pi.registerShortcut(Key.ctrlAlt("p"), {
|
|
35
54
|
description: shortcutDesc("Open parallel worker monitor", "/gsd parallel watch"),
|
|
36
55
|
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" },
|
|
@@ -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",
|