gsd-pi 2.78.0 → 2.78.1-dev.9d08d820b
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 +59 -23
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +104 -33
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +43 -8
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +9 -13
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +30 -13
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +128 -32
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +5 -13
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +5 -6
- package/dist/resources/extensions/gsd/auto-dashboard.js +3 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +63 -2
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- 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 +60 -13
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +22 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-config.js +3 -2
- package/dist/resources/extensions/gsd/commands-extensions.js +46 -3
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +10 -8
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +25 -24
- package/dist/resources/extensions/gsd/home-dir.js +16 -0
- package/dist/resources/extensions/gsd/key-manager.js +2 -1
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/migrate/command.js +3 -2
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/unit-context-manifest.js +29 -4
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-manager.js +20 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +4 -13
- package/dist/resources/extensions/gsd/worktree-root.js +124 -0
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/gsd/worktree.js +4 -115
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/ollama/index.js +15 -2
- package/dist/resources/extensions/ollama/model-capabilities.js +31 -0
- package/dist/resources/extensions/ollama/ollama-client.js +40 -4
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/extensions/subagent/index.js +324 -178
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- 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 +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- 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 +11 -11
- 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 +44 -4
- 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 +4 -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 +11 -11
- 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/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.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/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-9bf2e0c50fb2ca05.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.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 +2 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/worktree-cli.d.ts +1 -0
- package/dist/worktree-cli.js +9 -3
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -3
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +78 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- 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 +24 -3
- 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 +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- 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 +6 -0
- 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 +4 -0
- 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 +19 -2
- 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 +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- 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 +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +130 -30
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +6 -14
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +5 -6
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +3 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +60 -2
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +82 -12
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +108 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +20 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-config.ts +3 -2
- package/src/resources/extensions/gsd/commands-extensions.ts +43 -3
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +10 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +12 -7
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +27 -26
- package/src/resources/extensions/gsd/home-dir.ts +19 -0
- package/src/resources/extensions/gsd/journal.ts +4 -1
- package/src/resources/extensions/gsd/key-manager.ts +2 -1
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/migrate/command.ts +3 -2
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +10 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +10 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +10 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +24 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- 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 +138 -211
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/home-dir.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +72 -1
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +18 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +17 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +38 -3
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +34 -33
- package/src/resources/extensions/gsd/tests/worktree.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +131 -1
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +44 -12
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-manager.ts +40 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +4 -14
- package/src/resources/extensions/gsd/worktree-root.ts +144 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/gsd/worktree.ts +8 -119
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/ollama/index.ts +16 -2
- package/src/resources/extensions/ollama/model-capabilities.ts +34 -0
- package/src/resources/extensions/ollama/ollama-client.ts +41 -4
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +96 -0
- package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/extensions/subagent/index.ts +165 -7
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- 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/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- 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 +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{C1zT2kEfoLhDdbWPWKrXd → -Ukk6_YxRd4GY4iUOnRUE}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// GSD Extension — Regression test for #4996: ensurePreconditions phantom dir guard
|
|
2
|
+
// Verifies that ensurePreconditions does not create milestone directories for
|
|
3
|
+
// forward-referenced slice unit IDs when the milestone has no DB row.
|
|
4
|
+
|
|
5
|
+
import { describe, it, afterEach } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
|
|
11
|
+
import { ensurePreconditions } from "../auto.ts";
|
|
12
|
+
import {
|
|
13
|
+
openDatabase,
|
|
14
|
+
closeDatabase,
|
|
15
|
+
insertMilestone,
|
|
16
|
+
} from "../gsd-db.ts";
|
|
17
|
+
|
|
18
|
+
import type { GSDState } from "../types.ts";
|
|
19
|
+
|
|
20
|
+
function makeBase(prefix = "gsd-precond-"): string {
|
|
21
|
+
const base = mkdtempSync(join(tmpdir(), prefix));
|
|
22
|
+
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
23
|
+
return base;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function makeMinimalState(): GSDState {
|
|
27
|
+
return {
|
|
28
|
+
activeMilestone: null,
|
|
29
|
+
activeSlice: null,
|
|
30
|
+
activeTask: null,
|
|
31
|
+
phase: "planning",
|
|
32
|
+
recentDecisions: [],
|
|
33
|
+
blockers: [],
|
|
34
|
+
nextAction: "",
|
|
35
|
+
registry: [],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("ensurePreconditions phantom-dir guard (#4996)", () => {
|
|
40
|
+
let base: string;
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
try { closeDatabase(); } catch { /* ignore */ }
|
|
44
|
+
try { rmSync(base, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("(a) slice unit ID for unknown milestone does NOT create dirs when no DB row exists", () => {
|
|
48
|
+
base = makeBase();
|
|
49
|
+
const state = makeMinimalState();
|
|
50
|
+
|
|
51
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
52
|
+
|
|
53
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
54
|
+
assert.ok(!existsSync(milestoneDir), "M003 dir must not be created for phantom slice dispatch");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("(b) slice unit ID for milestone with DB row DOES create dirs", () => {
|
|
58
|
+
base = makeBase();
|
|
59
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
60
|
+
openDatabase(dbPath);
|
|
61
|
+
insertMilestone({ id: "M003", status: "active" });
|
|
62
|
+
const state = makeMinimalState();
|
|
63
|
+
|
|
64
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
65
|
+
|
|
66
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
67
|
+
assert.ok(existsSync(milestoneDir), "M003 dir must be created when DB row exists");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("(c) slice unit ID for existing milestone dir with CONTEXT.md content file uses normal scaffolding", () => {
|
|
71
|
+
base = makeBase();
|
|
72
|
+
const mid = "M003";
|
|
73
|
+
const milestoneDir = join(base, ".gsd", "milestones", mid);
|
|
74
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
75
|
+
writeFileSync(join(milestoneDir, `${mid}-CONTEXT.md`), "# Context\n");
|
|
76
|
+
const state = makeMinimalState();
|
|
77
|
+
|
|
78
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
79
|
+
|
|
80
|
+
const slicesDir = join(milestoneDir, "slices");
|
|
81
|
+
assert.ok(existsSync(slicesDir), "existing milestone dir should allow slice scaffolding");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("(d) milestone-only unit ID (no slice) still creates dir even with no DB row", () => {
|
|
85
|
+
base = makeBase();
|
|
86
|
+
const state = makeMinimalState();
|
|
87
|
+
|
|
88
|
+
ensurePreconditions("discuss-milestone", "M003", base, state);
|
|
89
|
+
|
|
90
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
91
|
+
assert.ok(existsSync(milestoneDir), "M003 dir must be created for milestone-only dispatch");
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -1,104 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Behavioural regression tests for #3922.
|
|
3
3
|
*
|
|
4
|
-
* Before this fix, deriveState() logged
|
|
5
|
-
*
|
|
6
|
-
* before_agent_start context injection). The fix
|
|
7
|
-
*
|
|
4
|
+
* Before this fix, deriveState() logged "DB unavailable — degraded mode"
|
|
5
|
+
* even when the DB had not been opened yet (e.g. during
|
|
6
|
+
* before_agent_start context injection). The fix introduced
|
|
7
|
+
* wasDbOpenAttempted() so the warning fires only after a real open attempt.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The earlier tests source-grepped state.ts for the warning string and the
|
|
10
|
+
* preceding line (POSITIONAL/SOURCE_GREP per #4826/#4829). They are
|
|
11
|
+
* replaced here with direct calls to the wasDbOpenAttempted flag.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { describe, test } from "node:test";
|
|
14
|
+
import { describe, test, beforeEach, afterEach } 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";
|
|
19
16
|
import {
|
|
20
17
|
openDatabase,
|
|
21
18
|
closeDatabase,
|
|
22
|
-
isDbAvailable,
|
|
23
19
|
wasDbOpenAttempted,
|
|
24
20
|
} from "../gsd-db.ts";
|
|
25
21
|
|
|
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
|
-
|
|
33
22
|
describe("wasDbOpenAttempted (#3922)", () => {
|
|
23
|
+
beforeEach(() => { closeDatabase(); });
|
|
24
|
+
afterEach(() => { closeDatabase(); });
|
|
34
25
|
|
|
35
|
-
test("
|
|
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.
|
|
26
|
+
test("returns true after a successful openDatabase call", () => {
|
|
38
27
|
openDatabase(":memory:");
|
|
39
|
-
assert.strictEqual(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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.
|
|
47
|
-
try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
|
|
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",
|
|
28
|
+
assert.strictEqual(
|
|
29
|
+
wasDbOpenAttempted(),
|
|
30
|
+
true,
|
|
31
|
+
"wasDbOpenAttempted should report true after openDatabase succeeds",
|
|
63
32
|
);
|
|
64
33
|
});
|
|
65
34
|
|
|
66
|
-
test("
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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",
|
|
35
|
+
test("remains true after a failed open attempt — the attempt is what matters", () => {
|
|
36
|
+
try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
|
|
37
|
+
assert.strictEqual(
|
|
38
|
+
wasDbOpenAttempted(),
|
|
39
|
+
true,
|
|
40
|
+
"wasDbOpenAttempted should be true even when openDatabase throws — the warning gate keys on the attempt, not the outcome",
|
|
80
41
|
);
|
|
81
42
|
});
|
|
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
|
-
});
|
|
104
43
|
});
|
|
@@ -17,12 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { createTestContext } from "./test-helpers.ts";
|
|
20
|
-
import {
|
|
21
|
-
withTimeout,
|
|
22
|
-
FINALIZE_PRE_TIMEOUT_MS,
|
|
23
|
-
FINALIZE_POST_TIMEOUT_MS,
|
|
24
|
-
} from "../auto/finalize-timeout.ts";
|
|
25
|
-
import { MAX_FINALIZE_TIMEOUTS } from "../auto/types.ts";
|
|
20
|
+
import { withTimeout } from "../auto/finalize-timeout.ts";
|
|
26
21
|
|
|
27
22
|
const { assertTrue, assertEq, report } = createTestContext();
|
|
28
23
|
|
|
@@ -80,44 +75,6 @@ const { assertTrue, assertEq, report } = createTestContext();
|
|
|
80
75
|
assertTrue(caught, "rejection should propagate");
|
|
81
76
|
}
|
|
82
77
|
|
|
83
|
-
// ═══ Test: FINALIZE_PRE_TIMEOUT_MS is defined and reasonable ═════════════════
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
console.log("\n=== #3757: pre-verification timeout constant is defined and reasonable ===");
|
|
87
|
-
|
|
88
|
-
assertTrue(
|
|
89
|
-
typeof FINALIZE_PRE_TIMEOUT_MS === "number",
|
|
90
|
-
"FINALIZE_PRE_TIMEOUT_MS should be a number",
|
|
91
|
-
);
|
|
92
|
-
assertTrue(
|
|
93
|
-
FINALIZE_PRE_TIMEOUT_MS >= 30_000,
|
|
94
|
-
`pre timeout should be >= 30s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
|
|
95
|
-
);
|
|
96
|
-
assertTrue(
|
|
97
|
-
FINALIZE_PRE_TIMEOUT_MS <= 120_000,
|
|
98
|
-
`pre timeout should be <= 120s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ═══ Test: FINALIZE_POST_TIMEOUT_MS is defined and reasonable ═════════════════
|
|
103
|
-
|
|
104
|
-
{
|
|
105
|
-
console.log("\n=== #2344: timeout constant is defined and reasonable ===");
|
|
106
|
-
|
|
107
|
-
assertTrue(
|
|
108
|
-
typeof FINALIZE_POST_TIMEOUT_MS === "number",
|
|
109
|
-
"FINALIZE_POST_TIMEOUT_MS should be a number",
|
|
110
|
-
);
|
|
111
|
-
assertTrue(
|
|
112
|
-
FINALIZE_POST_TIMEOUT_MS >= 30_000,
|
|
113
|
-
`timeout should be >= 30s (got ${FINALIZE_POST_TIMEOUT_MS}ms)`,
|
|
114
|
-
);
|
|
115
|
-
assertTrue(
|
|
116
|
-
FINALIZE_POST_TIMEOUT_MS <= 120_000,
|
|
117
|
-
`timeout should be <= 120s (got ${FINALIZE_POST_TIMEOUT_MS}ms)`,
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
78
|
// ═══ Test: withTimeout cleans up timer on success ════════════════════════════
|
|
122
79
|
|
|
123
80
|
{
|
|
@@ -134,25 +91,6 @@ const { assertTrue, assertEq, report } = createTestContext();
|
|
|
134
91
|
assertEq(result.timedOut, false, "should not time out");
|
|
135
92
|
}
|
|
136
93
|
|
|
137
|
-
// ═══ Test: MAX_FINALIZE_TIMEOUTS is defined and reasonable ═══════════════════
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
console.log("\n=== #3757: MAX_FINALIZE_TIMEOUTS is defined and reasonable ===");
|
|
141
|
-
|
|
142
|
-
assertTrue(
|
|
143
|
-
typeof MAX_FINALIZE_TIMEOUTS === "number",
|
|
144
|
-
"MAX_FINALIZE_TIMEOUTS should be a number",
|
|
145
|
-
);
|
|
146
|
-
assertTrue(
|
|
147
|
-
MAX_FINALIZE_TIMEOUTS >= 2,
|
|
148
|
-
`threshold should be >= 2 (got ${MAX_FINALIZE_TIMEOUTS})`,
|
|
149
|
-
);
|
|
150
|
-
assertTrue(
|
|
151
|
-
MAX_FINALIZE_TIMEOUTS <= 10,
|
|
152
|
-
`threshold should be <= 10 (got ${MAX_FINALIZE_TIMEOUTS})`,
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
94
|
// Note: the two previous source-grep blocks that scanned phases.ts for
|
|
157
95
|
// `withTimeout(` / `failClosedOnFinalizeTimeout(` occurrences were removed
|
|
158
96
|
// under #4825 — they encoded implementation shape (Goodhart) and broke on
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — closed-status omission for missing-summary detection
|
|
3
|
+
* (#4902).
|
|
4
|
+
*
|
|
5
|
+
* `findMissingSummaries` (auto-dispatch.ts) filters out slices in any closed
|
|
6
|
+
* status before checking for an on-disk SUMMARY. The deleted source-grep
|
|
7
|
+
* test asserted the literal `CLOSED_STATUSES` Set; this rewrite tests the
|
|
8
|
+
* exported predicate (`isClosedStatus`) that the inline Set replicates,
|
|
9
|
+
* so any drift between the predicate and the inline filter surfaces as a
|
|
10
|
+
* test failure here rather than a runtime miss.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
|
|
16
|
+
import { isClosedStatus, isInactiveStatus } from '../status-guards.ts';
|
|
17
|
+
|
|
18
|
+
describe('isClosedStatus — closed-status omission contract (#4902)', () => {
|
|
19
|
+
test('returns true for every status findMissingSummaries skips', () => {
|
|
20
|
+
// Mirror the inline Set in auto-dispatch.ts:findMissingSummaries.
|
|
21
|
+
for (const s of ['complete', 'done', 'skipped']) {
|
|
22
|
+
assert.equal(
|
|
23
|
+
isClosedStatus(s),
|
|
24
|
+
true,
|
|
25
|
+
`${s} must count as a closed status (would-have-summary omission)`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('returns false for live in-flight statuses', () => {
|
|
31
|
+
for (const s of ['pending', 'active', 'in-progress', 'planning', 'executing']) {
|
|
32
|
+
assert.equal(
|
|
33
|
+
isClosedStatus(s),
|
|
34
|
+
false,
|
|
35
|
+
`${s} is in-flight and MUST be checked for a missing SUMMARY`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('isInactiveStatus also covers deferred so it is not summary-checked', () => {
|
|
41
|
+
// Deferred slices likewise never produce a SUMMARY; the active-slice
|
|
42
|
+
// selector uses isInactiveStatus to skip them. Pin the contract.
|
|
43
|
+
assert.equal(isInactiveStatus('deferred'), true);
|
|
44
|
+
assert.equal(isInactiveStatus('complete'), true);
|
|
45
|
+
assert.equal(isInactiveStatus('pending'), false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
import test from "node:test";
|
|
10
10
|
import assert from "node:assert/strict";
|
|
11
11
|
import type { UnitMetrics } from "../metrics.js";
|
|
12
|
-
import {
|
|
12
|
+
import type { WorktreeTelemetrySummary } from "../worktree-telemetry.js";
|
|
13
|
+
import { detectStuckLoops, detectWorktreeOrphans, type ForensicAnomaly } from "../forensics.js";
|
|
13
14
|
|
|
14
15
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
15
16
|
|
|
@@ -163,3 +164,27 @@ test("#3760 detectStuckLoops still flags repeated dispatches within one auto ses
|
|
|
163
164
|
`details should explain the session-aware rule: ${anomalies[0].details}`,
|
|
164
165
|
);
|
|
165
166
|
});
|
|
167
|
+
|
|
168
|
+
test("#4711 detectWorktreeOrphans suggests doctor fix for completed unmerged branches", () => {
|
|
169
|
+
const anomalies: ForensicAnomaly[] = [];
|
|
170
|
+
const summary: WorktreeTelemetrySummary = {
|
|
171
|
+
worktreesCreated: 0,
|
|
172
|
+
worktreesMerged: 0,
|
|
173
|
+
orphansDetected: 1,
|
|
174
|
+
orphansByReason: { "complete-unmerged": 1 },
|
|
175
|
+
mergeDurationsMs: [],
|
|
176
|
+
mergeConflicts: 0,
|
|
177
|
+
exitsByReason: {},
|
|
178
|
+
exitsWithUnmergedWork: 0,
|
|
179
|
+
canonicalRedirects: 0,
|
|
180
|
+
slicesMerged: 0,
|
|
181
|
+
sliceMergeConflicts: 0,
|
|
182
|
+
milestoneResquashes: 0,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
detectWorktreeOrphans(summary, anomalies);
|
|
186
|
+
|
|
187
|
+
assert.equal(anomalies.length, 1);
|
|
188
|
+
assert.match(anomalies[0]!.details, /\/gsd doctor fix/);
|
|
189
|
+
assert.doesNotMatch(anomalies[0]!.details, /\/gsd health --fix/);
|
|
190
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — `.bg-shell/` baseline pattern (#4902, prior #2655).
|
|
3
|
+
*
|
|
4
|
+
* The deleted `gitignore-bg-shell.test.ts` asserted `.bg-shell/` appeared in
|
|
5
|
+
* the BASELINE_PATTERNS array via source grep. This rewrite drives
|
|
6
|
+
* `ensureGitignore()` against a tmp directory and asserts the written
|
|
7
|
+
* `.gitignore` actually contains the `.bg-shell/` pattern — i.e. tests the
|
|
8
|
+
* behaviour the constant exists to guarantee, not the spelling of the
|
|
9
|
+
* constant.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, test } from 'node:test';
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as os from 'node:os';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
|
|
18
|
+
import { ensureGitignore } from '../gitignore.ts';
|
|
19
|
+
|
|
20
|
+
function makeTmpRepo(): string {
|
|
21
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-gitignore-bg-'));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function cleanup(dir: string): void {
|
|
25
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* swallow */ }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('ensureGitignore writes .bg-shell/ baseline (#4902)', () => {
|
|
29
|
+
test('appends .bg-shell/ to a fresh project .gitignore', () => {
|
|
30
|
+
const dir = makeTmpRepo();
|
|
31
|
+
try {
|
|
32
|
+
const wrote = ensureGitignore(dir);
|
|
33
|
+
assert.equal(wrote, true, 'ensureGitignore should report it wrote');
|
|
34
|
+
|
|
35
|
+
const ignore = fs.readFileSync(path.join(dir, '.gitignore'), 'utf-8');
|
|
36
|
+
const lines = new Set(
|
|
37
|
+
ignore.split('\n').map((l) => l.trim()).filter(Boolean),
|
|
38
|
+
);
|
|
39
|
+
assert.ok(
|
|
40
|
+
lines.has('.bg-shell/'),
|
|
41
|
+
`.gitignore should include .bg-shell/. Got:\n${ignore}`,
|
|
42
|
+
);
|
|
43
|
+
} finally {
|
|
44
|
+
cleanup(dir);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('preserves .bg-shell/ when it is already present (idempotent)', () => {
|
|
49
|
+
const dir = makeTmpRepo();
|
|
50
|
+
try {
|
|
51
|
+
fs.writeFileSync(
|
|
52
|
+
path.join(dir, '.gitignore'),
|
|
53
|
+
'.bg-shell/\nnode_modules/\n',
|
|
54
|
+
);
|
|
55
|
+
ensureGitignore(dir); // run once to fill missing baseline
|
|
56
|
+
const ignore = fs.readFileSync(path.join(dir, '.gitignore'), 'utf-8');
|
|
57
|
+
const occurrences = ignore.split('\n').filter((l) => l.trim() === '.bg-shell/').length;
|
|
58
|
+
assert.equal(occurrences, 1, 'should not duplicate an existing .bg-shell/ entry');
|
|
59
|
+
} finally {
|
|
60
|
+
cleanup(dir);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
getActiveDecisions,
|
|
19
19
|
getActiveRequirements,
|
|
20
20
|
transaction,
|
|
21
|
+
readTransaction,
|
|
22
|
+
isInTransaction,
|
|
21
23
|
_getAdapter,
|
|
22
24
|
_resetProvider,
|
|
23
25
|
insertMilestone,
|
|
@@ -383,6 +385,34 @@ describe('gsd-db', () => {
|
|
|
383
385
|
closeDatabase();
|
|
384
386
|
});
|
|
385
387
|
|
|
388
|
+
test('gsd-db: failed BEGIN does not poison transaction depth', () => {
|
|
389
|
+
openDatabase(':memory:');
|
|
390
|
+
const adapter = _getAdapter()!;
|
|
391
|
+
|
|
392
|
+
const assertFailedBeginLeavesDepthClear = (label: string, fn: () => void) => {
|
|
393
|
+
adapter.exec('BEGIN');
|
|
394
|
+
try {
|
|
395
|
+
let threw = false;
|
|
396
|
+
try {
|
|
397
|
+
fn();
|
|
398
|
+
} catch {
|
|
399
|
+
threw = true;
|
|
400
|
+
}
|
|
401
|
+
assert.equal(threw, true, `${label} should surface the SQLite BEGIN failure`);
|
|
402
|
+
assert.equal(isInTransaction(), false, `${label} failed BEGIN must not leave depth active`);
|
|
403
|
+
} finally {
|
|
404
|
+
adapter.exec('ROLLBACK');
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
assertFailedBeginLeavesDepthClear('transaction', () => transaction(() => undefined));
|
|
410
|
+
assertFailedBeginLeavesDepthClear('readTransaction', () => readTransaction(() => undefined));
|
|
411
|
+
} finally {
|
|
412
|
+
closeDatabase();
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
386
416
|
test('gsd-db: recreates missing verification evidence dedup index after removing duplicate rows', () => {
|
|
387
417
|
const dbPath = tempDbPath();
|
|
388
418
|
openDatabase(dbPath);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — `projectRoot()` throws `GSDNoProjectError` when
|
|
3
|
+
* invoked outside a project directory (#4902).
|
|
4
|
+
*
|
|
5
|
+
* The deleted `gsd-no-project-error.test.ts` was a source-grep check.
|
|
6
|
+
* This rewrite chdirs to $HOME, calls the real `projectRoot()`, and
|
|
7
|
+
* asserts a `GSDNoProjectError` is thrown with the project-required
|
|
8
|
+
* message.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, test, after } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import * as os from 'node:os';
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
|
|
17
|
+
import { projectRoot, GSDNoProjectError } from '../commands/context.ts';
|
|
18
|
+
|
|
19
|
+
const ORIGINAL_CWD = process.cwd();
|
|
20
|
+
|
|
21
|
+
after(() => {
|
|
22
|
+
try { process.chdir(ORIGINAL_CWD); } catch { /* swallow */ }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('projectRoot() throws GSDNoProjectError outside a project (#4902)', () => {
|
|
26
|
+
test('throws GSDNoProjectError when cwd is $HOME', () => {
|
|
27
|
+
const home = os.homedir();
|
|
28
|
+
process.chdir(home);
|
|
29
|
+
try {
|
|
30
|
+
assert.throws(
|
|
31
|
+
() => projectRoot(),
|
|
32
|
+
(err: unknown) => {
|
|
33
|
+
assert.ok(err instanceof GSDNoProjectError, 'should throw GSDNoProjectError');
|
|
34
|
+
assert.match(
|
|
35
|
+
(err as Error).message,
|
|
36
|
+
/home directory|project directory/i,
|
|
37
|
+
'error message should mention home/project directory',
|
|
38
|
+
);
|
|
39
|
+
return true;
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
} finally {
|
|
43
|
+
process.chdir(ORIGINAL_CWD);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('throws GSDNoProjectError when cwd is the system tmpdir root', () => {
|
|
48
|
+
// Use realpath to dodge symlinks blocking the cwd
|
|
49
|
+
const tmpRoot = fs.realpathSync(os.tmpdir());
|
|
50
|
+
// Some systems make tmpdir a subdirectory; only run when it normalizes
|
|
51
|
+
// to a known-blocked root. validateDirectory blocks /tmp + /var/folders
|
|
52
|
+
// tmp roots; build a small subdir under tmp and then assert that the
|
|
53
|
+
// raw tmpdir root itself blocks. We just use it directly.
|
|
54
|
+
process.chdir(tmpRoot);
|
|
55
|
+
try {
|
|
56
|
+
// Behaviour: either we get a GSDNoProjectError (blocked tmpdir root) or
|
|
57
|
+
// we don't — but in the case where we don't (tmpdir is somehow allowed
|
|
58
|
+
// as a project root on this machine), the test is vacuously satisfied
|
|
59
|
+
// by the prior $HOME case. We assert the type-narrowing path instead:
|
|
60
|
+
let threw: unknown = null;
|
|
61
|
+
try { projectRoot(); } catch (err) { threw = err; }
|
|
62
|
+
if (threw !== null) {
|
|
63
|
+
assert.ok(
|
|
64
|
+
threw instanceof GSDNoProjectError,
|
|
65
|
+
'if projectRoot throws, it must be a GSDNoProjectError (typed)',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
process.chdir(ORIGINAL_CWD);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('GSDNoProjectError shape (#4902)', () => {
|
|
75
|
+
test('GSDNoProjectError extends Error and carries its name', () => {
|
|
76
|
+
const err = new GSDNoProjectError('test reason');
|
|
77
|
+
assert.ok(err instanceof Error);
|
|
78
|
+
assert.equal(err.name, 'GSDNoProjectError');
|
|
79
|
+
assert.equal(err.message, 'test reason');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* secrets, stats, and unused warnings).
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import test from 'node:test';
|
|
9
|
+
import test, { mock } from 'node:test';
|
|
10
10
|
import assert from 'node:assert/strict';
|
|
11
11
|
import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
12
12
|
import { join } from 'node:path';
|
|
@@ -164,7 +164,15 @@ test('tryHandle matches by question ID — single select', (t) => {
|
|
|
164
164
|
assert.strictEqual(injector.getStats().questionsAnswered, 1);
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
test('tryHandle unknown question deferred — first_option timeout',
|
|
167
|
+
test('tryHandle unknown question deferred — first_option timeout', (t) => {
|
|
168
|
+
// Use Node's MockTimers instead of a real-time setTimeout race. The
|
|
169
|
+
// production class schedules an internal setTimeout to default the
|
|
170
|
+
// answer when no metadata arrives — driving virtual time advances that
|
|
171
|
+
// timer deterministically, regardless of the literal ms value the
|
|
172
|
+
// production code chose.
|
|
173
|
+
mock.timers.enable({ apis: ['setTimeout'] });
|
|
174
|
+
t.after(() => { mock.timers.reset(); });
|
|
175
|
+
|
|
168
176
|
const injector = new AnswerInjector({ defaults: { strategy: 'first_option' } });
|
|
169
177
|
|
|
170
178
|
const captured: string[] = [];
|
|
@@ -177,8 +185,10 @@ test('tryHandle unknown question deferred — first_option timeout', async (t) =
|
|
|
177
185
|
assert.strictEqual(handled, true);
|
|
178
186
|
assert.strictEqual(captured.length, 0, 'nothing sent immediately');
|
|
179
187
|
|
|
180
|
-
//
|
|
181
|
-
|
|
188
|
+
// Advance virtual time past any internal defer timeout (well above any
|
|
189
|
+
// reasonable defer cap). MockTimers fires synchronously, so by the time
|
|
190
|
+
// tick() returns the deferred handler has run.
|
|
191
|
+
mock.timers.tick(60_000);
|
|
182
192
|
|
|
183
193
|
assert.strictEqual(captured.length, 1);
|
|
184
194
|
const response = JSON.parse(captured[0].trim());
|