gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.84a383f51
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/claude-cli-check.js +64 -37
- 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 +24 -4
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +7 -10
- 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 +28 -5
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +77 -45
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- 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 +30 -0
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +94 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- 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 +2 -2
- 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 +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- 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/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/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-session-state.js +33 -0
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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 +12 -12
- 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/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -1
- 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 +26 -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/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 +78 -46
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- 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 +38 -0
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +102 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- 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 +2 -2
- 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 +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- 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/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +9 -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/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/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 +22 -0
- 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/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/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/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/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- 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 +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-session-state.ts +35 -0
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/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 → UF5VF4F1tB0miEtJS7LyX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_ssgManifest.js +0 -0
|
@@ -1,104 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Behavioural regression tests for #3922.
|
|
3
3
|
*
|
|
4
|
-
* Before this fix, deriveState() logged
|
|
5
|
-
*
|
|
6
|
-
* before_agent_start context injection). The fix
|
|
7
|
-
*
|
|
4
|
+
* Before this fix, deriveState() logged "DB unavailable — degraded mode"
|
|
5
|
+
* even when the DB had not been opened yet (e.g. during
|
|
6
|
+
* before_agent_start context injection). The fix introduced
|
|
7
|
+
* wasDbOpenAttempted() so the warning fires only after a real open attempt.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The earlier tests source-grepped state.ts for the warning string and the
|
|
10
|
+
* preceding line (POSITIONAL/SOURCE_GREP per #4826/#4829). They are
|
|
11
|
+
* replaced here with direct calls to the wasDbOpenAttempted flag.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { describe, test } from "node:test";
|
|
14
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
15
15
|
import assert from "node:assert/strict";
|
|
16
|
-
import { readFileSync } from "node:fs";
|
|
17
|
-
import { dirname, join } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
16
|
import {
|
|
20
17
|
openDatabase,
|
|
21
18
|
closeDatabase,
|
|
22
|
-
isDbAvailable,
|
|
23
19
|
wasDbOpenAttempted,
|
|
24
20
|
} from "../gsd-db.ts";
|
|
25
21
|
|
|
26
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
-
const stateSource = readFileSync(join(__dirname, "..", "state.ts"), "utf-8");
|
|
28
|
-
|
|
29
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
30
|
-
// 1. gsd-db: wasDbOpenAttempted flag
|
|
31
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
32
|
-
|
|
33
22
|
describe("wasDbOpenAttempted (#3922)", () => {
|
|
23
|
+
beforeEach(() => { closeDatabase(); });
|
|
24
|
+
afterEach(() => { closeDatabase(); });
|
|
34
25
|
|
|
35
|
-
test("
|
|
36
|
-
// By this point in the test suite, openDatabase may or may not have been
|
|
37
|
-
// called by other tests. So we call it explicitly and verify it returns true.
|
|
26
|
+
test("returns true after a successful openDatabase call", () => {
|
|
38
27
|
openDatabase(":memory:");
|
|
39
|
-
assert.strictEqual(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
test("openDatabase sets the flag even if it fails on invalid path", () => {
|
|
45
|
-
// openDatabase with an unreachable path may fail, but the flag should
|
|
46
|
-
// still be set because the attempt was made.
|
|
47
|
-
try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
|
|
48
|
-
assert.strictEqual(wasDbOpenAttempted(), true,
|
|
49
|
-
"wasDbOpenAttempted should be true even after a failed open attempt");
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
54
|
-
// 2. state.ts: degraded-mode warning is gated behind wasDbOpenAttempted
|
|
55
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
56
|
-
|
|
57
|
-
describe("degraded-mode warning guard (#3922)", () => {
|
|
58
|
-
|
|
59
|
-
test("state.ts imports wasDbOpenAttempted from gsd-db", () => {
|
|
60
|
-
assert.ok(
|
|
61
|
-
stateSource.includes("wasDbOpenAttempted"),
|
|
62
|
-
"state.ts must import wasDbOpenAttempted to gate the degraded-mode warning",
|
|
28
|
+
assert.strictEqual(
|
|
29
|
+
wasDbOpenAttempted(),
|
|
30
|
+
true,
|
|
31
|
+
"wasDbOpenAttempted should report true after openDatabase succeeds",
|
|
63
32
|
);
|
|
64
33
|
});
|
|
65
34
|
|
|
66
|
-
test("
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// The wasDbOpenAttempted() check must appear BEFORE the warning,
|
|
73
|
-
// within the same else-branch (i.e. within a reasonable distance).
|
|
74
|
-
// Look backwards from the warning for the guard.
|
|
75
|
-
const searchWindow = stateSource.slice(Math.max(0, warningIdx - 300), warningIdx);
|
|
76
|
-
assert.ok(
|
|
77
|
-
searchWindow.includes("wasDbOpenAttempted()"),
|
|
78
|
-
"wasDbOpenAttempted() guard must appear shortly before the degraded-mode warning " +
|
|
79
|
-
"to prevent false warnings when DB has not been initialized yet",
|
|
35
|
+
test("remains true after a failed open attempt — the attempt is what matters", () => {
|
|
36
|
+
try { openDatabase("/nonexistent/path/that/will/fail.db"); } catch { /* expected */ }
|
|
37
|
+
assert.strictEqual(
|
|
38
|
+
wasDbOpenAttempted(),
|
|
39
|
+
true,
|
|
40
|
+
"wasDbOpenAttempted should be true even when openDatabase throws — the warning gate keys on the attempt, not the outcome",
|
|
80
41
|
);
|
|
81
42
|
});
|
|
82
|
-
|
|
83
|
-
test("warning is NOT emitted unconditionally in the else branch", () => {
|
|
84
|
-
// The old code had `logWarning(...)` directly in the else branch.
|
|
85
|
-
// The fix wraps it in `if (wasDbOpenAttempted())`.
|
|
86
|
-
// Verify the logWarning call is inside a conditional, not bare.
|
|
87
|
-
const lines = stateSource.split("\n");
|
|
88
|
-
for (let i = 0; i < lines.length; i++) {
|
|
89
|
-
if (lines[i]!.includes("DB unavailable") && lines[i]!.includes("degraded mode")) {
|
|
90
|
-
// This line has the warning. Check that the preceding non-empty line
|
|
91
|
-
// contains an if-condition (wasDbOpenAttempted), not a bare else.
|
|
92
|
-
let prev = i - 1;
|
|
93
|
-
while (prev >= 0 && lines[prev]!.trim() === "") prev--;
|
|
94
|
-
const prevLine = lines[prev]!.trim();
|
|
95
|
-
assert.ok(
|
|
96
|
-
prevLine.includes("wasDbOpenAttempted"),
|
|
97
|
-
`Line ${i + 1} emits degraded-mode warning — preceding line ${prev + 1} must ` +
|
|
98
|
-
`contain wasDbOpenAttempted guard, but found: "${prevLine}"`,
|
|
99
|
-
);
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
43
|
});
|
|
@@ -17,12 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { createTestContext } from "./test-helpers.ts";
|
|
20
|
-
import {
|
|
21
|
-
withTimeout,
|
|
22
|
-
FINALIZE_PRE_TIMEOUT_MS,
|
|
23
|
-
FINALIZE_POST_TIMEOUT_MS,
|
|
24
|
-
} from "../auto/finalize-timeout.ts";
|
|
25
|
-
import { MAX_FINALIZE_TIMEOUTS } from "../auto/types.ts";
|
|
20
|
+
import { withTimeout } from "../auto/finalize-timeout.ts";
|
|
26
21
|
|
|
27
22
|
const { assertTrue, assertEq, report } = createTestContext();
|
|
28
23
|
|
|
@@ -80,44 +75,6 @@ const { assertTrue, assertEq, report } = createTestContext();
|
|
|
80
75
|
assertTrue(caught, "rejection should propagate");
|
|
81
76
|
}
|
|
82
77
|
|
|
83
|
-
// ═══ Test: FINALIZE_PRE_TIMEOUT_MS is defined and reasonable ═════════════════
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
console.log("\n=== #3757: pre-verification timeout constant is defined and reasonable ===");
|
|
87
|
-
|
|
88
|
-
assertTrue(
|
|
89
|
-
typeof FINALIZE_PRE_TIMEOUT_MS === "number",
|
|
90
|
-
"FINALIZE_PRE_TIMEOUT_MS should be a number",
|
|
91
|
-
);
|
|
92
|
-
assertTrue(
|
|
93
|
-
FINALIZE_PRE_TIMEOUT_MS >= 30_000,
|
|
94
|
-
`pre timeout should be >= 30s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
|
|
95
|
-
);
|
|
96
|
-
assertTrue(
|
|
97
|
-
FINALIZE_PRE_TIMEOUT_MS <= 120_000,
|
|
98
|
-
`pre timeout should be <= 120s (got ${FINALIZE_PRE_TIMEOUT_MS}ms)`,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ═══ Test: FINALIZE_POST_TIMEOUT_MS is defined and reasonable ═════════════════
|
|
103
|
-
|
|
104
|
-
{
|
|
105
|
-
console.log("\n=== #2344: timeout constant is defined and reasonable ===");
|
|
106
|
-
|
|
107
|
-
assertTrue(
|
|
108
|
-
typeof FINALIZE_POST_TIMEOUT_MS === "number",
|
|
109
|
-
"FINALIZE_POST_TIMEOUT_MS should be a number",
|
|
110
|
-
);
|
|
111
|
-
assertTrue(
|
|
112
|
-
FINALIZE_POST_TIMEOUT_MS >= 30_000,
|
|
113
|
-
`timeout should be >= 30s (got ${FINALIZE_POST_TIMEOUT_MS}ms)`,
|
|
114
|
-
);
|
|
115
|
-
assertTrue(
|
|
116
|
-
FINALIZE_POST_TIMEOUT_MS <= 120_000,
|
|
117
|
-
`timeout should be <= 120s (got ${FINALIZE_POST_TIMEOUT_MS}ms)`,
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
78
|
// ═══ Test: withTimeout cleans up timer on success ════════════════════════════
|
|
122
79
|
|
|
123
80
|
{
|
|
@@ -134,25 +91,6 @@ const { assertTrue, assertEq, report } = createTestContext();
|
|
|
134
91
|
assertEq(result.timedOut, false, "should not time out");
|
|
135
92
|
}
|
|
136
93
|
|
|
137
|
-
// ═══ Test: MAX_FINALIZE_TIMEOUTS is defined and reasonable ═══════════════════
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
console.log("\n=== #3757: MAX_FINALIZE_TIMEOUTS is defined and reasonable ===");
|
|
141
|
-
|
|
142
|
-
assertTrue(
|
|
143
|
-
typeof MAX_FINALIZE_TIMEOUTS === "number",
|
|
144
|
-
"MAX_FINALIZE_TIMEOUTS should be a number",
|
|
145
|
-
);
|
|
146
|
-
assertTrue(
|
|
147
|
-
MAX_FINALIZE_TIMEOUTS >= 2,
|
|
148
|
-
`threshold should be >= 2 (got ${MAX_FINALIZE_TIMEOUTS})`,
|
|
149
|
-
);
|
|
150
|
-
assertTrue(
|
|
151
|
-
MAX_FINALIZE_TIMEOUTS <= 10,
|
|
152
|
-
`threshold should be <= 10 (got ${MAX_FINALIZE_TIMEOUTS})`,
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
94
|
// Note: the two previous source-grep blocks that scanned phases.ts for
|
|
157
95
|
// `withTimeout(` / `failClosedOnFinalizeTimeout(` occurrences were removed
|
|
158
96
|
// under #4825 — they encoded implementation shape (Goodhart) and broke on
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — closed-status omission for missing-summary detection
|
|
3
|
+
* (#4902).
|
|
4
|
+
*
|
|
5
|
+
* `findMissingSummaries` (auto-dispatch.ts) filters out slices in any closed
|
|
6
|
+
* status before checking for an on-disk SUMMARY. The deleted source-grep
|
|
7
|
+
* test asserted the literal `CLOSED_STATUSES` Set; this rewrite tests the
|
|
8
|
+
* exported predicate (`isClosedStatus`) that the inline Set replicates,
|
|
9
|
+
* so any drift between the predicate and the inline filter surfaces as a
|
|
10
|
+
* test failure here rather than a runtime miss.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, test } from 'node:test';
|
|
14
|
+
import assert from 'node:assert/strict';
|
|
15
|
+
|
|
16
|
+
import { isClosedStatus, isInactiveStatus } from '../status-guards.ts';
|
|
17
|
+
|
|
18
|
+
describe('isClosedStatus — closed-status omission contract (#4902)', () => {
|
|
19
|
+
test('returns true for every status findMissingSummaries skips', () => {
|
|
20
|
+
// Mirror the inline Set in auto-dispatch.ts:findMissingSummaries.
|
|
21
|
+
for (const s of ['complete', 'done', 'skipped']) {
|
|
22
|
+
assert.equal(
|
|
23
|
+
isClosedStatus(s),
|
|
24
|
+
true,
|
|
25
|
+
`${s} must count as a closed status (would-have-summary omission)`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('returns false for live in-flight statuses', () => {
|
|
31
|
+
for (const s of ['pending', 'active', 'in-progress', 'planning', 'executing']) {
|
|
32
|
+
assert.equal(
|
|
33
|
+
isClosedStatus(s),
|
|
34
|
+
false,
|
|
35
|
+
`${s} is in-flight and MUST be checked for a missing SUMMARY`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('isInactiveStatus also covers deferred so it is not summary-checked', () => {
|
|
41
|
+
// Deferred slices likewise never produce a SUMMARY; the active-slice
|
|
42
|
+
// selector uses isInactiveStatus to skip them. Pin the contract.
|
|
43
|
+
assert.equal(isInactiveStatus('deferred'), true);
|
|
44
|
+
assert.equal(isInactiveStatus('complete'), true);
|
|
45
|
+
assert.equal(isInactiveStatus('pending'), false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
import test from "node:test";
|
|
10
10
|
import assert from "node:assert/strict";
|
|
11
11
|
import type { UnitMetrics } from "../metrics.js";
|
|
12
|
-
import {
|
|
12
|
+
import type { WorktreeTelemetrySummary } from "../worktree-telemetry.js";
|
|
13
|
+
import { detectStuckLoops, detectWorktreeOrphans, type ForensicAnomaly } from "../forensics.js";
|
|
13
14
|
|
|
14
15
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
15
16
|
|
|
@@ -163,3 +164,27 @@ test("#3760 detectStuckLoops still flags repeated dispatches within one auto ses
|
|
|
163
164
|
`details should explain the session-aware rule: ${anomalies[0].details}`,
|
|
164
165
|
);
|
|
165
166
|
});
|
|
167
|
+
|
|
168
|
+
test("#4711 detectWorktreeOrphans suggests doctor fix for completed unmerged branches", () => {
|
|
169
|
+
const anomalies: ForensicAnomaly[] = [];
|
|
170
|
+
const summary: WorktreeTelemetrySummary = {
|
|
171
|
+
worktreesCreated: 0,
|
|
172
|
+
worktreesMerged: 0,
|
|
173
|
+
orphansDetected: 1,
|
|
174
|
+
orphansByReason: { "complete-unmerged": 1 },
|
|
175
|
+
mergeDurationsMs: [],
|
|
176
|
+
mergeConflicts: 0,
|
|
177
|
+
exitsByReason: {},
|
|
178
|
+
exitsWithUnmergedWork: 0,
|
|
179
|
+
canonicalRedirects: 0,
|
|
180
|
+
slicesMerged: 0,
|
|
181
|
+
sliceMergeConflicts: 0,
|
|
182
|
+
milestoneResquashes: 0,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
detectWorktreeOrphans(summary, anomalies);
|
|
186
|
+
|
|
187
|
+
assert.equal(anomalies.length, 1);
|
|
188
|
+
assert.match(anomalies[0]!.details, /\/gsd doctor fix/);
|
|
189
|
+
assert.doesNotMatch(anomalies[0]!.details, /\/gsd health --fix/);
|
|
190
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — `.bg-shell/` baseline pattern (#4902, prior #2655).
|
|
3
|
+
*
|
|
4
|
+
* The deleted `gitignore-bg-shell.test.ts` asserted `.bg-shell/` appeared in
|
|
5
|
+
* the BASELINE_PATTERNS array via source grep. This rewrite drives
|
|
6
|
+
* `ensureGitignore()` against a tmp directory and asserts the written
|
|
7
|
+
* `.gitignore` actually contains the `.bg-shell/` pattern — i.e. tests the
|
|
8
|
+
* behaviour the constant exists to guarantee, not the spelling of the
|
|
9
|
+
* constant.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, test } from 'node:test';
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as os from 'node:os';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
|
|
18
|
+
import { ensureGitignore } from '../gitignore.ts';
|
|
19
|
+
|
|
20
|
+
function makeTmpRepo(): string {
|
|
21
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-gitignore-bg-'));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function cleanup(dir: string): void {
|
|
25
|
+
try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* swallow */ }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('ensureGitignore writes .bg-shell/ baseline (#4902)', () => {
|
|
29
|
+
test('appends .bg-shell/ to a fresh project .gitignore', () => {
|
|
30
|
+
const dir = makeTmpRepo();
|
|
31
|
+
try {
|
|
32
|
+
const wrote = ensureGitignore(dir);
|
|
33
|
+
assert.equal(wrote, true, 'ensureGitignore should report it wrote');
|
|
34
|
+
|
|
35
|
+
const ignore = fs.readFileSync(path.join(dir, '.gitignore'), 'utf-8');
|
|
36
|
+
const lines = new Set(
|
|
37
|
+
ignore.split('\n').map((l) => l.trim()).filter(Boolean),
|
|
38
|
+
);
|
|
39
|
+
assert.ok(
|
|
40
|
+
lines.has('.bg-shell/'),
|
|
41
|
+
`.gitignore should include .bg-shell/. Got:\n${ignore}`,
|
|
42
|
+
);
|
|
43
|
+
} finally {
|
|
44
|
+
cleanup(dir);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('preserves .bg-shell/ when it is already present (idempotent)', () => {
|
|
49
|
+
const dir = makeTmpRepo();
|
|
50
|
+
try {
|
|
51
|
+
fs.writeFileSync(
|
|
52
|
+
path.join(dir, '.gitignore'),
|
|
53
|
+
'.bg-shell/\nnode_modules/\n',
|
|
54
|
+
);
|
|
55
|
+
ensureGitignore(dir); // run once to fill missing baseline
|
|
56
|
+
const ignore = fs.readFileSync(path.join(dir, '.gitignore'), 'utf-8');
|
|
57
|
+
const occurrences = ignore.split('\n').filter((l) => l.trim() === '.bg-shell/').length;
|
|
58
|
+
assert.equal(occurrences, 1, 'should not duplicate an existing .bg-shell/ entry');
|
|
59
|
+
} finally {
|
|
60
|
+
cleanup(dir);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
getActiveDecisions,
|
|
19
19
|
getActiveRequirements,
|
|
20
20
|
transaction,
|
|
21
|
+
readTransaction,
|
|
22
|
+
isInTransaction,
|
|
21
23
|
_getAdapter,
|
|
22
24
|
_resetProvider,
|
|
23
25
|
insertMilestone,
|
|
@@ -383,6 +385,34 @@ describe('gsd-db', () => {
|
|
|
383
385
|
closeDatabase();
|
|
384
386
|
});
|
|
385
387
|
|
|
388
|
+
test('gsd-db: failed BEGIN does not poison transaction depth', () => {
|
|
389
|
+
openDatabase(':memory:');
|
|
390
|
+
const adapter = _getAdapter()!;
|
|
391
|
+
|
|
392
|
+
const assertFailedBeginLeavesDepthClear = (label: string, fn: () => void) => {
|
|
393
|
+
adapter.exec('BEGIN');
|
|
394
|
+
try {
|
|
395
|
+
let threw = false;
|
|
396
|
+
try {
|
|
397
|
+
fn();
|
|
398
|
+
} catch {
|
|
399
|
+
threw = true;
|
|
400
|
+
}
|
|
401
|
+
assert.equal(threw, true, `${label} should surface the SQLite BEGIN failure`);
|
|
402
|
+
assert.equal(isInTransaction(), false, `${label} failed BEGIN must not leave depth active`);
|
|
403
|
+
} finally {
|
|
404
|
+
adapter.exec('ROLLBACK');
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
try {
|
|
409
|
+
assertFailedBeginLeavesDepthClear('transaction', () => transaction(() => undefined));
|
|
410
|
+
assertFailedBeginLeavesDepthClear('readTransaction', () => readTransaction(() => undefined));
|
|
411
|
+
} finally {
|
|
412
|
+
closeDatabase();
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
386
416
|
test('gsd-db: recreates missing verification evidence dedup index after removing duplicate rows', () => {
|
|
387
417
|
const dbPath = tempDbPath();
|
|
388
418
|
openDatabase(dbPath);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime regression — `projectRoot()` throws `GSDNoProjectError` when
|
|
3
|
+
* invoked outside a project directory (#4902).
|
|
4
|
+
*
|
|
5
|
+
* The deleted `gsd-no-project-error.test.ts` was a source-grep check.
|
|
6
|
+
* This rewrite chdirs to $HOME, calls the real `projectRoot()`, and
|
|
7
|
+
* asserts a `GSDNoProjectError` is thrown with the project-required
|
|
8
|
+
* message.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, test, after } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import * as os from 'node:os';
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
|
|
17
|
+
import { projectRoot, GSDNoProjectError } from '../commands/context.ts';
|
|
18
|
+
|
|
19
|
+
const ORIGINAL_CWD = process.cwd();
|
|
20
|
+
|
|
21
|
+
after(() => {
|
|
22
|
+
try { process.chdir(ORIGINAL_CWD); } catch { /* swallow */ }
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('projectRoot() throws GSDNoProjectError outside a project (#4902)', () => {
|
|
26
|
+
test('throws GSDNoProjectError when cwd is $HOME', () => {
|
|
27
|
+
const home = os.homedir();
|
|
28
|
+
process.chdir(home);
|
|
29
|
+
try {
|
|
30
|
+
assert.throws(
|
|
31
|
+
() => projectRoot(),
|
|
32
|
+
(err: unknown) => {
|
|
33
|
+
assert.ok(err instanceof GSDNoProjectError, 'should throw GSDNoProjectError');
|
|
34
|
+
assert.match(
|
|
35
|
+
(err as Error).message,
|
|
36
|
+
/home directory|project directory/i,
|
|
37
|
+
'error message should mention home/project directory',
|
|
38
|
+
);
|
|
39
|
+
return true;
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
} finally {
|
|
43
|
+
process.chdir(ORIGINAL_CWD);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('throws GSDNoProjectError when cwd is the system tmpdir root', () => {
|
|
48
|
+
// Use realpath to dodge symlinks blocking the cwd
|
|
49
|
+
const tmpRoot = fs.realpathSync(os.tmpdir());
|
|
50
|
+
// Some systems make tmpdir a subdirectory; only run when it normalizes
|
|
51
|
+
// to a known-blocked root. validateDirectory blocks /tmp + /var/folders
|
|
52
|
+
// tmp roots; build a small subdir under tmp and then assert that the
|
|
53
|
+
// raw tmpdir root itself blocks. We just use it directly.
|
|
54
|
+
process.chdir(tmpRoot);
|
|
55
|
+
try {
|
|
56
|
+
// Behaviour: either we get a GSDNoProjectError (blocked tmpdir root) or
|
|
57
|
+
// we don't — but in the case where we don't (tmpdir is somehow allowed
|
|
58
|
+
// as a project root on this machine), the test is vacuously satisfied
|
|
59
|
+
// by the prior $HOME case. We assert the type-narrowing path instead:
|
|
60
|
+
let threw: unknown = null;
|
|
61
|
+
try { projectRoot(); } catch (err) { threw = err; }
|
|
62
|
+
if (threw !== null) {
|
|
63
|
+
assert.ok(
|
|
64
|
+
threw instanceof GSDNoProjectError,
|
|
65
|
+
'if projectRoot throws, it must be a GSDNoProjectError (typed)',
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
process.chdir(ORIGINAL_CWD);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('GSDNoProjectError shape (#4902)', () => {
|
|
75
|
+
test('GSDNoProjectError extends Error and carries its name', () => {
|
|
76
|
+
const err = new GSDNoProjectError('test reason');
|
|
77
|
+
assert.ok(err instanceof Error);
|
|
78
|
+
assert.equal(err.name, 'GSDNoProjectError');
|
|
79
|
+
assert.equal(err.message, 'test reason');
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* secrets, stats, and unused warnings).
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import test from 'node:test';
|
|
9
|
+
import test, { mock } from 'node:test';
|
|
10
10
|
import assert from 'node:assert/strict';
|
|
11
11
|
import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
12
12
|
import { join } from 'node:path';
|
|
@@ -164,7 +164,15 @@ test('tryHandle matches by question ID — single select', (t) => {
|
|
|
164
164
|
assert.strictEqual(injector.getStats().questionsAnswered, 1);
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
test('tryHandle unknown question deferred — first_option timeout',
|
|
167
|
+
test('tryHandle unknown question deferred — first_option timeout', (t) => {
|
|
168
|
+
// Use Node's MockTimers instead of a real-time setTimeout race. The
|
|
169
|
+
// production class schedules an internal setTimeout to default the
|
|
170
|
+
// answer when no metadata arrives — driving virtual time advances that
|
|
171
|
+
// timer deterministically, regardless of the literal ms value the
|
|
172
|
+
// production code chose.
|
|
173
|
+
mock.timers.enable({ apis: ['setTimeout'] });
|
|
174
|
+
t.after(() => { mock.timers.reset(); });
|
|
175
|
+
|
|
168
176
|
const injector = new AnswerInjector({ defaults: { strategy: 'first_option' } });
|
|
169
177
|
|
|
170
178
|
const captured: string[] = [];
|
|
@@ -177,8 +185,10 @@ test('tryHandle unknown question deferred — first_option timeout', async (t) =
|
|
|
177
185
|
assert.strictEqual(handled, true);
|
|
178
186
|
assert.strictEqual(captured.length, 0, 'nothing sent immediately');
|
|
179
187
|
|
|
180
|
-
//
|
|
181
|
-
|
|
188
|
+
// Advance virtual time past any internal defer timeout (well above any
|
|
189
|
+
// reasonable defer cap). MockTimers fires synchronously, so by the time
|
|
190
|
+
// tick() returns the deferred handler has run.
|
|
191
|
+
mock.timers.tick(60_000);
|
|
182
192
|
|
|
183
193
|
assert.strictEqual(captured.length, 1);
|
|
184
194
|
const response = JSON.parse(captured[0].trim());
|
|
@@ -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
|
+
});
|