gsd-pi 2.64.0 → 2.65.0-dev.5c8557b
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 +16 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +20 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/notifications-handler.js +104 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +256 -0
- package/dist/resources/extensions/gsd/notification-store.js +273 -0
- package/dist/resources/extensions/gsd/notification-widget.js +56 -0
- package/dist/resources/extensions/gsd/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 +16 -15
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/routes-manifest.json +6 -0
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +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 +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/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 +2 -2
- 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 +2 -2
- 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 +4 -4
- 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 +16 -15
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_global-error/page-8805a20e15762c3c.js +1 -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/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/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.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/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/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-8805a20e15762c3c.js +1 -0
- package/dist/web/standalone/.next/static/qq3YfHPfyqvh3DIMVmsRH/_buildManifest.js +1 -0
- 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/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/__tests__/overlay-layout.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +66 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
- package/packages/pi-tui/dist/components/loader.d.ts +4 -2
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/loader.js +27 -9
- package/packages/pi-tui/dist/components/loader.js.map +1 -1
- package/packages/pi-tui/dist/components/text.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/text.js +2 -0
- package/packages/pi-tui/dist/components/text.js.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -1
- package/packages/pi-tui/dist/overlay-layout.js +12 -1
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +4 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +35 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +82 -0
- package/packages/pi-tui/src/components/loader.ts +27 -10
- package/packages/pi-tui/src/components/text.ts +1 -0
- package/packages/pi-tui/src/overlay-layout.ts +13 -1
- package/packages/pi-tui/src/tui.ts +34 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +19 -7
- package/src/resources/extensions/bg-shell/process-manager.ts +8 -2
- package/src/resources/extensions/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 +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +28 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +140 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +295 -0
- package/src/resources/extensions/gsd/notification-store.ts +293 -0
- package/src/resources/extensions/gsd/notification-widget.ts +68 -0
- package/src/resources/extensions/gsd/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-overlay.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +282 -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/app/page-62be3b5fa91e4c8f.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/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/global-error-ab5a8926e07ec673.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/eebXKteM9EaWyseHKTjqp/_buildManifest.js +0 -1
- /package/dist/web/standalone/.next/static/{eebXKteM9EaWyseHKTjqp → qq3YfHPfyqvh3DIMVmsRH}/_ssgManifest.js +0 -0
|
@@ -2,13 +2,16 @@ import type { TUI } from "../tui.js";
|
|
|
2
2
|
import { Text } from "./text.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Loader component that updates every 80ms with spinning animation
|
|
5
|
+
* Loader component that updates every 80ms with spinning animation.
|
|
6
|
+
* Frame rotation is isolated from message text to avoid invalidating
|
|
7
|
+
* Text's render cache (wrapTextWithAnsi, visibleWidth) on every tick.
|
|
6
8
|
*/
|
|
7
9
|
export class Loader extends Text {
|
|
8
10
|
private frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
9
11
|
private currentFrame = 0;
|
|
10
12
|
private intervalId: NodeJS.Timeout | null = null;
|
|
11
13
|
private ui: TUI | null = null;
|
|
14
|
+
private _lastMessage: string = "";
|
|
12
15
|
|
|
13
16
|
constructor(
|
|
14
17
|
ui: TUI,
|
|
@@ -22,18 +25,38 @@ export class Loader extends Text {
|
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
render(width: number): string[] {
|
|
25
|
-
|
|
28
|
+
// Only update Text content when message actually changes —
|
|
29
|
+
// frame rotation is prepended below without touching the cache
|
|
30
|
+
if (this.message !== this._lastMessage) {
|
|
31
|
+
this.setText(this.messageColorFn(this.message));
|
|
32
|
+
this._lastMessage = this.message;
|
|
33
|
+
}
|
|
34
|
+
const messageLines = super.render(width);
|
|
35
|
+
// Shallow copy so we don't mutate cachedLines from Text
|
|
36
|
+
const result = ["", ...messageLines];
|
|
37
|
+
// Prepend spinner frame to first content line
|
|
38
|
+
if (result.length > 1) {
|
|
39
|
+
const frame = this.frames[this.currentFrame];
|
|
40
|
+
result[1] = this.spinnerColorFn(frame) + " " + result[1];
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
26
43
|
}
|
|
27
44
|
|
|
28
45
|
start() {
|
|
29
46
|
if (this.intervalId) {
|
|
30
47
|
clearInterval(this.intervalId);
|
|
31
48
|
}
|
|
32
|
-
this.
|
|
49
|
+
this.currentFrame = 0;
|
|
33
50
|
this.intervalId = setInterval(() => {
|
|
34
51
|
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
35
|
-
this.
|
|
52
|
+
if (this.ui) {
|
|
53
|
+
this.ui.requestRender();
|
|
54
|
+
}
|
|
36
55
|
}, 80);
|
|
56
|
+
// Trigger initial render
|
|
57
|
+
if (this.ui) {
|
|
58
|
+
this.ui.requestRender();
|
|
59
|
+
}
|
|
37
60
|
}
|
|
38
61
|
|
|
39
62
|
stop() {
|
|
@@ -50,12 +73,6 @@ export class Loader extends Text {
|
|
|
50
73
|
|
|
51
74
|
setMessage(message: string) {
|
|
52
75
|
this.message = message;
|
|
53
|
-
this.updateDisplay();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private updateDisplay() {
|
|
57
|
-
const frame = this.frames[this.currentFrame];
|
|
58
|
-
this.setText(`${this.spinnerColorFn(frame)} ${this.messageColorFn(this.message)}`);
|
|
59
76
|
if (this.ui) {
|
|
60
77
|
this.ui.requestRender();
|
|
61
78
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { OverlayAnchor, OverlayOptions, SizeValue } from "./tui.js";
|
|
9
|
-
import { extractSegments, sliceByColumn, sliceWithWidth, truncateToWidth, visibleWidth } from "./utils.js";
|
|
9
|
+
import { applyBackgroundToLine, extractSegments, sliceByColumn, sliceWithWidth, truncateToWidth, visibleWidth } from "./utils.js";
|
|
10
10
|
import { isImageLine } from "./terminal-image.js";
|
|
11
11
|
import { CURSOR_MARKER } from "./tui.js";
|
|
12
12
|
|
|
@@ -324,6 +324,18 @@ export function compositeOverlays(
|
|
|
324
324
|
|
|
325
325
|
const viewportStart = Math.max(0, workingHeight - termHeight);
|
|
326
326
|
|
|
327
|
+
// Apply backdrop dimming if any visible overlay requests it.
|
|
328
|
+
// Uses dim + gray foreground so text fades without painting empty lines.
|
|
329
|
+
const hasBackdrop = visibleEntries.some((e) => e.options?.backdrop);
|
|
330
|
+
if (hasBackdrop) {
|
|
331
|
+
const dimFn = (text: string) => `\x1b[2m\x1b[38;5;240m${text}\x1b[39m\x1b[22m`;
|
|
332
|
+
for (let i = viewportStart; i < result.length; i++) {
|
|
333
|
+
if (!isImageLine(result[i]) && result[i].length > 0) {
|
|
334
|
+
result[i] = applyBackgroundToLine(result[i], termWidth, dimFn);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
327
339
|
// Composite each overlay
|
|
328
340
|
for (const { overlayLines, row, col, w } of rendered) {
|
|
329
341
|
for (let i = 0; i < overlayLines.length; i++) {
|
|
@@ -141,6 +141,8 @@ export interface OverlayOptions {
|
|
|
141
141
|
visible?: (termWidth: number, termHeight: number) => boolean;
|
|
142
142
|
/** If true, don't capture keyboard focus when shown */
|
|
143
143
|
nonCapturing?: boolean;
|
|
144
|
+
/** If true, dim the background behind the overlay */
|
|
145
|
+
backdrop?: boolean;
|
|
144
146
|
}
|
|
145
147
|
|
|
146
148
|
/**
|
|
@@ -166,20 +168,33 @@ export interface OverlayHandle {
|
|
|
166
168
|
*/
|
|
167
169
|
export class Container implements Component {
|
|
168
170
|
children: Component[] = [];
|
|
171
|
+
private _prevRender: string[] | null = null;
|
|
169
172
|
|
|
170
173
|
addChild(component: Component): void {
|
|
171
174
|
this.children.push(component);
|
|
175
|
+
this._prevRender = null;
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
removeChild(component: Component): void {
|
|
175
179
|
const index = this.children.indexOf(component);
|
|
176
180
|
if (index !== -1) {
|
|
181
|
+
const child = this.children[index];
|
|
177
182
|
this.children.splice(index, 1);
|
|
183
|
+
if ('dispose' in child && typeof (child as any).dispose === 'function') {
|
|
184
|
+
(child as any).dispose();
|
|
185
|
+
}
|
|
186
|
+
this._prevRender = null;
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
189
|
|
|
181
190
|
clear(): void {
|
|
191
|
+
for (const child of this.children) {
|
|
192
|
+
if ('dispose' in child && typeof (child as any).dispose === 'function') {
|
|
193
|
+
(child as any).dispose();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
182
196
|
this.children = [];
|
|
197
|
+
this._prevRender = null;
|
|
183
198
|
}
|
|
184
199
|
|
|
185
200
|
invalidate(): void {
|
|
@@ -194,6 +209,17 @@ export class Container implements Component {
|
|
|
194
209
|
const rendered = child.render(width);
|
|
195
210
|
for (let i = 0; i < rendered.length; i++) lines.push(rendered[i]);
|
|
196
211
|
}
|
|
212
|
+
// Return stable reference if output unchanged — allows doRender()
|
|
213
|
+
// to skip ALL post-processing (isImageLine, applyLineResets, diffs)
|
|
214
|
+
const prev = this._prevRender;
|
|
215
|
+
if (prev && prev.length === lines.length) {
|
|
216
|
+
let same = true;
|
|
217
|
+
for (let i = 0; i < lines.length; i++) {
|
|
218
|
+
if (lines[i] !== prev[i]) { same = false; break; }
|
|
219
|
+
}
|
|
220
|
+
if (same) return prev;
|
|
221
|
+
}
|
|
222
|
+
this._prevRender = lines;
|
|
197
223
|
return lines;
|
|
198
224
|
}
|
|
199
225
|
}
|
|
@@ -222,6 +248,7 @@ export class TUI extends Container {
|
|
|
222
248
|
private previousViewportTop = 0; // Track previous viewport top for resize-aware cursor moves
|
|
223
249
|
private fullRedrawCount = 0;
|
|
224
250
|
private stopped = false;
|
|
251
|
+
private _lastRenderedComponents: string[] | null = null;
|
|
225
252
|
|
|
226
253
|
// Overlay stack for modal components rendered on top of base content
|
|
227
254
|
private focusOrderCounter = 0;
|
|
@@ -599,6 +626,13 @@ export class TUI extends Container {
|
|
|
599
626
|
// Render all components to get new lines
|
|
600
627
|
let newLines = this.render(width);
|
|
601
628
|
|
|
629
|
+
// Skip ALL post-processing if component output is unchanged.
|
|
630
|
+
// Container.render() returns the same array reference when stable.
|
|
631
|
+
if (newLines === this._lastRenderedComponents && this.overlayStack.length === 0) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
this._lastRenderedComponents = newLines;
|
|
635
|
+
|
|
602
636
|
// Composite overlays into the rendered lines (before differential compare)
|
|
603
637
|
if (this.overlayStack.length > 0) {
|
|
604
638
|
newLines = compositeOverlays(newLines, this.overlayStack, width, height, this.maxLinesRendered);
|
package/pkg/package.json
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
processes,
|
|
18
18
|
pendingAlerts,
|
|
19
|
+
pushAlert,
|
|
19
20
|
cleanupAll,
|
|
20
21
|
cleanupSessionProcesses,
|
|
21
22
|
persistManifest,
|
|
@@ -37,19 +38,30 @@ export function registerBgShellLifecycle(pi: ExtensionAPI, state: BgShellSharedS
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
// Clean up on session shutdown
|
|
41
|
-
pi.on("session_shutdown", async () => {
|
|
42
|
-
cleanupAll();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
41
|
// Register signal handlers to clean up bg processes on unexpected exit (fixes #428)
|
|
46
42
|
const signalCleanup = () => {
|
|
47
43
|
cleanupAll();
|
|
44
|
+
// Also kill bash-tool spawned children that bg-shell doesn't track
|
|
45
|
+
try {
|
|
46
|
+
const { listDescendants } = require("@gsd/native") as typeof import("@gsd/native");
|
|
47
|
+
const descendants = listDescendants(process.pid);
|
|
48
|
+
for (const childPid of descendants) {
|
|
49
|
+
try { process.kill(childPid, "SIGKILL"); } catch {}
|
|
50
|
+
}
|
|
51
|
+
} catch {}
|
|
48
52
|
};
|
|
49
53
|
process.on("SIGTERM", signalCleanup);
|
|
50
54
|
process.on("SIGINT", signalCleanup);
|
|
51
55
|
process.on("beforeExit", signalCleanup);
|
|
52
56
|
|
|
57
|
+
// Clean up on session shutdown — remove signal handlers to prevent accumulation
|
|
58
|
+
pi.on("session_shutdown", async () => {
|
|
59
|
+
process.off("SIGTERM", signalCleanup);
|
|
60
|
+
process.off("SIGINT", signalCleanup);
|
|
61
|
+
process.off("beforeExit", signalCleanup);
|
|
62
|
+
cleanupAll();
|
|
63
|
+
});
|
|
64
|
+
|
|
53
65
|
// ── Compaction Awareness: Survive Context Resets ───────────────
|
|
54
66
|
|
|
55
67
|
/** Build a compact state summary of all alive processes for context re-injection */
|
|
@@ -65,7 +77,7 @@ export function registerBgShellLifecycle(pi: ExtensionAPI, state: BgShellSharedS
|
|
|
65
77
|
return ` - id:${p.id} "${p.label}" [${p.processType}] status:${p.status} uptime:${formatUptime(Date.now() - p.startedAt)}${portInfo}${urlInfo}${errInfo}${groupInfo}`;
|
|
66
78
|
}).join("\n");
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
pushAlert(null,
|
|
69
81
|
`${reason} ${alive.length} background process(es) are still running:\n${processSummaries}\nUse bg_shell digest/output/kill with these IDs.`
|
|
70
82
|
);
|
|
71
83
|
}
|
|
@@ -150,7 +162,7 @@ export function registerBgShellLifecycle(pi: ExtensionAPI, state: BgShellSharedS
|
|
|
150
162
|
` - ${s.id}: ${s.label} (pid ${s.pid}, type: ${s.processType}${s.group ? `, group: ${s.group}` : ""})`
|
|
151
163
|
).join("\n");
|
|
152
164
|
|
|
153
|
-
|
|
165
|
+
pushAlert(null,
|
|
154
166
|
`${surviving.length} background process(es) from previous session still running:\n${summary}\n Note: These processes are outside bg_shell's control. Kill them manually if needed.`
|
|
155
167
|
);
|
|
156
168
|
}
|
|
@@ -33,6 +33,8 @@ export const processes = new Map<string, BgProcess>();
|
|
|
33
33
|
/** Pending alerts to inject into the next agent context */
|
|
34
34
|
export let pendingAlerts: string[] = [];
|
|
35
35
|
|
|
36
|
+
const MAX_PENDING_ALERTS = 50;
|
|
37
|
+
|
|
36
38
|
/** Replace the pendingAlerts array (used by the extension entry point) */
|
|
37
39
|
export function setPendingAlerts(alerts: string[]): void {
|
|
38
40
|
pendingAlerts = alerts;
|
|
@@ -58,8 +60,12 @@ export function addEvent(bg: BgProcess, event: Omit<ProcessEvent, "timestamp">):
|
|
|
58
60
|
}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
export function pushAlert(bg: BgProcess, message: string): void {
|
|
62
|
-
|
|
63
|
+
export function pushAlert(bg: BgProcess | null, message: string): void {
|
|
64
|
+
const prefix = bg ? `[bg:${bg.id} ${bg.label}] ` : "";
|
|
65
|
+
pendingAlerts.push(`${prefix}${message}`);
|
|
66
|
+
if (pendingAlerts.length > MAX_PENDING_ALERTS) {
|
|
67
|
+
pendingAlerts.splice(0, pendingAlerts.length - MAX_PENDING_ALERTS);
|
|
68
|
+
}
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
export function getInfo(p: BgProcess): BgProcessInfo {
|
|
@@ -585,10 +585,11 @@ export function updateProgressWidget(
|
|
|
585
585
|
lines.push(rightAlign(headerLeft, headerRight, width));
|
|
586
586
|
|
|
587
587
|
// Worktree/branch right-aligned below header
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
588
|
+
const branchLabel = worktreeName && cachedBranch
|
|
589
|
+
? `${worktreeName} (${cachedBranch})`
|
|
590
|
+
: cachedBranch ?? "";
|
|
591
|
+
if (branchLabel) {
|
|
592
|
+
lines.push(rightAlign("", theme.fg("dim", branchLabel), width));
|
|
592
593
|
}
|
|
593
594
|
|
|
594
595
|
// Show health signal details when degraded (yellow/red)
|
|
@@ -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
|
+
}
|