gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.0fdacd524
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 +8 -7
- package/dist/bundled-resource-path.d.ts +7 -0
- package/dist/bundled-resource-path.js +34 -2
- package/dist/claude-cli-check.js +77 -38
- 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 +90 -46
- package/dist/resources/extensions/google-search/index.js +2 -6
- 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 +26 -12
- 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-direct-dispatch.js +55 -21
- package/dist/resources/extensions/gsd/auto-dispatch.js +18 -6
- package/dist/resources/extensions/gsd/auto-prompts.js +69 -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 +39 -14
- 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 +112 -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 +45 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +121 -3
- package/dist/resources/extensions/gsd/commands/catalog.js +76 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +23 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +8 -0
- 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/commands-worktree.js +309 -0
- 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/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -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/prompts/rewrite-docs.md +2 -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 -9
- 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/resources/skills/lint/SKILL.md +4 -0
- package/dist/resources/skills/review/SKILL.md +4 -0
- package/dist/resources/skills/test/SKILL.md +3 -0
- 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 +13 -13
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +44 -4
- 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_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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.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/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/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/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/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/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -1
- package/dist/welcome-screen.js +27 -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 +92 -47
- package/src/resources/extensions/google-search/index.ts +2 -9
- 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 +26 -12
- 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-direct-dispatch.ts +60 -24
- package/src/resources/extensions/gsd/auto-dispatch.ts +18 -6
- package/src/resources/extensions/gsd/auto-prompts.ts +66 -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 +37 -10
- 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 +121 -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 +50 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +141 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +82 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +23 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- 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/commands-worktree.ts +383 -0
- 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/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +2 -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/prompts/rewrite-docs.md +2 -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 +179 -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/bundled-skill-triggers.test.ts +50 -27
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -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/google-search-stub.test.ts +25 -65
- 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/safety-harness-false-positives.test.ts +34 -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-path-injection.test.ts +235 -0
- 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 -10
- 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/src/resources/skills/lint/SKILL.md +4 -0
- package/src/resources/skills/review/SKILL.md +4 -0
- package/src/resources/skills/test/SKILL.md +3 -0
- 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/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/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → 4iu6IYeYfxOq8OidlDqp6}/_ssgManifest.js +0 -0
|
@@ -11,26 +11,23 @@ test("google-search stub: default export is a function", async (_t) => {
|
|
|
11
11
|
assert.equal(typeof stubFn, "function");
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
test("google-search stub: registers
|
|
15
|
-
// STUB-01: stub
|
|
14
|
+
test("google-search stub: registers no event handlers", async (_t) => {
|
|
15
|
+
// STUB-01: deprecation notice is suppressed — stub must not call pi.on() at all
|
|
16
16
|
const mod = await import("../../google-search/index.ts");
|
|
17
17
|
const stubFn = mod.default;
|
|
18
18
|
|
|
19
|
-
let
|
|
20
|
-
let capturedHandler: unknown;
|
|
19
|
+
let onCallCount = 0;
|
|
21
20
|
|
|
22
21
|
const mockPi = {
|
|
23
|
-
on(
|
|
24
|
-
|
|
25
|
-
capturedHandler = handler;
|
|
22
|
+
on(_event: string, _handler: unknown) {
|
|
23
|
+
onCallCount++;
|
|
26
24
|
},
|
|
27
25
|
registerTool: () => {},
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
stubFn(mockPi as never);
|
|
31
29
|
|
|
32
|
-
assert.equal(
|
|
33
|
-
assert.equal(typeof capturedHandler, "function");
|
|
30
|
+
assert.equal(onCallCount, 0, "stub should not register any event handlers");
|
|
34
31
|
});
|
|
35
32
|
|
|
36
33
|
test("google-search stub: does NOT call registerTool", async (_t) => {
|
|
@@ -50,82 +47,45 @@ test("google-search stub: does NOT call registerTool", async (_t) => {
|
|
|
50
47
|
assert.equal(registerToolCalled, false);
|
|
51
48
|
});
|
|
52
49
|
|
|
53
|
-
test("google-search stub:
|
|
54
|
-
// STUB-01:
|
|
50
|
+
test("google-search stub: does not emit any notifications", async (_t) => {
|
|
51
|
+
// STUB-01: deprecation notice is suppressed — stub must not call ctx.ui.notify()
|
|
55
52
|
const mod = await import("../../google-search/index.ts");
|
|
56
53
|
const stubFn = mod.default;
|
|
57
54
|
|
|
58
|
-
let
|
|
55
|
+
let notifyCallCount = 0;
|
|
59
56
|
|
|
60
57
|
const mockPi = {
|
|
61
|
-
on(_event: string,
|
|
62
|
-
capturedHandler = handler;
|
|
63
|
-
},
|
|
58
|
+
on(_event: string, _handler: unknown) {},
|
|
64
59
|
registerTool: () => {},
|
|
65
60
|
};
|
|
66
61
|
|
|
62
|
+
// Verify no notify is emitted by the stub itself (it registers no handlers,
|
|
63
|
+
// so there is nothing to invoke — this simply confirms no top-level notify call).
|
|
67
64
|
stubFn(mockPi as never);
|
|
68
65
|
|
|
69
|
-
assert.
|
|
70
|
-
|
|
71
|
-
let capturedMessage: string | undefined;
|
|
72
|
-
const mockCtx = {
|
|
73
|
-
ui: {
|
|
74
|
-
notify(message: string, _level: string) {
|
|
75
|
-
capturedMessage = message;
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
await capturedHandler!({}, mockCtx);
|
|
81
|
-
|
|
82
|
-
assert.ok(
|
|
83
|
-
capturedMessage?.includes("@gsd-extensions/google-search"),
|
|
84
|
-
`Expected message to include "@gsd-extensions/google-search", got: "${capturedMessage}"`,
|
|
85
|
-
);
|
|
66
|
+
assert.equal(notifyCallCount, 0, "stub should not emit any notifications");
|
|
86
67
|
});
|
|
87
68
|
|
|
88
|
-
test("google-search stub:
|
|
89
|
-
// STUB-01:
|
|
90
|
-
//
|
|
91
|
-
// explain the extraction is in progress and no user action is required.
|
|
69
|
+
test("google-search stub: is a complete no-op (no handlers, no tools, no notifications)", async (_t) => {
|
|
70
|
+
// STUB-01: the deprecation notice is suppressed until @gsd-extensions/google-search
|
|
71
|
+
// ships. The stub must call nothing on the ExtensionAPI.
|
|
92
72
|
const mod = await import("../../google-search/index.ts");
|
|
93
73
|
const stubFn = mod.default;
|
|
94
74
|
|
|
95
|
-
let
|
|
75
|
+
let onCallCount = 0;
|
|
76
|
+
let registerToolCallCount = 0;
|
|
96
77
|
|
|
97
78
|
const mockPi = {
|
|
98
|
-
on(_event: string,
|
|
99
|
-
|
|
79
|
+
on(_event: string, _handler: unknown) {
|
|
80
|
+
onCallCount++;
|
|
81
|
+
},
|
|
82
|
+
registerTool: () => {
|
|
83
|
+
registerToolCallCount++;
|
|
100
84
|
},
|
|
101
|
-
registerTool: () => {},
|
|
102
85
|
};
|
|
103
86
|
|
|
104
87
|
stubFn(mockPi as never);
|
|
105
88
|
|
|
106
|
-
assert.
|
|
107
|
-
|
|
108
|
-
let capturedMessage: string | undefined;
|
|
109
|
-
const mockCtx = {
|
|
110
|
-
ui: {
|
|
111
|
-
notify(message: string, _level: string) {
|
|
112
|
-
capturedMessage = message;
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
await capturedHandler!({}, mockCtx);
|
|
118
|
-
|
|
119
|
-
assert.ok(
|
|
120
|
-
!capturedMessage?.includes("gsd extensions install"),
|
|
121
|
-
`Expected message NOT to include unpublished install command, got: "${capturedMessage}"`,
|
|
122
|
-
);
|
|
123
|
-
assert.ok(
|
|
124
|
-
capturedMessage?.includes("not yet published"),
|
|
125
|
-
`Expected message to include "not yet published", got: "${capturedMessage}"`,
|
|
126
|
-
);
|
|
127
|
-
assert.ok(
|
|
128
|
-
capturedMessage?.includes("No action needed"),
|
|
129
|
-
`Expected message to include "No action needed", got: "${capturedMessage}"`,
|
|
130
|
-
);
|
|
89
|
+
assert.equal(onCallCount, 0, "stub should not register any event handlers");
|
|
90
|
+
assert.equal(registerToolCallCount, 0, "stub should not register any tools");
|
|
131
91
|
});
|
|
@@ -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());
|
|
@@ -66,16 +66,22 @@ test("detectHealthWidgetProjectState: milestone without metrics returns active",
|
|
|
66
66
|
assert.equal(detectHealthWidgetProjectState(dir), "active");
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
test("buildHealthLines: none state shows onboarding
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
test("buildHealthLines: none state shows single onboarding line pointing at /gsd", (t) => {
|
|
70
|
+
const lines = buildHealthLines(activeData({ projectState: "none" }));
|
|
71
|
+
assert.equal(lines.length, 1, "renders exactly one line");
|
|
72
|
+
// Should not show System OK / Budget / Last commit chrome when there's no project.
|
|
73
|
+
assert.ok(!/System OK|Budget|Last commit/.test(lines[0]!), "no active-project chrome");
|
|
74
|
+
// Should direct user to bootstrap via /gsd.
|
|
75
|
+
assert.match(lines[0]!, /\/gsd/);
|
|
73
76
|
});
|
|
74
77
|
|
|
75
|
-
test("buildHealthLines: initialized state shows
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
]);
|
|
78
|
+
test("buildHealthLines: initialized state shows single setup line pointing at /gsd", (t) => {
|
|
79
|
+
const lines = buildHealthLines(activeData({ projectState: "initialized" }));
|
|
80
|
+
assert.equal(lines.length, 1, "renders exactly one line");
|
|
81
|
+
assert.ok(!/System OK|Budget|Last commit/.test(lines[0]!), "no active-project chrome");
|
|
82
|
+
// Distinct from "none" — must mention initialized/setup language and /gsd.
|
|
83
|
+
assert.match(lines[0]!, /\/gsd/);
|
|
84
|
+
assert.match(lines[0]!, /initiali[sz]ed|setup/i);
|
|
79
85
|
});
|
|
80
86
|
|
|
81
87
|
test("buildHealthLines: active state with ledger-driven spend shows spent summary", (t) => {
|
|
@@ -115,16 +121,20 @@ test("buildHealthLines: shows last commit with relative time and message", (t) =
|
|
|
115
121
|
assert.match(lines[0]!, /feat\(widget\): add health display/);
|
|
116
122
|
});
|
|
117
123
|
|
|
118
|
-
test("buildHealthLines: truncates long commit messages", (t) => {
|
|
124
|
+
test("buildHealthLines: truncates long commit messages with ellipsis", (t) => {
|
|
119
125
|
const epoch = Math.floor(Date.now() / 1000) - 60;
|
|
120
|
-
const longMsg = "a".repeat(
|
|
126
|
+
const longMsg = "a".repeat(200); // far longer than any reasonable widget cap
|
|
121
127
|
const lines = buildHealthLines(activeData({
|
|
122
128
|
lastCommitEpoch: epoch,
|
|
123
129
|
lastCommitMessage: longMsg,
|
|
124
130
|
}));
|
|
125
131
|
assert.equal(lines.length, 1);
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
// Behavioural contract: rendered output is shorter than the input message
|
|
133
|
+
// and ends the message portion with the ellipsis character.
|
|
134
|
+
const aRun = lines[0]!.match(/a+…/);
|
|
135
|
+
assert.ok(aRun, "rendered output contains a run of a-chars terminated by an ellipsis");
|
|
136
|
+
assert.ok(aRun![0].length - 1 < longMsg.length, "truncated message is shorter than input");
|
|
137
|
+
assert.ok(!lines[0]!.includes("a".repeat(longMsg.length)), "untruncated message must not appear in output");
|
|
128
138
|
});
|
|
129
139
|
|
|
130
140
|
test("buildHealthLines: no last commit section when epoch is null", (t) => {
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for getHomeDir() — cross-platform home directory resolution.
|
|
3
|
+
*
|
|
4
|
+
* @see https://github.com/gsd-build/gsd-2/issues/5015
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
|
|
10
|
+
describe("getHomeDir", () => {
|
|
11
|
+
let savedHome: string | undefined;
|
|
12
|
+
let savedUserProfile: string | undefined;
|
|
13
|
+
let getHomeDir: () => string;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
savedHome = process.env.HOME;
|
|
17
|
+
savedUserProfile = process.env.USERPROFILE;
|
|
18
|
+
const mod = await import("../home-dir.ts");
|
|
19
|
+
getHomeDir = mod.getHomeDir;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
if (savedHome !== undefined) {
|
|
24
|
+
process.env.HOME = savedHome;
|
|
25
|
+
} else {
|
|
26
|
+
delete process.env.HOME;
|
|
27
|
+
}
|
|
28
|
+
if (savedUserProfile !== undefined) {
|
|
29
|
+
process.env.USERPROFILE = savedUserProfile;
|
|
30
|
+
} else {
|
|
31
|
+
delete process.env.USERPROFILE;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("returns HOME when set", () => {
|
|
36
|
+
process.env.HOME = "/test/home";
|
|
37
|
+
delete process.env.USERPROFILE;
|
|
38
|
+
assert.equal(getHomeDir(), "/test/home");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("falls back to USERPROFILE when HOME is unset", () => {
|
|
42
|
+
delete process.env.HOME;
|
|
43
|
+
process.env.USERPROFILE = String.raw`C:\Users\test`;
|
|
44
|
+
assert.equal(getHomeDir(), String.raw`C:\Users\test`);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("falls back to os.homedir() when both HOME and USERPROFILE are unset", () => {
|
|
48
|
+
delete process.env.HOME;
|
|
49
|
+
delete process.env.USERPROFILE;
|
|
50
|
+
assert.equal(getHomeDir(), homedir());
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
+
});
|