gsd-pi 2.78.1-dev.84a383f51 → 2.78.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/cli.js +55 -95
- package/dist/headless-query.d.ts +0 -22
- package/dist/headless-query.js +4 -24
- package/dist/headless.d.ts +0 -10
- package/dist/headless.js +1 -16
- package/dist/loader.js +10 -7
- package/dist/onboarding.d.ts +0 -10
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +2 -5
- package/dist/resource-loader.d.ts +2 -5
- package/dist/resource-loader.js +5 -28
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
- package/dist/resources/extensions/gsd/auto/loop.js +0 -23
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +1 -3
- package/dist/resources/extensions/gsd/auto/session.js +0 -3
- package/dist/resources/extensions/gsd/auto-recovery.js +4 -43
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +0 -30
- package/dist/resources/extensions/gsd/auto.js +5 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -14
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +5 -7
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +4 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -94
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +6 -11
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +8 -34
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +2 -38
- package/dist/resources/extensions/gsd/commands/catalog.js +5 -69
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -22
- package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -3
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +1 -10
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +0 -4
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +1 -39
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +5 -12
- package/dist/resources/extensions/gsd/gsd-db.js +2 -11
- package/dist/resources/extensions/gsd/guided-flow.js +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +31 -66
- package/dist/resources/extensions/gsd/model-router.js +9 -114
- package/dist/resources/extensions/gsd/native-git-bridge.js +1 -7
- package/dist/resources/extensions/gsd/preferences-models.js +15 -91
- package/dist/resources/extensions/gsd/preferences-types.js +0 -2
- package/dist/resources/extensions/gsd/preferences-validation.js +0 -32
- package/dist/resources/extensions/gsd/preferences.js +3 -5
- package/dist/resources/extensions/gsd/prompt-loader.js +12 -23
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -9
- package/dist/resources/extensions/gsd/state.js +0 -42
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +53 -0
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +5 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -18
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +1 -3
- package/dist/resources/extensions/gsd/worktree-command.js +46 -26
- package/dist/resources/extensions/mcp-client/index.js +3 -6
- package/dist/resources/extensions/slash-commands/create-extension.js +22 -36
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -9
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
- package/dist/rtk-shared.d.ts +0 -3
- package/dist/rtk-shared.js +0 -17
- package/dist/rtk.d.ts +5 -2
- package/dist/rtk.js +20 -3
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +13 -13
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +4 -44
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -4
- 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 +13 -13
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +11 -0
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +20 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.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/package.json +1 -2
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +46 -74
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +0 -26
- package/packages/mcp-server/src/workflow-tools.ts +58 -93
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -48
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +0 -13
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +3 -24
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +0 -26
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +20 -52
- package/packages/pi-ai/src/types.ts +0 -13
- package/packages/pi-ai/src/utils/repair-tool-json.ts +3 -24
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +0 -32
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +0 -6
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +0 -4
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +2 -19
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +0 -10
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +0 -18
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +0 -13
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -20
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -14
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +0 -7
- package/packages/pi-coding-agent/src/core/messages.ts +0 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +2 -32
- package/packages/pi-coding-agent/src/core/model-registry.ts +0 -21
- package/packages/pi-coding-agent/src/core/system-prompt.ts +15 -33
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -17
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +3 -17
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +3 -20
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop.ts +2 -24
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +1 -3
- package/src/resources/extensions/gsd/auto/session.ts +0 -3
- package/src/resources/extensions/gsd/auto/types.ts +0 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +8 -46
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +4 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +0 -38
- package/src/resources/extensions/gsd/auto.ts +4 -14
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +13 -15
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -8
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +9 -10
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -102
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +6 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -39
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +11 -39
- package/src/resources/extensions/gsd/commands/catalog.ts +5 -75
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -22
- package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -3
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1 -15
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +0 -4
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +1 -39
- package/src/resources/extensions/gsd/doctor-types.ts +1 -3
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +5 -13
- package/src/resources/extensions/gsd/gsd-db.ts +2 -12
- package/src/resources/extensions/gsd/guided-flow.ts +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +28 -81
- package/src/resources/extensions/gsd/model-router.ts +9 -172
- package/src/resources/extensions/gsd/native-git-bridge.ts +1 -7
- package/src/resources/extensions/gsd/preferences-models.ts +15 -101
- package/src/resources/extensions/gsd/preferences-types.ts +0 -6
- package/src/resources/extensions/gsd/preferences-validation.ts +0 -35
- package/src/resources/extensions/gsd/preferences.ts +2 -16
- package/src/resources/extensions/gsd/prompt-loader.ts +12 -26
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +3 -9
- package/src/resources/extensions/gsd/state.ts +0 -42
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +0 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +1 -178
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +0 -58
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +5 -9
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -21
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +211 -138
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +59 -142
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +4 -7
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +32 -89
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +23 -41
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +43 -3
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +3 -5
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +87 -22
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +118 -7
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +60 -18
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +76 -14
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +83 -22
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +63 -1
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +1 -26
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +0 -30
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +4 -14
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +12 -22
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +1 -64
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +0 -128
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +1 -33
- package/src/resources/extensions/gsd/tests/model-router.test.ts +8 -169
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +0 -8
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +43 -32
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -127
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +0 -16
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +0 -7
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +19 -168
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +1 -7
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +1 -23
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +4 -51
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +16 -7
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +1 -15
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +0 -15
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -17
- package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +1 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +0 -1
- package/src/resources/extensions/gsd/worktree-command.ts +44 -31
- package/src/resources/extensions/mcp-client/index.ts +3 -6
- package/src/resources/extensions/slash-commands/create-extension.ts +24 -38
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -9
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +12 -32
- package/dist/cli-policy.d.ts +0 -13
- package/dist/cli-policy.js +0 -17
- package/dist/resources/.managed-resources-content-hash +0 -1
- package/dist/resources/extensions/gsd/auto-runtime-state.js +0 -31
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +0 -36
- package/dist/resources/extensions/gsd/worktree-session-state.js +0 -33
- package/dist/runtime-checks.d.ts +0 -27
- package/dist/runtime-checks.js +0 -38
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +0 -1
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +0 -1
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +0 -1
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +0 -1
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +0 -1
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +0 -2
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +0 -20
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +0 -1
- package/dist/worktree-status-banner.d.ts +0 -1
- package/dist/worktree-status-banner.js +0 -132
- package/packages/mcp-server/dist/alias-telemetry.d.ts +0 -8
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +0 -1
- package/packages/mcp-server/dist/alias-telemetry.js +0 -30
- package/packages/mcp-server/dist/alias-telemetry.js.map +0 -1
- package/packages/mcp-server/src/alias-telemetry.test.ts +0 -78
- package/packages/mcp-server/src/alias-telemetry.ts +0 -30
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +0 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +0 -231
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +0 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +0 -289
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +0 -37
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +0 -49
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +0 -133
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +0 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +0 -78
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +0 -1
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +0 -181
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +0 -1
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +0 -77
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +0 -212
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +0 -102
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +0 -200
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +0 -2
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +0 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +0 -161
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +0 -1
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +0 -219
- package/src/resources/extensions/gsd/auto-runtime-state.ts +0 -51
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +0 -47
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +0 -116
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +0 -100
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +0 -93
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +0 -63
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +0 -81
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +0 -57
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +0 -145
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +0 -124
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +0 -152
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +0 -50
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +0 -93
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +0 -101
- package/src/resources/extensions/gsd/worktree-session-state.ts +0 -35
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +0 -91
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +0 -58
- /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{UF5VF4F1tB0miEtJS7LyX → 7afp7gq8-DVbxum83zRQ-}/_ssgManifest.js +0 -0
|
@@ -16,9 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
import { describe, test, afterEach } from "node:test";
|
|
18
18
|
import assert from "node:assert/strict";
|
|
19
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, readFileSync } from "node:fs";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { dirname } from "node:path";
|
|
22
24
|
|
|
23
25
|
import { deriveState } from "../state.ts";
|
|
24
26
|
import { invalidateAllCaches } from "../cache.ts";
|
|
@@ -55,6 +57,12 @@ function writeRoadmap(base: string, mid: string, content: string): void {
|
|
|
55
57
|
writeFileSync(join(base, ".gsd", "milestones", mid, `${mid}-ROADMAP.md`), content);
|
|
56
58
|
}
|
|
57
59
|
|
|
60
|
+
function readGuidedFlowSource(): string {
|
|
61
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
62
|
+
const thisDir = dirname(thisFile);
|
|
63
|
+
return readFileSync(join(thisDir, "..", "guided-flow.ts"), "utf-8");
|
|
64
|
+
}
|
|
65
|
+
|
|
58
66
|
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
59
67
|
|
|
60
68
|
describe("discuss-queued-milestones (#2307)", () => {
|
|
@@ -161,10 +169,113 @@ describe("discuss-queued-milestones (#2307)", () => {
|
|
|
161
169
|
}
|
|
162
170
|
});
|
|
163
171
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
test("6. guided-flow no longer hard-exits when no active milestone but pending exist", () => {
|
|
173
|
+
const source = readGuidedFlowSource();
|
|
174
|
+
|
|
175
|
+
// The old guard was a simple early-exit:
|
|
176
|
+
// if (!state.activeMilestone) {
|
|
177
|
+
// ctx.ui.notify("No active milestone. Run /gsd to create one first.", "warning");
|
|
178
|
+
// return;
|
|
179
|
+
// }
|
|
180
|
+
//
|
|
181
|
+
// The new guard should check for pending milestones and route instead.
|
|
182
|
+
const oldGuardPattern = /if\s*\(!state\.activeMilestone\)\s*\{\s*ctx\.ui\.notify\("No active milestone/;
|
|
183
|
+
assert.ok(
|
|
184
|
+
!oldGuardPattern.test(source),
|
|
185
|
+
"guided-flow must not unconditionally exit when activeMilestone is null",
|
|
186
|
+
);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("7. showDiscussQueuedMilestone helper exists in guided-flow", () => {
|
|
190
|
+
const source = readGuidedFlowSource();
|
|
191
|
+
assert.ok(
|
|
192
|
+
source.includes("showDiscussQueuedMilestone"),
|
|
193
|
+
"guided-flow must export showDiscussQueuedMilestone helper",
|
|
194
|
+
);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("8. dispatchDiscussForMilestone helper exists in guided-flow", () => {
|
|
198
|
+
const source = readGuidedFlowSource();
|
|
199
|
+
assert.ok(
|
|
200
|
+
source.includes("dispatchDiscussForMilestone"),
|
|
201
|
+
"guided-flow must export dispatchDiscussForMilestone helper",
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("9. dispatchDiscussForMilestone does not set pendingAutoStart", () => {
|
|
206
|
+
const source = readGuidedFlowSource();
|
|
207
|
+
|
|
208
|
+
// Extract the dispatchDiscussForMilestone function body
|
|
209
|
+
const fnMatch = source.match(
|
|
210
|
+
/async function dispatchDiscussForMilestone\s*\([^)]*\)[^{]*\{([\s\S]*?)\n\}/,
|
|
211
|
+
);
|
|
212
|
+
assert.ok(!!fnMatch, "dispatchDiscussForMilestone function body must be present");
|
|
213
|
+
|
|
214
|
+
if (fnMatch) {
|
|
215
|
+
assert.ok(
|
|
216
|
+
!fnMatch[1].includes("pendingAutoStart"),
|
|
217
|
+
"dispatchDiscussForMilestone must NOT set pendingAutoStart — discussing a queued milestone must not activate it",
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test("10. slice picker includes queued milestone option when pending milestones exist", () => {
|
|
223
|
+
const source = readGuidedFlowSource();
|
|
224
|
+
assert.ok(
|
|
225
|
+
source.includes("discuss_queued_milestone"),
|
|
226
|
+
"slice picker must include a 'discuss_queued_milestone' action id for queued milestones",
|
|
227
|
+
);
|
|
228
|
+
assert.ok(
|
|
229
|
+
source.includes("Discuss a queued milestone"),
|
|
230
|
+
"slice picker must label the queued milestone action clearly",
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("11. queued milestone picker labels entries with [queued]", () => {
|
|
235
|
+
const source = readGuidedFlowSource();
|
|
236
|
+
assert.ok(
|
|
237
|
+
source.includes("[queued]"),
|
|
238
|
+
"queued milestone picker must label entries with [queued] to distinguish from active",
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// ─── #3150: allDiscussed early-return must not block queued milestone discussion ──
|
|
243
|
+
|
|
244
|
+
test("12. allDiscussed path checks for pending milestones before returning (#3150)", () => {
|
|
245
|
+
const source = readGuidedFlowSource();
|
|
246
|
+
|
|
247
|
+
// Extract the allDiscussed block — the if (allDiscussed) { ... } body
|
|
248
|
+
const allDiscussedMatch = source.match(
|
|
249
|
+
/const allDiscussed = pendingSlices\.every\([\s\S]*?\n if \(allDiscussed\) \{([\s\S]*?)\n \}/,
|
|
250
|
+
);
|
|
251
|
+
assert.ok(!!allDiscussedMatch, "allDiscussed guard block must exist in showDiscuss()");
|
|
252
|
+
|
|
253
|
+
if (allDiscussedMatch) {
|
|
254
|
+
const body = allDiscussedMatch[1];
|
|
255
|
+
// The fix must check for pending milestones and route to showDiscussQueuedMilestone
|
|
256
|
+
assert.ok(
|
|
257
|
+
body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
|
|
258
|
+
"allDiscussed block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("13. pendingSlices.length===0 path checks for pending milestones before returning (#3150)", () => {
|
|
264
|
+
const source = readGuidedFlowSource();
|
|
265
|
+
|
|
266
|
+
// Find the pendingSlices.length === 0 guard block
|
|
267
|
+
const zeroSlicesMatch = source.match(
|
|
268
|
+
/if \(pendingSlices\.length === 0\) \{([\s\S]*?)\n \}/,
|
|
269
|
+
);
|
|
270
|
+
assert.ok(!!zeroSlicesMatch, "pendingSlices.length === 0 guard block must exist in showDiscuss()");
|
|
271
|
+
|
|
272
|
+
if (zeroSlicesMatch) {
|
|
273
|
+
const body = zeroSlicesMatch[1];
|
|
274
|
+
// The fix must check for pending milestones and route to showDiscussQueuedMilestone
|
|
275
|
+
assert.ok(
|
|
276
|
+
body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
|
|
277
|
+
"pendingSlices.length===0 block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
170
281
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression test for discuss-slice structured questions availability
|
|
3
|
+
*
|
|
4
|
+
* The guided-discuss-slice.md template must use the structuredQuestionsAvailable
|
|
5
|
+
* template variable to conditionally switch between ask_user_questions tool
|
|
6
|
+
* calls and plain-text questions, so the prompt works correctly when the
|
|
7
|
+
* structured questions tool is not available.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it } from 'node:test'
|
|
11
|
+
import assert from 'node:assert/strict'
|
|
12
|
+
import { readFileSync } from 'node:fs'
|
|
13
|
+
import { resolve } from 'node:path'
|
|
14
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
15
|
+
|
|
16
|
+
const template = readFileSync(
|
|
17
|
+
resolve(process.cwd(), 'src', 'resources', 'extensions', 'gsd', 'prompts', 'guided-discuss-slice.md'),
|
|
18
|
+
'utf-8',
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
describe('discuss-slice structuredQuestionsAvailable template variable', () => {
|
|
22
|
+
it('template references structuredQuestionsAvailable variable', () => {
|
|
23
|
+
assert.ok(
|
|
24
|
+
template.includes('{{structuredQuestionsAvailable}}'),
|
|
25
|
+
'guided-discuss-slice.md must use {{structuredQuestionsAvailable}} template variable',
|
|
26
|
+
)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('template handles both true and false cases', () => {
|
|
30
|
+
const trueCase = template.includes('`{{structuredQuestionsAvailable}}` is `true`')
|
|
31
|
+
const falseCase = template.includes('`{{structuredQuestionsAvailable}}` is `false`')
|
|
32
|
+
|
|
33
|
+
assert.ok(trueCase, 'template must have a branch for structuredQuestionsAvailable=true')
|
|
34
|
+
assert.ok(falseCase, 'template must have a branch for structuredQuestionsAvailable=false')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('false case instructs plain text questions', () => {
|
|
38
|
+
const falseIdx = template.indexOf('`{{structuredQuestionsAvailable}}` is `false`')
|
|
39
|
+
assert.ok(falseIdx !== -1)
|
|
40
|
+
|
|
41
|
+
const afterFalse = extractSourceRegion(template, '`{{structuredQuestionsAvailable}}` is `false`')
|
|
42
|
+
assert.ok(
|
|
43
|
+
afterFalse.includes('plain text'),
|
|
44
|
+
'when structuredQuestionsAvailable is false, questions should be in plain text',
|
|
45
|
+
)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -1,35 +1,77 @@
|
|
|
1
|
-
// GSD-2 —
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
// GSD-2 — Regression test for #3616: discuss tool scoping must not leak into subsequent sessions
|
|
2
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bug #3616: After a discuss session narrows the active tool set via
|
|
6
|
+
* setActiveTools(), the narrowed list persisted into the next auto-mode
|
|
7
|
+
* session because newSession() did not restore extension tools when cwd
|
|
8
|
+
* was unchanged. This caused gsd_plan_slice and other DB tools to be
|
|
9
|
+
* missing from plan-slice subagent sessions.
|
|
10
|
+
*
|
|
11
|
+
* This test verifies the structural properties that prevent the leak:
|
|
12
|
+
* 1. guided-flow.ts narrows tools ONLY for discuss-* unit types
|
|
13
|
+
* 2. The narrowed set explicitly excludes gsd_plan_slice (a HEAVY_TOOL)
|
|
14
|
+
* 3. agent-session.ts:newSession() has an else-branch that restores
|
|
15
|
+
* all extension tools even when cwd hasn't changed
|
|
16
|
+
*/
|
|
15
17
|
|
|
16
18
|
import { describe, test } from "node:test";
|
|
17
19
|
import assert from "node:assert/strict";
|
|
20
|
+
import { readFileSync } from "node:fs";
|
|
21
|
+
import { join, dirname } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
18
23
|
|
|
19
24
|
import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
|
|
25
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
26
|
+
|
|
27
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const guidedFlowSource = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
20
29
|
|
|
21
30
|
describe("#3616 — discuss tool scoping must not leak across sessions", () => {
|
|
22
31
|
test("gsd_plan_slice is NOT in DISCUSS_TOOLS_ALLOWLIST", () => {
|
|
23
32
|
assert.ok(
|
|
24
33
|
!DISCUSS_TOOLS_ALLOWLIST.includes("gsd_plan_slice"),
|
|
25
|
-
|
|
34
|
+
"gsd_plan_slice should be excluded from discuss scope (it's a heavy planning tool)",
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("tool scoping only activates for discuss-* unit types", () => {
|
|
39
|
+
// The guard must be: if (unitType?.startsWith("discuss-"))
|
|
40
|
+
assert.ok(
|
|
41
|
+
guidedFlowSource.includes('unitType?.startsWith("discuss-")'),
|
|
42
|
+
"tool scoping should only trigger for discuss-* unit types",
|
|
26
43
|
);
|
|
27
44
|
});
|
|
28
45
|
|
|
29
|
-
test("
|
|
46
|
+
test("discuss tool scoping uses setActiveTools (not setTools) for reversibility", () => {
|
|
47
|
+
// setActiveTools changes the active subset but doesn't remove tools from
|
|
48
|
+
// the registry. newSession()'s _refreshToolRegistry can restore them.
|
|
49
|
+
assert.ok(
|
|
50
|
+
guidedFlowSource.includes("pi.setActiveTools(scopedTools)"),
|
|
51
|
+
"should use pi.setActiveTools to narrow tools (preserving registry)",
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("newSession() in agent-session.ts has defense against tool narrowing persistence", () => {
|
|
56
|
+
const agentSessionSource = readFileSync(
|
|
57
|
+
join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
|
|
58
|
+
"utf-8",
|
|
59
|
+
);
|
|
60
|
+
const newSessionStart = agentSessionSource.indexOf("async newSession(options?:");
|
|
61
|
+
assert.ok(newSessionStart >= 0, "should find newSession");
|
|
62
|
+
const body = extractSourceRegion(agentSessionSource, "async newSession(options?:");
|
|
63
|
+
|
|
64
|
+
// Both branches (cwd-changed and cwd-unchanged) must include extension tools
|
|
65
|
+
assert.ok(
|
|
66
|
+
body.includes("includeAllExtensionTools: true"),
|
|
67
|
+
"newSession() must include all extension tools in both branches",
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Count occurrences — should be at least 2 (one per branch)
|
|
71
|
+
const matches = body.match(/includeAllExtensionTools:\s*true/g);
|
|
30
72
|
assert.ok(
|
|
31
|
-
|
|
32
|
-
|
|
73
|
+
matches && matches.length >= 2,
|
|
74
|
+
`expected >=2 includeAllExtensionTools:true in newSession(), got ${matches?.length ?? 0}`,
|
|
33
75
|
);
|
|
34
76
|
});
|
|
35
77
|
});
|
|
@@ -1,20 +1,82 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Behavioural regression test for #2645 — double mergeAndExit guard.
|
|
3
|
-
*
|
|
4
|
-
* AutoSession.milestoneMergedInPhases is the producer-side flag set by the
|
|
5
|
-
* "complete" / "all-milestones-complete" branches in phases.ts after they
|
|
6
|
-
* call mergeAndExit. stopAuto reads it to skip the redundant Step-4 merge
|
|
7
|
-
* (which previously failed because the branch was already deleted).
|
|
8
|
-
*
|
|
9
|
-
* Refs #4829 (rewrite from positional source-grep on phases.ts/auto.ts).
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
1
|
import { describe, test } from "node:test";
|
|
13
2
|
import assert from "node:assert/strict";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { join, dirname } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
14
6
|
import { AutoSession } from "../auto/session.ts";
|
|
7
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
8
|
+
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
|
|
11
|
+
describe("double mergeAndExit guard (#2645)", () => {
|
|
12
|
+
test("phases.ts sets milestoneMergedInPhases after mergeAndExit in milestone-complete path", () => {
|
|
13
|
+
// Source audit: the "complete" phase path must set the guard flag
|
|
14
|
+
// after calling mergeAndExit so that stopAuto skips the second merge.
|
|
15
|
+
const phasesSrc = readFileSync(
|
|
16
|
+
join(__dirname, "..", "auto", "phases.ts"),
|
|
17
|
+
"utf-8",
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// Find the "complete" phase block
|
|
21
|
+
const completeIdx = phasesSrc.indexOf('state.phase === "complete"');
|
|
22
|
+
assert.ok(completeIdx > 0, "phases.ts should have a 'complete' phase check");
|
|
23
|
+
|
|
24
|
+
const afterComplete = extractSourceRegion(phasesSrc, 'state.phase === "complete"');
|
|
25
|
+
const mergeIdx = afterComplete.indexOf("deps.resolver.mergeAndExit");
|
|
26
|
+
const flagIdx = afterComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
27
|
+
|
|
28
|
+
assert.ok(mergeIdx > 0, "complete path should call mergeAndExit");
|
|
29
|
+
assert.ok(flagIdx > 0, "complete path should set milestoneMergedInPhases");
|
|
30
|
+
assert.ok(
|
|
31
|
+
flagIdx > mergeIdx,
|
|
32
|
+
"milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("phases.ts sets milestoneMergedInPhases after mergeAndExit in all-milestones-complete path", () => {
|
|
37
|
+
const phasesSrc = readFileSync(
|
|
38
|
+
join(__dirname, "..", "auto", "phases.ts"),
|
|
39
|
+
"utf-8",
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// The "all milestones complete" block checks incomplete.length === 0
|
|
43
|
+
const allCompleteIdx = phasesSrc.indexOf("incomplete.length === 0");
|
|
44
|
+
assert.ok(allCompleteIdx > 0, "phases.ts should have an all-milestones-complete check");
|
|
45
|
+
|
|
46
|
+
const afterAllComplete = extractSourceRegion(phasesSrc, "incomplete.length === 0");
|
|
47
|
+
const mergeIdx = afterAllComplete.indexOf("deps.resolver.mergeAndExit");
|
|
48
|
+
const flagIdx = afterAllComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
49
|
+
|
|
50
|
+
assert.ok(mergeIdx > 0, "all-complete path should call mergeAndExit");
|
|
51
|
+
assert.ok(flagIdx > 0, "all-complete path should set milestoneMergedInPhases");
|
|
52
|
+
assert.ok(
|
|
53
|
+
flagIdx > mergeIdx,
|
|
54
|
+
"milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("stopAuto checks milestoneMergedInPhases before calling mergeAndExit", () => {
|
|
59
|
+
const autoSrc = readFileSync(
|
|
60
|
+
join(__dirname, "..", "auto.ts"),
|
|
61
|
+
"utf-8",
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// The Step 4 worktree exit block must check the guard flag
|
|
65
|
+
const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
|
|
66
|
+
assert.ok(step4Idx > 0, "auto.ts should have Step 4 worktree exit");
|
|
67
|
+
|
|
68
|
+
const step4Block = extractSourceRegion(autoSrc, "Step 4: Auto-worktree exit");
|
|
69
|
+
assert.ok(
|
|
70
|
+
step4Block.includes("milestoneMergedInPhases"),
|
|
71
|
+
"stopAuto Step 4 must check milestoneMergedInPhases before merging",
|
|
72
|
+
);
|
|
73
|
+
assert.ok(
|
|
74
|
+
step4Block.includes("!s.milestoneMergedInPhases"),
|
|
75
|
+
"stopAuto should skip merge when milestoneMergedInPhases is true",
|
|
76
|
+
);
|
|
77
|
+
});
|
|
15
78
|
|
|
16
|
-
|
|
17
|
-
test("defaults to false on a fresh session", () => {
|
|
79
|
+
test("AutoSession.milestoneMergedInPhases defaults to false", () => {
|
|
18
80
|
const session = new AutoSession();
|
|
19
81
|
assert.equal(
|
|
20
82
|
session.milestoneMergedInPhases,
|
|
@@ -23,7 +85,7 @@ describe("AutoSession.milestoneMergedInPhases (#2645)", () => {
|
|
|
23
85
|
);
|
|
24
86
|
});
|
|
25
87
|
|
|
26
|
-
test("reset() clears
|
|
88
|
+
test("AutoSession.reset() clears milestoneMergedInPhases", () => {
|
|
27
89
|
const session = new AutoSession();
|
|
28
90
|
session.milestoneMergedInPhases = true;
|
|
29
91
|
session.reset();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* empty-content-abort-loop.test.ts — Regression test for #2695.
|
|
3
|
+
*
|
|
4
|
+
* When the LLM sends an assistant message with empty `content: []` and
|
|
5
|
+
* `stopReason: "aborted"`, this is NOT a fatal abort — it is a non-fatal
|
|
6
|
+
* end-of-turn. The abort handler in agent-end-recovery.ts must distinguish
|
|
7
|
+
* this case and NOT pause auto-mode, allowing the loop to continue via
|
|
8
|
+
* resolveAgentEnd instead of entering a stuck re-dispatch loop.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import test from "node:test";
|
|
12
|
+
import assert from "node:assert/strict";
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
14
|
+
import { join, dirname } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
import { extractSourceRegion } from "./test-helpers.ts";
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const RECOVERY_PATH = join(__dirname, "..", "bootstrap", "agent-end-recovery.ts");
|
|
20
|
+
|
|
21
|
+
function getRecoverySource(): string {
|
|
22
|
+
return readFileSync(RECOVERY_PATH, "utf-8");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test("agent-end-recovery.ts does not pause on aborted messages with empty content (#2695)", () => {
|
|
26
|
+
const source = getRecoverySource();
|
|
27
|
+
|
|
28
|
+
// The abort handler at `stopReason === "aborted"` must check for empty content
|
|
29
|
+
// before deciding to pause. An empty content array is a non-fatal agent stop.
|
|
30
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
31
|
+
assert.ok(abortIdx > -1, "abort handler must exist in agent-end-recovery.ts");
|
|
32
|
+
|
|
33
|
+
// Extract the region around the abort handler (enough to see the guard logic)
|
|
34
|
+
const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"', { fromIdx: abortIdx });
|
|
35
|
+
|
|
36
|
+
// Must check for empty content before pausing
|
|
37
|
+
assert.ok(
|
|
38
|
+
abortRegion.includes("content") && (abortRegion.includes("length") || abortRegion.includes("?.length")),
|
|
39
|
+
"abort handler must inspect content array length to distinguish empty-content aborts from fatal aborts (#2695)",
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("agent-end-recovery.ts routes empty-content aborted messages to resolveAgentEnd (#2695)", () => {
|
|
44
|
+
const source = getRecoverySource();
|
|
45
|
+
|
|
46
|
+
// The abort block must have a path that calls resolveAgentEnd for empty-content messages
|
|
47
|
+
// instead of unconditionally calling pauseAuto
|
|
48
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
49
|
+
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
50
|
+
|
|
51
|
+
// Get the full abort handling block (from the if to the next stopReason check or success path)
|
|
52
|
+
const afterAbort = extractSourceRegion(source, 'stopReason === "aborted"');
|
|
53
|
+
|
|
54
|
+
// The abort block must have a code path that calls resolveAgentEnd (for empty-content case)
|
|
55
|
+
assert.ok(
|
|
56
|
+
afterAbort.includes("resolveAgentEnd"),
|
|
57
|
+
"abort handler must route empty-content aborted messages to resolveAgentEnd instead of always pausing (#2695)",
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("agent-end-recovery.ts checks for errorMessage presence in abort handler (#2695)", () => {
|
|
62
|
+
const source = getRecoverySource();
|
|
63
|
+
|
|
64
|
+
const abortIdx = source.indexOf('stopReason === "aborted"');
|
|
65
|
+
assert.ok(abortIdx > -1, "abort handler must exist");
|
|
66
|
+
|
|
67
|
+
const abortRegion = extractSourceRegion(source, 'stopReason === "aborted"');
|
|
68
|
+
|
|
69
|
+
// Fatal aborts should have error context (errorMessage field).
|
|
70
|
+
// The handler should check for this to distinguish fatal from non-fatal aborts.
|
|
71
|
+
assert.ok(
|
|
72
|
+
abortRegion.includes("errorMessage"),
|
|
73
|
+
"abort handler must check for errorMessage to distinguish fatal aborts from empty-content non-fatal stops (#2695)",
|
|
74
|
+
);
|
|
75
|
+
});
|
|
@@ -1,43 +1,104 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* false-degraded-mode-warning.test.ts — Regression tests for #3922.
|
|
3
3
|
*
|
|
4
|
-
* Before this fix, deriveState() logged "DB unavailable — degraded mode"
|
|
5
|
-
* even when the DB
|
|
6
|
-
* before_agent_start context injection). The fix
|
|
7
|
-
*
|
|
4
|
+
* Before this fix, deriveState() logged a "DB unavailable — degraded mode"
|
|
5
|
+
* warning even when the DB simply hadn't been opened yet (e.g. during
|
|
6
|
+
* before_agent_start context injection). The fix introduces wasDbOpenAttempted()
|
|
7
|
+
* to distinguish "not yet initialized" from "genuinely unavailable."
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Two aspects:
|
|
10
|
+
* 1. gsd-db: wasDbOpenAttempted() tracks whether openDatabase() was ever called.
|
|
11
|
+
* 2. state: the degraded-mode warning is gated behind wasDbOpenAttempted().
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { describe, test
|
|
14
|
+
import { describe, test } from "node:test";
|
|
15
15
|
import assert from "node:assert/strict";
|
|
16
|
+
import { readFileSync } from "node:fs";
|
|
17
|
+
import { dirname, join } from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
16
19
|
import {
|
|
17
20
|
openDatabase,
|
|
18
21
|
closeDatabase,
|
|
22
|
+
isDbAvailable,
|
|
19
23
|
wasDbOpenAttempted,
|
|
20
24
|
} from "../gsd-db.ts";
|
|
21
25
|
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const stateSource = readFileSync(join(__dirname, "..", "state.ts"), "utf-8");
|
|
28
|
+
|
|
29
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
+
// 1. gsd-db: wasDbOpenAttempted flag
|
|
31
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
32
|
+
|
|
22
33
|
describe("wasDbOpenAttempted (#3922)", () => {
|
|
23
|
-
beforeEach(() => { closeDatabase(); });
|
|
24
|
-
afterEach(() => { closeDatabase(); });
|
|
25
34
|
|
|
26
|
-
test("returns true after
|
|
35
|
+
test("wasDbOpenAttempted returns true after openDatabase is called", () => {
|
|
36
|
+
// By this point in the test suite, openDatabase may or may not have been
|
|
37
|
+
// called by other tests. So we call it explicitly and verify it returns true.
|
|
27
38
|
openDatabase(":memory:");
|
|
28
|
-
assert.strictEqual(
|
|
29
|
-
wasDbOpenAttempted
|
|
30
|
-
|
|
31
|
-
"wasDbOpenAttempted should report true after openDatabase succeeds",
|
|
32
|
-
);
|
|
39
|
+
assert.strictEqual(wasDbOpenAttempted(), true,
|
|
40
|
+
"wasDbOpenAttempted should be true after openDatabase call");
|
|
41
|
+
closeDatabase();
|
|
33
42
|
});
|
|
34
43
|
|
|
35
|
-
test("
|
|
44
|
+
test("openDatabase sets the flag even if it fails on invalid path", () => {
|
|
45
|
+
// openDatabase with an unreachable path may fail, but the flag should
|
|
46
|
+
// still be set because the attempt was made.
|
|
36
47
|
try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
|
|
37
|
-
assert.strictEqual(
|
|
38
|
-
wasDbOpenAttempted
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
assert.strictEqual(wasDbOpenAttempted(), true,
|
|
49
|
+
"wasDbOpenAttempted should be true even after a failed open attempt");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
54
|
+
// 2. state.ts: degraded-mode warning is gated behind wasDbOpenAttempted
|
|
55
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
56
|
+
|
|
57
|
+
describe("degraded-mode warning guard (#3922)", () => {
|
|
58
|
+
|
|
59
|
+
test("state.ts imports wasDbOpenAttempted from gsd-db", () => {
|
|
60
|
+
assert.ok(
|
|
61
|
+
stateSource.includes("wasDbOpenAttempted"),
|
|
62
|
+
"state.ts must import wasDbOpenAttempted to gate the degraded-mode warning",
|
|
41
63
|
);
|
|
42
64
|
});
|
|
65
|
+
|
|
66
|
+
test("degraded-mode warning is inside a wasDbOpenAttempted() guard", () => {
|
|
67
|
+
// Find the degraded-mode warning string
|
|
68
|
+
const warningStr = 'DB unavailable — using filesystem state derivation (degraded mode)';
|
|
69
|
+
const warningIdx = stateSource.indexOf(warningStr);
|
|
70
|
+
assert.ok(warningIdx > 0, "degraded-mode warning string must exist in state.ts");
|
|
71
|
+
|
|
72
|
+
// The wasDbOpenAttempted() check must appear BEFORE the warning,
|
|
73
|
+
// within the same else-branch (i.e. within a reasonable distance).
|
|
74
|
+
// Look backwards from the warning for the guard.
|
|
75
|
+
const searchWindow = stateSource.slice(Math.max(0, warningIdx - 300), warningIdx);
|
|
76
|
+
assert.ok(
|
|
77
|
+
searchWindow.includes("wasDbOpenAttempted()"),
|
|
78
|
+
"wasDbOpenAttempted() guard must appear shortly before the degraded-mode warning " +
|
|
79
|
+
"to prevent false warnings when DB has not been initialized yet",
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("warning is NOT emitted unconditionally in the else branch", () => {
|
|
84
|
+
// The old code had `logWarning(...)` directly in the else branch.
|
|
85
|
+
// The fix wraps it in `if (wasDbOpenAttempted())`.
|
|
86
|
+
// Verify the logWarning call is inside a conditional, not bare.
|
|
87
|
+
const lines = stateSource.split("\n");
|
|
88
|
+
for (let i = 0; i < lines.length; i++) {
|
|
89
|
+
if (lines[i]!.includes("DB unavailable") && lines[i]!.includes("degraded mode")) {
|
|
90
|
+
// This line has the warning. Check that the preceding non-empty line
|
|
91
|
+
// contains an if-condition (wasDbOpenAttempted), not a bare else.
|
|
92
|
+
let prev = i - 1;
|
|
93
|
+
while (prev >= 0 && lines[prev]!.trim() === "") prev--;
|
|
94
|
+
const prevLine = lines[prev]!.trim();
|
|
95
|
+
assert.ok(
|
|
96
|
+
prevLine.includes("wasDbOpenAttempted"),
|
|
97
|
+
`Line ${i + 1} emits degraded-mode warning — preceding line ${prev + 1} must ` +
|
|
98
|
+
`contain wasDbOpenAttempted guard, but found: "${prevLine}"`,
|
|
99
|
+
);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
43
104
|
});
|