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
|
@@ -16,11 +16,9 @@
|
|
|
16
16
|
|
|
17
17
|
import { describe, test, afterEach } from "node:test";
|
|
18
18
|
import assert from "node:assert/strict";
|
|
19
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync
|
|
19
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
20
20
|
import { join } from "node:path";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
|
-
import { fileURLToPath } from "node:url";
|
|
23
|
-
import { dirname } from "node:path";
|
|
24
22
|
|
|
25
23
|
import { deriveState } from "../state.ts";
|
|
26
24
|
import { invalidateAllCaches } from "../cache.ts";
|
|
@@ -57,12 +55,6 @@ function writeRoadmap(base: string, mid: string, content: string): void {
|
|
|
57
55
|
writeFileSync(join(base, ".gsd", "milestones", mid, `${mid}-ROADMAP.md`), content);
|
|
58
56
|
}
|
|
59
57
|
|
|
60
|
-
function readGuidedFlowSource(): string {
|
|
61
|
-
const thisFile = fileURLToPath(import.meta.url);
|
|
62
|
-
const thisDir = dirname(thisFile);
|
|
63
|
-
return readFileSync(join(thisDir, "..", "guided-flow.ts"), "utf-8");
|
|
64
|
-
}
|
|
65
|
-
|
|
66
58
|
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
67
59
|
|
|
68
60
|
describe("discuss-queued-milestones (#2307)", () => {
|
|
@@ -169,113 +161,10 @@ describe("discuss-queued-milestones (#2307)", () => {
|
|
|
169
161
|
}
|
|
170
162
|
});
|
|
171
163
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// return;
|
|
179
|
-
// }
|
|
180
|
-
//
|
|
181
|
-
// The new guard should check for pending milestones and route instead.
|
|
182
|
-
const oldGuardPattern = /if\s*\(!state\.activeMilestone\)\s*\{\s*ctx\.ui\.notify\("No active milestone/;
|
|
183
|
-
assert.ok(
|
|
184
|
-
!oldGuardPattern.test(source),
|
|
185
|
-
"guided-flow must not unconditionally exit when activeMilestone is null",
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("7. showDiscussQueuedMilestone helper exists in guided-flow", () => {
|
|
190
|
-
const source = readGuidedFlowSource();
|
|
191
|
-
assert.ok(
|
|
192
|
-
source.includes("showDiscussQueuedMilestone"),
|
|
193
|
-
"guided-flow must export showDiscussQueuedMilestone helper",
|
|
194
|
-
);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test("8. dispatchDiscussForMilestone helper exists in guided-flow", () => {
|
|
198
|
-
const source = readGuidedFlowSource();
|
|
199
|
-
assert.ok(
|
|
200
|
-
source.includes("dispatchDiscussForMilestone"),
|
|
201
|
-
"guided-flow must export dispatchDiscussForMilestone helper",
|
|
202
|
-
);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test("9. dispatchDiscussForMilestone does not set pendingAutoStart", () => {
|
|
206
|
-
const source = readGuidedFlowSource();
|
|
207
|
-
|
|
208
|
-
// Extract the dispatchDiscussForMilestone function body
|
|
209
|
-
const fnMatch = source.match(
|
|
210
|
-
/async function dispatchDiscussForMilestone\s*\([^)]*\)[^{]*\{([\s\S]*?)\n\}/,
|
|
211
|
-
);
|
|
212
|
-
assert.ok(!!fnMatch, "dispatchDiscussForMilestone function body must be present");
|
|
213
|
-
|
|
214
|
-
if (fnMatch) {
|
|
215
|
-
assert.ok(
|
|
216
|
-
!fnMatch[1].includes("pendingAutoStart"),
|
|
217
|
-
"dispatchDiscussForMilestone must NOT set pendingAutoStart — discussing a queued milestone must not activate it",
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
test("10. slice picker includes queued milestone option when pending milestones exist", () => {
|
|
223
|
-
const source = readGuidedFlowSource();
|
|
224
|
-
assert.ok(
|
|
225
|
-
source.includes("discuss_queued_milestone"),
|
|
226
|
-
"slice picker must include a 'discuss_queued_milestone' action id for queued milestones",
|
|
227
|
-
);
|
|
228
|
-
assert.ok(
|
|
229
|
-
source.includes("Discuss a queued milestone"),
|
|
230
|
-
"slice picker must label the queued milestone action clearly",
|
|
231
|
-
);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test("11. queued milestone picker labels entries with [queued]", () => {
|
|
235
|
-
const source = readGuidedFlowSource();
|
|
236
|
-
assert.ok(
|
|
237
|
-
source.includes("[queued]"),
|
|
238
|
-
"queued milestone picker must label entries with [queued] to distinguish from active",
|
|
239
|
-
);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
// ─── #3150: allDiscussed early-return must not block queued milestone discussion ──
|
|
243
|
-
|
|
244
|
-
test("12. allDiscussed path checks for pending milestones before returning (#3150)", () => {
|
|
245
|
-
const source = readGuidedFlowSource();
|
|
246
|
-
|
|
247
|
-
// Extract the allDiscussed block — the if (allDiscussed) { ... } body
|
|
248
|
-
const allDiscussedMatch = source.match(
|
|
249
|
-
/const allDiscussed = pendingSlices\.every\([\s\S]*?\n if \(allDiscussed\) \{([\s\S]*?)\n \}/,
|
|
250
|
-
);
|
|
251
|
-
assert.ok(!!allDiscussedMatch, "allDiscussed guard block must exist in showDiscuss()");
|
|
252
|
-
|
|
253
|
-
if (allDiscussedMatch) {
|
|
254
|
-
const body = allDiscussedMatch[1];
|
|
255
|
-
// The fix must check for pending milestones and route to showDiscussQueuedMilestone
|
|
256
|
-
assert.ok(
|
|
257
|
-
body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
|
|
258
|
-
"allDiscussed block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
test("13. pendingSlices.length===0 path checks for pending milestones before returning (#3150)", () => {
|
|
264
|
-
const source = readGuidedFlowSource();
|
|
265
|
-
|
|
266
|
-
// Find the pendingSlices.length === 0 guard block
|
|
267
|
-
const zeroSlicesMatch = source.match(
|
|
268
|
-
/if \(pendingSlices\.length === 0\) \{([\s\S]*?)\n \}/,
|
|
269
|
-
);
|
|
270
|
-
assert.ok(!!zeroSlicesMatch, "pendingSlices.length === 0 guard block must exist in showDiscuss()");
|
|
271
|
-
|
|
272
|
-
if (zeroSlicesMatch) {
|
|
273
|
-
const body = zeroSlicesMatch[1];
|
|
274
|
-
// The fix must check for pending milestones and route to showDiscussQueuedMilestone
|
|
275
|
-
assert.ok(
|
|
276
|
-
body.includes("pending") && body.includes("showDiscussQueuedMilestone"),
|
|
277
|
-
"pendingSlices.length===0 block must check for pending milestones and call showDiscussQueuedMilestone before returning (#3150)",
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
});
|
|
164
|
+
// The earlier tests 6-13 source-grepped guided-flow.ts for identifier
|
|
165
|
+
// names (showDiscussQueuedMilestone, dispatchDiscussForMilestone),
|
|
166
|
+
// UI-copy strings ("[queued]", "Discuss a queued milestone"), and
|
|
167
|
+
// regex-on-function-body assertions for the #3150 routing — all
|
|
168
|
+
// structural rather than behavioural (Refs #4826). They were dropped
|
|
169
|
+
// when this file was tightened against handler-level assertions.
|
|
281
170
|
});
|
|
@@ -1,77 +1,35 @@
|
|
|
1
|
-
// GSD-2 —
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* all extension tools even when cwd hasn't changed
|
|
16
|
-
*/
|
|
1
|
+
// GSD-2 — Behavioural regression test for #3616.
|
|
2
|
+
//
|
|
3
|
+
// Bug: After a discuss session narrows the active tool set via setActiveTools,
|
|
4
|
+
// the narrowed list persisted into the next auto-mode session because newSession()
|
|
5
|
+
// did not restore extension tools when cwd was unchanged. This caused
|
|
6
|
+
// gsd_plan_slice and other DB tools to be missing from plan-slice subagent
|
|
7
|
+
// sessions.
|
|
8
|
+
//
|
|
9
|
+
// The behavioural invariant we can pin without grepping source: gsd_plan_slice
|
|
10
|
+
// (a heavy planning tool) is NOT inside the discuss allowlist. The remaining
|
|
11
|
+
// guarantees (newSession including all extension tools in both branches) are
|
|
12
|
+
// covered by agent-session.test.ts inside packages/pi-coding-agent.
|
|
13
|
+
//
|
|
14
|
+
// Refs #4826 (rewrite from source-grep on guided-flow.ts / agent-session.ts).
|
|
17
15
|
|
|
18
16
|
import { describe, test } from "node:test";
|
|
19
17
|
import assert from "node:assert/strict";
|
|
20
|
-
import { readFileSync } from "node:fs";
|
|
21
|
-
import { join, dirname } from "node:path";
|
|
22
|
-
import { fileURLToPath } from "node:url";
|
|
23
18
|
|
|
24
19
|
import { DISCUSS_TOOLS_ALLOWLIST } from "../constants.ts";
|
|
25
|
-
import { extractSourceRegion } from "./test-helpers.ts";
|
|
26
|
-
|
|
27
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
-
const guidedFlowSource = readFileSync(join(__dirname, "..", "guided-flow.ts"), "utf-8");
|
|
29
20
|
|
|
30
21
|
describe("#3616 — discuss tool scoping must not leak across sessions", () => {
|
|
31
22
|
test("gsd_plan_slice is NOT in DISCUSS_TOOLS_ALLOWLIST", () => {
|
|
32
23
|
assert.ok(
|
|
33
24
|
!DISCUSS_TOOLS_ALLOWLIST.includes("gsd_plan_slice"),
|
|
34
|
-
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("tool scoping only activates for discuss-* unit types", () => {
|
|
39
|
-
// The guard must be: if (unitType?.startsWith("discuss-"))
|
|
40
|
-
assert.ok(
|
|
41
|
-
guidedFlowSource.includes('unitType?.startsWith("discuss-")'),
|
|
42
|
-
"tool scoping should only trigger for discuss-* unit types",
|
|
25
|
+
`gsd_plan_slice (a heavy planning tool) must be excluded from the discuss scope; allowlist=${JSON.stringify(DISCUSS_TOOLS_ALLOWLIST)}`,
|
|
43
26
|
);
|
|
44
27
|
});
|
|
45
28
|
|
|
46
|
-
test("
|
|
47
|
-
// setActiveTools changes the active subset but doesn't remove tools from
|
|
48
|
-
// the registry. newSession()'s _refreshToolRegistry can restore them.
|
|
49
|
-
assert.ok(
|
|
50
|
-
guidedFlowSource.includes("pi.setActiveTools(scopedTools)"),
|
|
51
|
-
"should use pi.setActiveTools to narrow tools (preserving registry)",
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("newSession() in agent-session.ts has defense against tool narrowing persistence", () => {
|
|
56
|
-
const agentSessionSource = readFileSync(
|
|
57
|
-
join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
|
|
58
|
-
"utf-8",
|
|
59
|
-
);
|
|
60
|
-
const newSessionStart = agentSessionSource.indexOf("async newSession(options?:");
|
|
61
|
-
assert.ok(newSessionStart >= 0, "should find newSession");
|
|
62
|
-
const body = extractSourceRegion(agentSessionSource, "async newSession(options?:");
|
|
63
|
-
|
|
64
|
-
// Both branches (cwd-changed and cwd-unchanged) must include extension tools
|
|
65
|
-
assert.ok(
|
|
66
|
-
body.includes("includeAllExtensionTools: true"),
|
|
67
|
-
"newSession() must include all extension tools in both branches",
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
// Count occurrences — should be at least 2 (one per branch)
|
|
71
|
-
const matches = body.match(/includeAllExtensionTools:\s*true/g);
|
|
29
|
+
test("DISCUSS_TOOLS_ALLOWLIST is non-empty (sanity)", () => {
|
|
72
30
|
assert.ok(
|
|
73
|
-
|
|
74
|
-
|
|
31
|
+
DISCUSS_TOOLS_ALLOWLIST.length > 0,
|
|
32
|
+
"discuss scope should include at least one tool — empty allowlist would break /gsd discuss",
|
|
75
33
|
);
|
|
76
34
|
});
|
|
77
35
|
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// GSD Extension — Regression test for #4996: doctor orphan milestone dir check
|
|
2
|
+
// Verifies that checkRuntimeHealth reports orphan_milestone_dir for empty stub
|
|
3
|
+
// dirs with no DB row, does not report populated dirs, and does not report
|
|
4
|
+
// legitimate in-flight worktree-only milestone dirs.
|
|
5
|
+
|
|
6
|
+
import { describe, it, afterEach } from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { tmpdir } from "node:os";
|
|
11
|
+
|
|
12
|
+
import { checkRuntimeHealth } from "../doctor-runtime-checks.ts";
|
|
13
|
+
import {
|
|
14
|
+
openDatabase,
|
|
15
|
+
closeDatabase,
|
|
16
|
+
insertMilestone,
|
|
17
|
+
} from "../gsd-db.ts";
|
|
18
|
+
import { invalidateAllCaches } from "../cache.ts";
|
|
19
|
+
import type { DoctorIssue, DoctorIssueCode } from "../doctor-types.ts";
|
|
20
|
+
|
|
21
|
+
function makeBase(prefix = "gsd-doctor-orphan-"): string {
|
|
22
|
+
const base = mkdtempSync(join(tmpdir(), prefix));
|
|
23
|
+
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
24
|
+
return base;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function stubDir(base: string, mid: string): void {
|
|
28
|
+
mkdirSync(join(base, ".gsd", "milestones", mid, "slices"), { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function populateDir(base: string, mid: string): void {
|
|
32
|
+
mkdirSync(join(base, ".gsd", "milestones", mid), { recursive: true });
|
|
33
|
+
writeFileSync(join(base, ".gsd", "milestones", mid, `${mid}-CONTEXT.md`), `# ${mid}\n`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("gsd_doctor orphan milestone directory check (#4996)", () => {
|
|
37
|
+
let base: string;
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
try { closeDatabase(); } catch { /* ignore */ }
|
|
41
|
+
try { invalidateAllCaches(); } catch { /* ignore */ }
|
|
42
|
+
try { rmSync(base, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("(a) empty stub dir with no DB row is reported as orphan_milestone_dir", async () => {
|
|
46
|
+
base = makeBase();
|
|
47
|
+
stubDir(base, "M003");
|
|
48
|
+
|
|
49
|
+
const issues: DoctorIssue[] = [];
|
|
50
|
+
const fixes: string[] = [];
|
|
51
|
+
await checkRuntimeHealth(base, issues, fixes, () => false);
|
|
52
|
+
|
|
53
|
+
const orphan = issues.find(i => i.code === "orphan_milestone_dir" && i.unitId === "M003");
|
|
54
|
+
assert.ok(orphan, "should report orphan_milestone_dir for empty stub");
|
|
55
|
+
assert.equal(orphan?.severity, "warning");
|
|
56
|
+
assert.equal(orphan?.fixable, true);
|
|
57
|
+
assert.ok(orphan?.message.includes("M003"), "message should name the milestone");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("(b) populated milestone dir is NOT reported", async () => {
|
|
61
|
+
base = makeBase();
|
|
62
|
+
populateDir(base, "M001");
|
|
63
|
+
|
|
64
|
+
const issues: DoctorIssue[] = [];
|
|
65
|
+
const fixes: string[] = [];
|
|
66
|
+
await checkRuntimeHealth(base, issues, fixes, () => false);
|
|
67
|
+
|
|
68
|
+
const orphan = issues.find(i => i.code === "orphan_milestone_dir" && i.unitId === "M001");
|
|
69
|
+
assert.ok(!orphan, "populated milestone dir must not be reported as orphan");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("(c) worktree-only milestone (no content files, no DB row, but worktree exists) is NOT reported", async () => {
|
|
73
|
+
base = makeBase();
|
|
74
|
+
stubDir(base, "M003");
|
|
75
|
+
// Simulate a legitimate in-flight worktree
|
|
76
|
+
mkdirSync(join(base, ".gsd", "worktrees", "M003"), { recursive: true });
|
|
77
|
+
|
|
78
|
+
const issues: DoctorIssue[] = [];
|
|
79
|
+
const fixes: string[] = [];
|
|
80
|
+
await checkRuntimeHealth(base, issues, fixes, () => false);
|
|
81
|
+
|
|
82
|
+
const orphan = issues.find(i => i.code === "orphan_milestone_dir" && i.unitId === "M003");
|
|
83
|
+
assert.ok(!orphan, "milestone with a worktree must not be reported as orphan");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("(d) queued DB row (in-flight ID) is NOT reported as orphan", async () => {
|
|
87
|
+
base = makeBase();
|
|
88
|
+
stubDir(base, "M003");
|
|
89
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
90
|
+
openDatabase(dbPath);
|
|
91
|
+
insertMilestone({ id: "M003", status: "queued" });
|
|
92
|
+
|
|
93
|
+
const issues: DoctorIssue[] = [];
|
|
94
|
+
const fixes: string[] = [];
|
|
95
|
+
await checkRuntimeHealth(base, issues, fixes, () => false);
|
|
96
|
+
|
|
97
|
+
const orphan = issues.find(i => i.code === "orphan_milestone_dir" && i.unitId === "M003");
|
|
98
|
+
assert.ok(!orphan, "queued DB row must block orphan report (in-flight race protection)");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,82 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavioural regression test for #2645 — double mergeAndExit guard.
|
|
3
|
+
*
|
|
4
|
+
* AutoSession.milestoneMergedInPhases is the producer-side flag set by the
|
|
5
|
+
* "complete" / "all-milestones-complete" branches in phases.ts after they
|
|
6
|
+
* call mergeAndExit. stopAuto reads it to skip the redundant Step-4 merge
|
|
7
|
+
* (which previously failed because the branch was already deleted).
|
|
8
|
+
*
|
|
9
|
+
* Refs #4829 (rewrite from positional source-grep on phases.ts/auto.ts).
|
|
10
|
+
*/
|
|
11
|
+
|
|
1
12
|
import { describe, test } from "node:test";
|
|
2
13
|
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { join, dirname } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
14
|
import { AutoSession } from "../auto/session.ts";
|
|
7
|
-
import { extractSourceRegion } from "./test-helpers.ts";
|
|
8
|
-
|
|
9
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
|
|
11
|
-
describe("double mergeAndExit guard (#2645)", () => {
|
|
12
|
-
test("phases.ts sets milestoneMergedInPhases after mergeAndExit in milestone-complete path", () => {
|
|
13
|
-
// Source audit: the "complete" phase path must set the guard flag
|
|
14
|
-
// after calling mergeAndExit so that stopAuto skips the second merge.
|
|
15
|
-
const phasesSrc = readFileSync(
|
|
16
|
-
join(__dirname, "..", "auto", "phases.ts"),
|
|
17
|
-
"utf-8",
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
// Find the "complete" phase block
|
|
21
|
-
const completeIdx = phasesSrc.indexOf('state.phase === "complete"');
|
|
22
|
-
assert.ok(completeIdx > 0, "phases.ts should have a 'complete' phase check");
|
|
23
|
-
|
|
24
|
-
const afterComplete = extractSourceRegion(phasesSrc, 'state.phase === "complete"');
|
|
25
|
-
const mergeIdx = afterComplete.indexOf("deps.resolver.mergeAndExit");
|
|
26
|
-
const flagIdx = afterComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
27
|
-
|
|
28
|
-
assert.ok(mergeIdx > 0, "complete path should call mergeAndExit");
|
|
29
|
-
assert.ok(flagIdx > 0, "complete path should set milestoneMergedInPhases");
|
|
30
|
-
assert.ok(
|
|
31
|
-
flagIdx > mergeIdx,
|
|
32
|
-
"milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("phases.ts sets milestoneMergedInPhases after mergeAndExit in all-milestones-complete path", () => {
|
|
37
|
-
const phasesSrc = readFileSync(
|
|
38
|
-
join(__dirname, "..", "auto", "phases.ts"),
|
|
39
|
-
"utf-8",
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
// The "all milestones complete" block checks incomplete.length === 0
|
|
43
|
-
const allCompleteIdx = phasesSrc.indexOf("incomplete.length === 0");
|
|
44
|
-
assert.ok(allCompleteIdx > 0, "phases.ts should have an all-milestones-complete check");
|
|
45
|
-
|
|
46
|
-
const afterAllComplete = extractSourceRegion(phasesSrc, "incomplete.length === 0");
|
|
47
|
-
const mergeIdx = afterAllComplete.indexOf("deps.resolver.mergeAndExit");
|
|
48
|
-
const flagIdx = afterAllComplete.indexOf("s.milestoneMergedInPhases = true");
|
|
49
|
-
|
|
50
|
-
assert.ok(mergeIdx > 0, "all-complete path should call mergeAndExit");
|
|
51
|
-
assert.ok(flagIdx > 0, "all-complete path should set milestoneMergedInPhases");
|
|
52
|
-
assert.ok(
|
|
53
|
-
flagIdx > mergeIdx,
|
|
54
|
-
"milestoneMergedInPhases must be set AFTER mergeAndExit (not before)",
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test("stopAuto checks milestoneMergedInPhases before calling mergeAndExit", () => {
|
|
59
|
-
const autoSrc = readFileSync(
|
|
60
|
-
join(__dirname, "..", "auto.ts"),
|
|
61
|
-
"utf-8",
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
// The Step 4 worktree exit block must check the guard flag
|
|
65
|
-
const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
|
|
66
|
-
assert.ok(step4Idx > 0, "auto.ts should have Step 4 worktree exit");
|
|
67
|
-
|
|
68
|
-
const step4Block = extractSourceRegion(autoSrc, "Step 4: Auto-worktree exit");
|
|
69
|
-
assert.ok(
|
|
70
|
-
step4Block.includes("milestoneMergedInPhases"),
|
|
71
|
-
"stopAuto Step 4 must check milestoneMergedInPhases before merging",
|
|
72
|
-
);
|
|
73
|
-
assert.ok(
|
|
74
|
-
step4Block.includes("!s.milestoneMergedInPhases"),
|
|
75
|
-
"stopAuto should skip merge when milestoneMergedInPhases is true",
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
15
|
|
|
79
|
-
|
|
16
|
+
describe("AutoSession.milestoneMergedInPhases (#2645)", () => {
|
|
17
|
+
test("defaults to false on a fresh session", () => {
|
|
80
18
|
const session = new AutoSession();
|
|
81
19
|
assert.equal(
|
|
82
20
|
session.milestoneMergedInPhases,
|
|
@@ -85,7 +23,7 @@ describe("double mergeAndExit guard (#2645)", () => {
|
|
|
85
23
|
);
|
|
86
24
|
});
|
|
87
25
|
|
|
88
|
-
test("
|
|
26
|
+
test("reset() clears the flag back to false", () => {
|
|
89
27
|
const session = new AutoSession();
|
|
90
28
|
session.milestoneMergedInPhases = true;
|
|
91
29
|
session.reset();
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// GSD Extension — Regression test for #4996: ensurePreconditions phantom dir guard
|
|
2
|
+
// Verifies that ensurePreconditions does not create milestone directories for
|
|
3
|
+
// forward-referenced slice unit IDs when the milestone has no DB row.
|
|
4
|
+
|
|
5
|
+
import { describe, it, afterEach } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
|
|
11
|
+
import { ensurePreconditions } from "../auto.ts";
|
|
12
|
+
import {
|
|
13
|
+
openDatabase,
|
|
14
|
+
closeDatabase,
|
|
15
|
+
insertMilestone,
|
|
16
|
+
} from "../gsd-db.ts";
|
|
17
|
+
|
|
18
|
+
import type { GSDState } from "../types.ts";
|
|
19
|
+
|
|
20
|
+
function makeBase(prefix = "gsd-precond-"): string {
|
|
21
|
+
const base = mkdtempSync(join(tmpdir(), prefix));
|
|
22
|
+
mkdirSync(join(base, ".gsd", "milestones"), { recursive: true });
|
|
23
|
+
return base;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function makeMinimalState(): GSDState {
|
|
27
|
+
return {
|
|
28
|
+
activeMilestone: null,
|
|
29
|
+
activeSlice: null,
|
|
30
|
+
activeTask: null,
|
|
31
|
+
phase: "planning",
|
|
32
|
+
recentDecisions: [],
|
|
33
|
+
blockers: [],
|
|
34
|
+
nextAction: "",
|
|
35
|
+
registry: [],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe("ensurePreconditions phantom-dir guard (#4996)", () => {
|
|
40
|
+
let base: string;
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
try { closeDatabase(); } catch { /* ignore */ }
|
|
44
|
+
try { rmSync(base, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("(a) slice unit ID for unknown milestone does NOT create dirs when no DB row exists", () => {
|
|
48
|
+
base = makeBase();
|
|
49
|
+
const state = makeMinimalState();
|
|
50
|
+
|
|
51
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
52
|
+
|
|
53
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
54
|
+
assert.ok(!existsSync(milestoneDir), "M003 dir must not be created for phantom slice dispatch");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("(b) slice unit ID for milestone with DB row DOES create dirs", () => {
|
|
58
|
+
base = makeBase();
|
|
59
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
60
|
+
openDatabase(dbPath);
|
|
61
|
+
insertMilestone({ id: "M003", status: "active" });
|
|
62
|
+
const state = makeMinimalState();
|
|
63
|
+
|
|
64
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
65
|
+
|
|
66
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
67
|
+
assert.ok(existsSync(milestoneDir), "M003 dir must be created when DB row exists");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("(c) slice unit ID for existing milestone dir with CONTEXT.md content file uses normal scaffolding", () => {
|
|
71
|
+
base = makeBase();
|
|
72
|
+
const mid = "M003";
|
|
73
|
+
const milestoneDir = join(base, ".gsd", "milestones", mid);
|
|
74
|
+
mkdirSync(milestoneDir, { recursive: true });
|
|
75
|
+
writeFileSync(join(milestoneDir, `${mid}-CONTEXT.md`), "# Context\n");
|
|
76
|
+
const state = makeMinimalState();
|
|
77
|
+
|
|
78
|
+
ensurePreconditions("execute-task", "M003/S01", base, state);
|
|
79
|
+
|
|
80
|
+
const slicesDir = join(milestoneDir, "slices");
|
|
81
|
+
assert.ok(existsSync(slicesDir), "existing milestone dir should allow slice scaffolding");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("(d) milestone-only unit ID (no slice) still creates dir even with no DB row", () => {
|
|
85
|
+
base = makeBase();
|
|
86
|
+
const state = makeMinimalState();
|
|
87
|
+
|
|
88
|
+
ensurePreconditions("discuss-milestone", "M003", base, state);
|
|
89
|
+
|
|
90
|
+
const milestoneDir = join(base, ".gsd", "milestones", "M003");
|
|
91
|
+
assert.ok(existsSync(milestoneDir), "M003 dir must be created for milestone-only dispatch");
|
|
92
|
+
});
|
|
93
|
+
});
|