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
|
@@ -1,47 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// GSD-2 — Verify /gsd help menu covers all registered commands
|
|
2
|
-
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
-
|
|
4
|
-
import { describe, test } from "node:test";
|
|
5
|
-
import assert from "node:assert/strict";
|
|
6
|
-
|
|
7
|
-
import { TOP_LEVEL_SUBCOMMANDS } from "../commands/catalog.ts";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Extracts command names from the showHelp("full") lines array.
|
|
11
|
-
* Each help line follows the pattern: " /gsd <cmd> ..."
|
|
12
|
-
*/
|
|
13
|
-
function extractHelpCommands(lines: string[]): Set<string> {
|
|
14
|
-
const cmds = new Set<string>();
|
|
15
|
-
for (const line of lines) {
|
|
16
|
-
const m = line.match(/^\s+\/gsd\s+(\S+)/);
|
|
17
|
-
if (m) cmds.add(m[1]);
|
|
18
|
-
}
|
|
19
|
-
return cmds;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe("help menu coverage", () => {
|
|
23
|
-
test("every TOP_LEVEL_SUBCOMMAND appears in showHelp(\"full\") output", async () => {
|
|
24
|
-
// Import showHelp and capture its output via a mock ctx
|
|
25
|
-
const lines: string[] = [];
|
|
26
|
-
const mockCtx = {
|
|
27
|
-
ui: {
|
|
28
|
-
notify(message: string) {
|
|
29
|
-
lines.push(...message.split("\n"));
|
|
30
|
-
},
|
|
31
|
-
custom: async () => {},
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const { showHelp } = await import("../commands/handlers/core.ts");
|
|
36
|
-
showHelp(mockCtx as any, "full");
|
|
37
|
-
|
|
38
|
-
const helpCmds = extractHelpCommands(lines);
|
|
39
|
-
|
|
40
|
-
// "help" is the command that shows the menu — it doesn't list itself
|
|
41
|
-
const SELF_REFERENTIAL = new Set(["help"]);
|
|
42
|
-
|
|
43
|
-
const missing: string[] = [];
|
|
44
|
-
for (const entry of TOP_LEVEL_SUBCOMMANDS) {
|
|
45
|
-
if (SELF_REFERENTIAL.has(entry.cmd)) continue;
|
|
46
|
-
if (!helpCmds.has(entry.cmd)) {
|
|
47
|
-
missing.push(entry.cmd);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
assert.deepStrictEqual(
|
|
52
|
-
missing,
|
|
53
|
-
[],
|
|
54
|
-
`Commands registered in TOP_LEVEL_SUBCOMMANDS but missing from /gsd help full:\n ${missing.join(", ")}`,
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime regression — milestones with all-done roadmap slices import as
|
|
3
|
-
* `complete` (#3699 / #3390 / #3379), follow-up #4902.
|
|
4
|
-
*
|
|
5
|
-
* The deleted `import-done-milestones.test.ts` was a source-grep check
|
|
6
|
-
* for the literal `roadmap.slices.every(s => s.done)`. This rewrite
|
|
7
|
-
* exercises `migrateHierarchyToDb()` against a fixture roadmap whose
|
|
8
|
-
* slices are all `[x]` and asserts the milestone row's `status` is
|
|
9
|
-
* `complete` — the actual behaviour the every() check exists to
|
|
10
|
-
* produce.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
14
|
-
import { join } from 'node:path';
|
|
15
|
-
import { tmpdir } from 'node:os';
|
|
16
|
-
|
|
17
|
-
import {
|
|
18
|
-
openDatabase,
|
|
19
|
-
closeDatabase,
|
|
20
|
-
getAllMilestones,
|
|
21
|
-
} from '../gsd-db.ts';
|
|
22
|
-
import { migrateHierarchyToDb } from '../md-importer.ts';
|
|
23
|
-
import { describe, test } from 'node:test';
|
|
24
|
-
import assert from 'node:assert/strict';
|
|
25
|
-
|
|
26
|
-
function createFixtureBase(): string {
|
|
27
|
-
const base = mkdtempSync(join(tmpdir(), 'gsd-import-done-'));
|
|
28
|
-
mkdirSync(join(base, '.gsd', 'milestones'), { recursive: true });
|
|
29
|
-
return base;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function writeFile(base: string, relativePath: string, content: string): void {
|
|
33
|
-
const full = join(base, '.gsd', relativePath);
|
|
34
|
-
mkdirSync(join(full, '..'), { recursive: true });
|
|
35
|
-
writeFileSync(full, content);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function cleanup(base: string): void {
|
|
39
|
-
rmSync(base, { recursive: true, force: true });
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const ROADMAP_ALL_DONE = `# M001: Finished Milestone
|
|
43
|
-
|
|
44
|
-
**Vision:** Done work.
|
|
45
|
-
|
|
46
|
-
## Slices
|
|
47
|
-
|
|
48
|
-
- [x] **S01: First Slice** \`risk:low\` \`depends:[]\`
|
|
49
|
-
> After this: Done.
|
|
50
|
-
|
|
51
|
-
- [x] **S02: Second Slice** \`risk:medium\` \`depends:[S01]\`
|
|
52
|
-
> After this: Also done.
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
const ROADMAP_PARTIAL = `# M002: In-Progress Milestone
|
|
56
|
-
|
|
57
|
-
**Vision:** Mid-flight.
|
|
58
|
-
|
|
59
|
-
## Slices
|
|
60
|
-
|
|
61
|
-
- [x] **S01: Done Slice** \`risk:low\` \`depends:[]\`
|
|
62
|
-
> After this: Done.
|
|
63
|
-
|
|
64
|
-
- [ ] **S02: Pending Slice** \`risk:medium\` \`depends:[S01]\`
|
|
65
|
-
> After this: TBD.
|
|
66
|
-
`;
|
|
67
|
-
|
|
68
|
-
const ROADMAP_EMPTY = `# M003: Empty Milestone
|
|
69
|
-
|
|
70
|
-
**Vision:** No slices yet.
|
|
71
|
-
|
|
72
|
-
## Slices
|
|
73
|
-
|
|
74
|
-
`;
|
|
75
|
-
|
|
76
|
-
describe('migrateHierarchyToDb: all-done milestones import as complete (#4902)', () => {
|
|
77
|
-
test('milestone with all [x] slices and no SUMMARY imports as complete', () => {
|
|
78
|
-
const base = createFixtureBase();
|
|
79
|
-
try {
|
|
80
|
-
writeFile(base, 'milestones/M001/M001-ROADMAP.md', ROADMAP_ALL_DONE);
|
|
81
|
-
// No SUMMARY.md — the all-done roadmap check is the authoritative signal.
|
|
82
|
-
|
|
83
|
-
openDatabase(':memory:');
|
|
84
|
-
migrateHierarchyToDb(base);
|
|
85
|
-
|
|
86
|
-
const milestones = getAllMilestones();
|
|
87
|
-
const m001 = milestones.find((m) => m.id === 'M001');
|
|
88
|
-
assert.ok(m001, 'M001 should be imported');
|
|
89
|
-
assert.equal(
|
|
90
|
-
m001!.status,
|
|
91
|
-
'complete',
|
|
92
|
-
'milestone with all-done slices must import as complete',
|
|
93
|
-
);
|
|
94
|
-
} finally {
|
|
95
|
-
closeDatabase();
|
|
96
|
-
cleanup(base);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test('milestone with one pending slice imports as active (negative case)', () => {
|
|
101
|
-
const base = createFixtureBase();
|
|
102
|
-
try {
|
|
103
|
-
writeFile(base, 'milestones/M002/M002-ROADMAP.md', ROADMAP_PARTIAL);
|
|
104
|
-
|
|
105
|
-
openDatabase(':memory:');
|
|
106
|
-
migrateHierarchyToDb(base);
|
|
107
|
-
|
|
108
|
-
const milestones = getAllMilestones();
|
|
109
|
-
const m002 = milestones.find((m) => m.id === 'M002');
|
|
110
|
-
assert.ok(m002, 'M002 should be imported');
|
|
111
|
-
assert.equal(
|
|
112
|
-
m002!.status,
|
|
113
|
-
'active',
|
|
114
|
-
'milestone with at least one pending slice must NOT be marked complete',
|
|
115
|
-
);
|
|
116
|
-
} finally {
|
|
117
|
-
closeDatabase();
|
|
118
|
-
cleanup(base);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test('milestone with empty slice list does not import as complete', () => {
|
|
123
|
-
// Guards the `roadmap.slices.length > 0` precondition: an empty roadmap
|
|
124
|
-
// must not be misread as "everything is done" (vacuous truth bug).
|
|
125
|
-
const base = createFixtureBase();
|
|
126
|
-
try {
|
|
127
|
-
writeFile(base, 'milestones/M003/M003-ROADMAP.md', ROADMAP_EMPTY);
|
|
128
|
-
|
|
129
|
-
openDatabase(':memory:');
|
|
130
|
-
migrateHierarchyToDb(base);
|
|
131
|
-
|
|
132
|
-
const milestones = getAllMilestones();
|
|
133
|
-
const m003 = milestones.find((m) => m.id === 'M003');
|
|
134
|
-
assert.ok(m003, 'M003 should be imported');
|
|
135
|
-
assert.notEqual(
|
|
136
|
-
m003!.status,
|
|
137
|
-
'complete',
|
|
138
|
-
'empty roadmap (no slices) must not import as complete',
|
|
139
|
-
);
|
|
140
|
-
} finally {
|
|
141
|
-
closeDatabase();
|
|
142
|
-
cleanup(base);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
});
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// gsd-2 / merge-self-branch-guard.test.ts — regression for #5024
|
|
2
|
-
//
|
|
3
|
-
// mergeMilestoneToMain() must fail closed when the resolved integration
|
|
4
|
-
// branch is the same ref as the milestone branch. Stale or corrupt
|
|
5
|
-
// integration metadata (e.g. integrationBranch recorded as "milestone/<MID>")
|
|
6
|
-
// would otherwise let the squash merge resolve to a self-merge: the post-
|
|
7
|
-
// merge no-op safety check (#1792) compares main vs milestone and finds an
|
|
8
|
-
// empty diff (because they're the same ref), so the helper returns success
|
|
9
|
-
// for work that never landed on a distinct integration branch.
|
|
10
|
-
|
|
11
|
-
import test from "node:test";
|
|
12
|
-
import assert from "node:assert/strict";
|
|
13
|
-
import {
|
|
14
|
-
mkdtempSync,
|
|
15
|
-
mkdirSync,
|
|
16
|
-
rmSync,
|
|
17
|
-
existsSync,
|
|
18
|
-
realpathSync,
|
|
19
|
-
writeFileSync,
|
|
20
|
-
} from "node:fs";
|
|
21
|
-
import { join } from "node:path";
|
|
22
|
-
import { tmpdir } from "node:os";
|
|
23
|
-
import { execFileSync } from "node:child_process";
|
|
24
|
-
|
|
25
|
-
import { mergeMilestoneToMain } from "../auto-worktree.ts";
|
|
26
|
-
import { _resetServiceCache } from "../worktree.ts";
|
|
27
|
-
import { _clearGsdRootCache } from "../paths.ts";
|
|
28
|
-
|
|
29
|
-
function git(args: string[], cwd: string): string {
|
|
30
|
-
return execFileSync("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function createTempRepo(): string {
|
|
34
|
-
const dir = realpathSync(mkdtempSync(join(tmpdir(), "merge-self-guard-")));
|
|
35
|
-
git(["init"], dir);
|
|
36
|
-
git(["config", "user.email", "test@test.com"], dir);
|
|
37
|
-
git(["config", "user.name", "Test"], dir);
|
|
38
|
-
writeFileSync(join(dir, "README.md"), "# test\n");
|
|
39
|
-
git(["add", "."], dir);
|
|
40
|
-
git(["commit", "-m", "init"], dir);
|
|
41
|
-
git(["branch", "-M", "main"], dir);
|
|
42
|
-
return dir;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function assertSelfMergeRefIsRejected(recordedIntegrationBranch: string): void {
|
|
46
|
-
const savedCwd = process.cwd();
|
|
47
|
-
let tempDir = "";
|
|
48
|
-
|
|
49
|
-
// Isolate from user's global preferences so prefs.main_branch can't
|
|
50
|
-
// override the corrupt-metadata path under test.
|
|
51
|
-
const originalHome = process.env.HOME;
|
|
52
|
-
const fakeHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-fake-home-")));
|
|
53
|
-
process.env.HOME = fakeHome;
|
|
54
|
-
_clearGsdRootCache();
|
|
55
|
-
_resetServiceCache();
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
tempDir = createTempRepo();
|
|
59
|
-
|
|
60
|
-
// Plant corrupt integration metadata: integrationBranch points at the
|
|
61
|
-
// milestone branch itself. Commit it so mergeMilestoneToMain's
|
|
62
|
-
// autoCommitDirtyState pre-step has nothing to capture and the
|
|
63
|
-
// postcondition (no new commits) cleanly reflects the guard.
|
|
64
|
-
const msDir = join(tempDir, ".gsd", "milestones", "M001");
|
|
65
|
-
mkdirSync(msDir, { recursive: true });
|
|
66
|
-
writeFileSync(
|
|
67
|
-
join(msDir, "M001-META.json"),
|
|
68
|
-
JSON.stringify({ integrationBranch: recordedIntegrationBranch }),
|
|
69
|
-
);
|
|
70
|
-
git(["add", "."], tempDir);
|
|
71
|
-
git(["commit", "-m", "chore: plant corrupt M001 meta"], tempDir);
|
|
72
|
-
|
|
73
|
-
// Create the milestone branch ref so any pre-guard branch operations
|
|
74
|
-
// wouldn't fail for unrelated reasons.
|
|
75
|
-
git(["branch", "milestone/M001"], tempDir);
|
|
76
|
-
|
|
77
|
-
const mainHeadBefore = git(["rev-parse", "main"], tempDir);
|
|
78
|
-
const milestoneHeadBefore = git(["rev-parse", "milestone/M001"], tempDir);
|
|
79
|
-
|
|
80
|
-
process.chdir(tempDir);
|
|
81
|
-
|
|
82
|
-
assert.throws(
|
|
83
|
-
() => mergeMilestoneToMain(tempDir, "M001", ""),
|
|
84
|
-
(err: unknown) => {
|
|
85
|
-
assert.ok(err instanceof Error, "expected an Error to be thrown");
|
|
86
|
-
assert.match(
|
|
87
|
-
err.message,
|
|
88
|
-
/self-merge|same ref/i,
|
|
89
|
-
"error message should explain the self-merge refusal",
|
|
90
|
-
);
|
|
91
|
-
return true;
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
// Postcondition: neither branch should have been advanced by a merge
|
|
96
|
-
// commit. The guard fires before checkout/merge, so both refs must be
|
|
97
|
-
// unchanged from their pre-call state.
|
|
98
|
-
const mainHeadAfter = git(["rev-parse", "main"], tempDir);
|
|
99
|
-
const milestoneHeadAfter = git(["rev-parse", "milestone/M001"], tempDir);
|
|
100
|
-
assert.equal(mainHeadAfter, mainHeadBefore, "main must not have advanced");
|
|
101
|
-
assert.equal(
|
|
102
|
-
milestoneHeadAfter,
|
|
103
|
-
milestoneHeadBefore,
|
|
104
|
-
"milestone branch must not have advanced",
|
|
105
|
-
);
|
|
106
|
-
} finally {
|
|
107
|
-
process.chdir(savedCwd);
|
|
108
|
-
process.env.HOME = originalHome;
|
|
109
|
-
_clearGsdRootCache();
|
|
110
|
-
_resetServiceCache();
|
|
111
|
-
if (tempDir && existsSync(tempDir)) {
|
|
112
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
113
|
-
}
|
|
114
|
-
rmSync(fakeHome, { recursive: true, force: true });
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
test("mergeMilestoneToMain refuses exact milestone branch self-merge metadata (#5024)", () => {
|
|
119
|
-
assertSelfMergeRefIsRejected("milestone/M001");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("mergeMilestoneToMain refuses refs/heads milestone branch self-merge metadata (#5024)", () => {
|
|
123
|
-
assertSelfMergeRefIsRejected("refs/heads/milestone/M001");
|
|
124
|
-
});
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
// GSD Extension — Regression test for #4996: ghost milestone ID reuse
|
|
2
|
-
// Verifies that isReusableGhostMilestone correctly identifies reclaim-safe stub dirs,
|
|
3
|
-
// and that nextMilestoneIdReserved (guided-flow) prefers the lowest reusable ghost
|
|
4
|
-
// over max+1. Also covers the race-window regression: a queued DB row must NOT be reused.
|
|
5
|
-
|
|
6
|
-
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
7
|
-
import assert from "node:assert/strict";
|
|
8
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
9
|
-
import { join } from "node:path";
|
|
10
|
-
import { tmpdir } from "node:os";
|
|
11
|
-
|
|
12
|
-
import { isReusableGhostMilestone } from "../state.ts";
|
|
13
|
-
import { nextMilestoneIdReserved } from "../milestone-id-reservation.ts";
|
|
14
|
-
import {
|
|
15
|
-
openDatabase,
|
|
16
|
-
closeDatabase,
|
|
17
|
-
insertMilestone,
|
|
18
|
-
} from "../gsd-db.ts";
|
|
19
|
-
import { clearReservedMilestoneIds, findMilestoneIds } from "../milestone-ids.ts";
|
|
20
|
-
import { invalidateAllCaches } from "../cache.ts";
|
|
21
|
-
|
|
22
|
-
function makeBase(prefix = "gsd-gap-4996-"): string {
|
|
23
|
-
const base = mkdtempSync(join(tmpdir(), prefix));
|
|
24
|
-
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
25
|
-
return base;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function stubDir(base: string, mid: string): void {
|
|
29
|
-
// Create an empty stub — the phantom pattern
|
|
30
|
-
mkdirSync(join(base, ".gsd", "milestones", mid, "slices"), { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function populateDir(base: string, mid: string): void {
|
|
34
|
-
mkdirSync(join(base, ".gsd", "milestones", mid), { recursive: true });
|
|
35
|
-
writeFileSync(join(base, ".gsd", "milestones", mid, `${mid}-CONTEXT.md`), `# ${mid} Context\n`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe("isReusableGhostMilestone (#4996)", () => {
|
|
39
|
-
let base: string;
|
|
40
|
-
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
try { closeDatabase(); } catch { /* ignore */ }
|
|
43
|
-
try { invalidateAllCaches(); } catch { /* ignore */ }
|
|
44
|
-
try { rmSync(base, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("(a) fails closed when the DB is unavailable", () => {
|
|
48
|
-
base = makeBase();
|
|
49
|
-
stubDir(base, "M003");
|
|
50
|
-
assert.equal(isReusableGhostMilestone(base, "M003"), false, "closed DB should block reusable-ghost claims");
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("(b) empty stub dir with an open DB and no DB row is reusable", () => {
|
|
54
|
-
base = makeBase();
|
|
55
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
56
|
-
stubDir(base, "M003");
|
|
57
|
-
assert.ok(isReusableGhostMilestone(base, "M003"), "empty stub with no DB row should be reusable");
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("(c) queued DB row with no content must NOT be reusable (race window regression)", () => {
|
|
61
|
-
base = makeBase();
|
|
62
|
-
stubDir(base, "M003");
|
|
63
|
-
const dbPath = join(base, ".gsd", "gsd.db");
|
|
64
|
-
openDatabase(dbPath);
|
|
65
|
-
insertMilestone({ id: "M003", status: "queued" });
|
|
66
|
-
// Even though no content files exist, the queued DB row means an in-flight discuss
|
|
67
|
-
// is reserving this ID — it must not be reclaimed.
|
|
68
|
-
assert.ok(!isReusableGhostMilestone(base, "M003"), "queued DB row must block reuse");
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("(d) populated milestone dir is not reusable", () => {
|
|
72
|
-
base = makeBase();
|
|
73
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
74
|
-
populateDir(base, "M001");
|
|
75
|
-
assert.ok(!isReusableGhostMilestone(base, "M001"), "populated dir must not be reusable");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("(e) stub dir with worktree is not reusable (legitimate in-flight)", () => {
|
|
79
|
-
base = makeBase();
|
|
80
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
81
|
-
stubDir(base, "M003");
|
|
82
|
-
// Simulate an existing worktree
|
|
83
|
-
mkdirSync(join(base, ".gsd", "worktrees", "M003"), { recursive: true });
|
|
84
|
-
assert.ok(!isReusableGhostMilestone(base, "M003"), "dir with worktree must not be reusable");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it("(f) active DB row makes dir not reusable", () => {
|
|
88
|
-
base = makeBase();
|
|
89
|
-
stubDir(base, "M003");
|
|
90
|
-
const dbPath = join(base, ".gsd", "gsd.db");
|
|
91
|
-
openDatabase(dbPath);
|
|
92
|
-
insertMilestone({ id: "M003", status: "active" });
|
|
93
|
-
assert.ok(!isReusableGhostMilestone(base, "M003"), "active DB row must block reuse");
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
describe("primary regression: M003/M004 stubs returned as next ID (#4996)", () => {
|
|
98
|
-
let base: string;
|
|
99
|
-
|
|
100
|
-
beforeEach(() => {
|
|
101
|
-
clearReservedMilestoneIds();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
afterEach(() => {
|
|
105
|
-
try { closeDatabase(); } catch { /* ignore */ }
|
|
106
|
-
try { invalidateAllCaches(); } catch { /* ignore */ }
|
|
107
|
-
try { clearReservedMilestoneIds(); } catch { /* ignore */ }
|
|
108
|
-
try { rmSync(base, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("M001/M002 populated + M003/M004 stubs → isReusableGhostMilestone returns true for M003 and M004", () => {
|
|
112
|
-
base = makeBase();
|
|
113
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
114
|
-
populateDir(base, "M001");
|
|
115
|
-
populateDir(base, "M002");
|
|
116
|
-
stubDir(base, "M003");
|
|
117
|
-
stubDir(base, "M004");
|
|
118
|
-
|
|
119
|
-
assert.ok(isReusableGhostMilestone(base, "M003"), "M003 should be identified as reusable ghost");
|
|
120
|
-
assert.ok(isReusableGhostMilestone(base, "M004"), "M004 should be identified as reusable ghost");
|
|
121
|
-
assert.ok(!isReusableGhostMilestone(base, "M001"), "M001 should not be reusable");
|
|
122
|
-
assert.ok(!isReusableGhostMilestone(base, "M002"), "M002 should not be reusable");
|
|
123
|
-
|
|
124
|
-
const nextId = nextMilestoneIdReserved(findMilestoneIds(base), false, base);
|
|
125
|
-
assert.equal(nextId, "M003", "ID reservation should select the lowest reusable ghost");
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("when all dirs are populated, no ghost exists and the function returns false for all", () => {
|
|
129
|
-
base = makeBase();
|
|
130
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
131
|
-
populateDir(base, "M001");
|
|
132
|
-
populateDir(base, "M002");
|
|
133
|
-
|
|
134
|
-
assert.ok(!isReusableGhostMilestone(base, "M001"), "M001 is populated, not reusable");
|
|
135
|
-
assert.ok(!isReusableGhostMilestone(base, "M002"), "M002 is populated, not reusable");
|
|
136
|
-
|
|
137
|
-
const nextId = nextMilestoneIdReserved(findMilestoneIds(base), false, base);
|
|
138
|
-
assert.equal(nextId, "M003", "ID reservation should fall back to max+1 when no ghost is reusable");
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("does not return an already-reserved reusable ghost twice", () => {
|
|
142
|
-
base = makeBase();
|
|
143
|
-
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
144
|
-
stubDir(base, "M001");
|
|
145
|
-
|
|
146
|
-
const firstId = nextMilestoneIdReserved(findMilestoneIds(base), false, base);
|
|
147
|
-
const secondId = nextMilestoneIdReserved(findMilestoneIds(base), false, base);
|
|
148
|
-
|
|
149
|
-
assert.equal(firstId, "M001", "first reservation should reuse the ghost");
|
|
150
|
-
assert.equal(secondId, "M002", "second reservation must skip the already-reserved ghost");
|
|
151
|
-
});
|
|
152
|
-
});
|