gsd-pi 2.80.0-dev.42bd34838 → 2.80.0-dev.488219eb6
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/dist/claude-cli-check.d.ts +30 -0
- package/dist/claude-cli-check.js +18 -7
- package/dist/cli.js +0 -19
- package/dist/headless-query.d.ts +10 -0
- package/dist/headless-query.js +6 -4
- package/dist/loader-entrypoint.d.ts +8 -0
- package/dist/loader-entrypoint.js +27 -0
- package/dist/loader.js +2 -11
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +6 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
- package/dist/resources/extensions/github-sync/sync.js +4 -1
- package/dist/resources/extensions/gsd/auto/loop.js +71 -8
- package/dist/resources/extensions/gsd/auto/phases.js +179 -99
- package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +94 -76
- package/dist/resources/extensions/gsd/auto-prompts.js +90 -15
- package/dist/resources/extensions/gsd/auto-start.js +238 -12
- package/dist/resources/extensions/gsd/auto-worktree.js +209 -81
- package/dist/resources/extensions/gsd/auto.js +95 -44
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +96 -26
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +44 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -10
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -3
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -3
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +298 -54
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-config.js +1 -1
- package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +37 -1
- package/dist/resources/extensions/gsd/guided-flow.js +61 -32
- package/dist/resources/extensions/gsd/init-wizard.js +4 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +8 -4
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
- package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +57 -5
- package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- 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/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 +11 -11
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- 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/static/chunks/8359.e059d86b255fce1c.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +9 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +8 -0
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +14 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +35 -13
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +9 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
- package/packages/pi-ai/src/providers/anthropic.ts +22 -9
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +36 -7
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +3 -6
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +3 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +34 -3
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js +22 -56
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
- package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
- package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +5 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +153 -8
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +18 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +23 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +19 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +23 -5
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +40 -7
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +3 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +5 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +37 -2
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
- package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
- package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
- package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
- package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
- package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +177 -8
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +24 -5
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +21 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +25 -8
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
- package/src/resources/extensions/github-sync/sync.ts +8 -1
- package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/loop.ts +84 -8
- package/src/resources/extensions/gsd/auto/phases.ts +258 -159
- package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -29
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +107 -78
- package/src/resources/extensions/gsd/auto-prompts.ts +95 -14
- package/src/resources/extensions/gsd/auto-start.ts +286 -15
- package/src/resources/extensions/gsd/auto-worktree.ts +241 -72
- package/src/resources/extensions/gsd/auto.ts +132 -40
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +116 -24
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +45 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +36 -10
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -3
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +7 -4
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +6 -3
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +347 -54
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +4 -2
- package/src/resources/extensions/gsd/commands-config.ts +1 -1
- package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/git-service.ts +41 -2
- package/src/resources/extensions/gsd/guided-flow.ts +71 -39
- package/src/resources/extensions/gsd/init-wizard.ts +5 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +8 -4
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +361 -10
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +159 -213
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
- package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
- package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +35 -31
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +2 -20
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
- package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -56
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +44 -6
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +24 -37
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +91 -75
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -125
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -69
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -97
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +33 -47
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +84 -309
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -99
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +140 -3
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
- package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +83 -5
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
- package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
- /package/dist/web/standalone/.next/static/{tht0ltP8EIjsohPOA_WZf → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tht0ltP8EIjsohPOA_WZf → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// GSD-2 + src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts
|
|
2
|
+
// Regression: bootstrap must actively merge orphan completed-but-unmerged
|
|
3
|
+
// milestones, not just seed `s.currentMilestoneId` (the seed approach was
|
|
4
|
+
// silently overwritten at auto-start.ts:948 — caught in audit of PR #5549).
|
|
5
|
+
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
|
|
9
|
+
import { _mergeOrphanCompletedMilestone } from "../auto-start.js";
|
|
10
|
+
import type { WorktreeResolver } from "../worktree-resolver.js";
|
|
11
|
+
|
|
12
|
+
interface FakeResolverState {
|
|
13
|
+
mergeCalls: Array<{ milestoneId: string }>;
|
|
14
|
+
shouldThrow?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fakeResolver(state: FakeResolverState): WorktreeResolver {
|
|
18
|
+
return {
|
|
19
|
+
mergeAndExit: (milestoneId: string) => {
|
|
20
|
+
state.mergeCalls.push({ milestoneId });
|
|
21
|
+
if (state.shouldThrow) throw state.shouldThrow;
|
|
22
|
+
},
|
|
23
|
+
} as unknown as WorktreeResolver;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface FakeUiState {
|
|
27
|
+
notifications: Array<{ message: string; level: string }>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function fakeUi(state: FakeUiState): {
|
|
31
|
+
notify: (msg: string, level?: "info" | "warning" | "error" | "success") => void;
|
|
32
|
+
} {
|
|
33
|
+
return {
|
|
34
|
+
notify: (message: string, level?: "info" | "warning" | "error" | "success") => {
|
|
35
|
+
state.notifications.push({ message, level: level ?? "info" });
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
test("happy path: orphan merge runs, returns merged:true, emits info notify", () => {
|
|
41
|
+
const resolverState: FakeResolverState = { mergeCalls: [] };
|
|
42
|
+
const uiState: FakeUiState = { notifications: [] };
|
|
43
|
+
const result = _mergeOrphanCompletedMilestone(
|
|
44
|
+
fakeResolver(resolverState),
|
|
45
|
+
"M002",
|
|
46
|
+
fakeUi(uiState),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
assert.deepEqual(result, { merged: true });
|
|
50
|
+
assert.deepEqual(resolverState.mergeCalls, [{ milestoneId: "M002" }]);
|
|
51
|
+
assert.equal(uiState.notifications.length, 1);
|
|
52
|
+
assert.deepEqual(uiState.notifications[0], {
|
|
53
|
+
message: "Detected unmerged completed milestone M002. Merging now.",
|
|
54
|
+
level: "info",
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("regression: mergeAndExit throwing (e.g. wrong-branch from PR #5549 commit 5) does not bubble out", () => {
|
|
59
|
+
// Commit 5 (68ef58a3c) made `_mergeBranchMode` throw on wrong branch
|
|
60
|
+
// instead of silently returning false. If `_mergeOrphanCompletedMilestone`
|
|
61
|
+
// didn't catch the throw, bootstrap would surface an unhandled exception
|
|
62
|
+
// to the slash-command caller — the exact regression risk that motivated
|
|
63
|
+
// wrapping in try/catch.
|
|
64
|
+
const boom = new Error("dirty working tree blocks checkout");
|
|
65
|
+
const resolverState: FakeResolverState = { mergeCalls: [], shouldThrow: boom };
|
|
66
|
+
const uiState: FakeUiState = { notifications: [] };
|
|
67
|
+
|
|
68
|
+
const result = _mergeOrphanCompletedMilestone(
|
|
69
|
+
fakeResolver(resolverState),
|
|
70
|
+
"M002",
|
|
71
|
+
fakeUi(uiState),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
assert.equal(result.merged, false);
|
|
75
|
+
assert.equal(result.error, boom);
|
|
76
|
+
|
|
77
|
+
// First notify announces the merge attempt; second notify reports the failure.
|
|
78
|
+
assert.equal(uiState.notifications.length, 2);
|
|
79
|
+
assert.equal(uiState.notifications[0].level, "info");
|
|
80
|
+
assert.equal(uiState.notifications[1].level, "warning");
|
|
81
|
+
assert.match(
|
|
82
|
+
uiState.notifications[1].message,
|
|
83
|
+
/Could not merge orphan milestone M002/,
|
|
84
|
+
);
|
|
85
|
+
assert.match(uiState.notifications[1].message, /dirty working tree blocks checkout/);
|
|
86
|
+
assert.match(uiState.notifications[1].message, /Resolve manually/);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("non-Error thrown values are still captured and notified", () => {
|
|
90
|
+
// Defensive: thrown strings, numbers, etc. must not crash the formatter.
|
|
91
|
+
const resolverState: FakeResolverState = {
|
|
92
|
+
mergeCalls: [],
|
|
93
|
+
// mimic a thrown non-Error value
|
|
94
|
+
shouldThrow: "git lock held",
|
|
95
|
+
};
|
|
96
|
+
const uiState: FakeUiState = { notifications: [] };
|
|
97
|
+
|
|
98
|
+
const result = _mergeOrphanCompletedMilestone(
|
|
99
|
+
fakeResolver(resolverState),
|
|
100
|
+
"M002",
|
|
101
|
+
fakeUi(uiState),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
assert.equal(result.merged, false);
|
|
105
|
+
assert.equal(result.error, resolverState.shouldThrow);
|
|
106
|
+
assert.equal(uiState.notifications[1].level, "warning");
|
|
107
|
+
assert.match(uiState.notifications[1].message, /git lock held/);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("the mergeAndExit call receives a notify-bound NotifyCtx the resolver can invoke", () => {
|
|
111
|
+
// The resolver's NotifyCtx must be wired to ui.notify so user-facing
|
|
112
|
+
// messages from inside mergeAndExit (e.g. "Milestone Mxxx merged") still
|
|
113
|
+
// reach the UI. Verify by having the fake resolver invoke the ctx.notify.
|
|
114
|
+
const uiState: FakeUiState = { notifications: [] };
|
|
115
|
+
const ui = fakeUi(uiState);
|
|
116
|
+
|
|
117
|
+
const resolver = {
|
|
118
|
+
mergeAndExit: (_milestoneId: string, ctx: { notify: (msg: string, level?: "info" | "warning" | "error" | "success") => void }) => {
|
|
119
|
+
ctx.notify("inner success message", "success");
|
|
120
|
+
},
|
|
121
|
+
} as unknown as WorktreeResolver;
|
|
122
|
+
|
|
123
|
+
const result = _mergeOrphanCompletedMilestone(resolver, "M002", ui);
|
|
124
|
+
|
|
125
|
+
assert.equal(result.merged, true);
|
|
126
|
+
// 1: outer "Detected unmerged completed milestone..."
|
|
127
|
+
// 2: inner "inner success message" emitted via the bound ctx.notify
|
|
128
|
+
assert.equal(uiState.notifications.length, 2);
|
|
129
|
+
assert.deepEqual(uiState.notifications[1], {
|
|
130
|
+
message: "inner success message",
|
|
131
|
+
level: "success",
|
|
132
|
+
});
|
|
133
|
+
});
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// GSD-2 + src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts
|
|
2
|
+
// Regression: orphaned gsd-preflight-stash entries from completed milestones
|
|
3
|
+
// must be auto-applied at startup so the user's pre-merge work returns.
|
|
4
|
+
|
|
5
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
import { mkdtempSync, rmSync, writeFileSync, readFileSync, existsSync } from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
auditOrphanedPreflightStashes,
|
|
14
|
+
_isAlreadyRestoredApplyError,
|
|
15
|
+
} from "../orphan-stash-audit.js";
|
|
16
|
+
|
|
17
|
+
function git(cwd: string, ...args: string[]): string {
|
|
18
|
+
return execFileSync("git", args, {
|
|
19
|
+
cwd,
|
|
20
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
21
|
+
encoding: "utf-8",
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
25
|
+
GIT_AUTHOR_NAME: "test",
|
|
26
|
+
GIT_AUTHOR_EMAIL: "test@example.com",
|
|
27
|
+
GIT_COMMITTER_NAME: "test",
|
|
28
|
+
GIT_COMMITTER_EMAIL: "test@example.com",
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function pushPreflightStash(repo: string, milestoneId: string, fileName: string, content: string): string {
|
|
34
|
+
writeFileSync(join(repo, fileName), content);
|
|
35
|
+
const marker = `gsd-preflight-stash:${milestoneId}:42:1700000000000:abcd`;
|
|
36
|
+
git(repo, "stash", "push", "--include-untracked", "-m", `gsd-preflight-stash [${marker}]`);
|
|
37
|
+
return marker;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe("auditOrphanedPreflightStashes", () => {
|
|
41
|
+
let repo: string;
|
|
42
|
+
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
repo = mkdtempSync(join(tmpdir(), "orphan-stash-audit-"));
|
|
45
|
+
git(repo, "init", "-q");
|
|
46
|
+
git(repo, "config", "user.email", "test@example.com");
|
|
47
|
+
git(repo, "config", "user.name", "test");
|
|
48
|
+
writeFileSync(join(repo, "seed.txt"), "seed\n");
|
|
49
|
+
git(repo, "add", "seed.txt");
|
|
50
|
+
git(repo, "commit", "-q", "-m", "initial");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
if (repo && existsSync(repo)) {
|
|
55
|
+
rmSync(repo, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("returns empty result when there are no stashes", () => {
|
|
60
|
+
const result = auditOrphanedPreflightStashes(repo, () => true);
|
|
61
|
+
assert.deepEqual(result, { applied: [], warnings: [] });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("applies an orphan preflight stash when its milestone is complete", () => {
|
|
65
|
+
pushPreflightStash(repo, "M002", "leftover.txt", "lost work\n");
|
|
66
|
+
|
|
67
|
+
// Verify the file is gone (stashed away) before the audit runs.
|
|
68
|
+
assert.equal(existsSync(join(repo, "leftover.txt")), false, "stash push must remove the file");
|
|
69
|
+
|
|
70
|
+
const result = auditOrphanedPreflightStashes(repo, (id) => id === "M002");
|
|
71
|
+
|
|
72
|
+
assert.equal(result.applied.length, 1, "expected exactly one stash applied");
|
|
73
|
+
assert.equal(result.applied[0].milestoneId, "M002");
|
|
74
|
+
assert.match(result.applied[0].stashRef, /^stash@\{\d+\}$/);
|
|
75
|
+
assert.equal(result.warnings.length, 0);
|
|
76
|
+
|
|
77
|
+
// The user's pre-merge content must be back in the working tree.
|
|
78
|
+
assert.equal(existsSync(join(repo, "leftover.txt")), true);
|
|
79
|
+
assert.equal(readFileSync(join(repo, "leftover.txt"), "utf-8"), "lost work\n");
|
|
80
|
+
|
|
81
|
+
// The stash entry must remain (apply, not pop) so the user has a backup.
|
|
82
|
+
const list = git(repo, "stash", "list");
|
|
83
|
+
assert.match(list, /gsd-preflight-stash:M002:/);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("ignores stashes whose milestone is not complete", () => {
|
|
87
|
+
pushPreflightStash(repo, "M003", "wip.txt", "still-working\n");
|
|
88
|
+
|
|
89
|
+
const result = auditOrphanedPreflightStashes(repo, () => false);
|
|
90
|
+
|
|
91
|
+
assert.deepEqual(result, { applied: [], warnings: [] });
|
|
92
|
+
// File stays stashed.
|
|
93
|
+
assert.equal(existsSync(join(repo, "wip.txt")), false);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("ignores non-gsd stash entries", () => {
|
|
97
|
+
writeFileSync(join(repo, "manual.txt"), "manual\n");
|
|
98
|
+
git(repo, "stash", "push", "--include-untracked", "-m", "user manual stash");
|
|
99
|
+
|
|
100
|
+
const result = auditOrphanedPreflightStashes(repo, () => true);
|
|
101
|
+
|
|
102
|
+
assert.deepEqual(result, { applied: [], warnings: [] });
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("collects a warning when the completion callback throws", () => {
|
|
106
|
+
pushPreflightStash(repo, "M004", "danger.txt", "boom\n");
|
|
107
|
+
|
|
108
|
+
const result = auditOrphanedPreflightStashes(repo, () => {
|
|
109
|
+
throw new Error("db unavailable");
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
assert.equal(result.applied.length, 0);
|
|
113
|
+
assert.equal(result.warnings.length, 1);
|
|
114
|
+
assert.match(result.warnings[0], /Could not determine completion status for M004/);
|
|
115
|
+
assert.match(result.warnings[0], /db unavailable/);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("collects a warning when stash apply fails (conflicting working tree)", () => {
|
|
119
|
+
// Push a stash containing a change to seed.txt; then dirty seed.txt with
|
|
120
|
+
// a conflicting modification before the audit runs so apply fails.
|
|
121
|
+
writeFileSync(join(repo, "seed.txt"), "stashed\n");
|
|
122
|
+
const marker = `gsd-preflight-stash:M005:42:1700:zz`;
|
|
123
|
+
git(repo, "stash", "push", "-m", `gsd-preflight-stash [${marker}]`);
|
|
124
|
+
|
|
125
|
+
// Dirty the working tree so apply will conflict.
|
|
126
|
+
writeFileSync(join(repo, "seed.txt"), "conflicting modification\n");
|
|
127
|
+
|
|
128
|
+
const result = auditOrphanedPreflightStashes(repo, () => true);
|
|
129
|
+
|
|
130
|
+
assert.equal(result.applied.length, 0);
|
|
131
|
+
assert.equal(result.warnings.length, 1);
|
|
132
|
+
assert.match(result.warnings[0], /Could not apply orphaned preflight stash/);
|
|
133
|
+
assert.match(result.warnings[0], /M005/);
|
|
134
|
+
assert.match(result.warnings[0], /git stash apply/);
|
|
135
|
+
|
|
136
|
+
const list = git(repo, "stash", "list");
|
|
137
|
+
assert.match(list, /gsd-preflight-stash:M005:/);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("returns empty result when basePath is not a git repo", () => {
|
|
141
|
+
const nonRepo = mkdtempSync(join(tmpdir(), "orphan-stash-not-repo-"));
|
|
142
|
+
try {
|
|
143
|
+
const result = auditOrphanedPreflightStashes(nonRepo, () => true);
|
|
144
|
+
assert.deepEqual(result, { applied: [], warnings: [] });
|
|
145
|
+
} finally {
|
|
146
|
+
rmSync(nonRepo, { recursive: true, force: true });
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("repeat run is a silent no-op when files were already restored (peer-review regression)", () => {
|
|
151
|
+
// Codex peer review caught: the first audit applies the stash and the
|
|
152
|
+
// file appears in the working tree. The stash entry stays in `git stash
|
|
153
|
+
// list` (apply, not pop). On the next audit, `git stash apply` exits
|
|
154
|
+
// non-zero with "already exists, no checkout" because the untracked file
|
|
155
|
+
// already exists. The original code surfaced that as a warning every
|
|
156
|
+
// startup. The fix detects that error and treats it as the idempotent
|
|
157
|
+
// steady state.
|
|
158
|
+
pushPreflightStash(repo, "M002", "leftover.txt", "lost work\n");
|
|
159
|
+
|
|
160
|
+
const first = auditOrphanedPreflightStashes(repo, () => true);
|
|
161
|
+
assert.equal(first.applied.length, 1, "first run applies");
|
|
162
|
+
assert.equal(first.warnings.length, 0);
|
|
163
|
+
|
|
164
|
+
const second = auditOrphanedPreflightStashes(repo, () => true);
|
|
165
|
+
assert.equal(second.applied.length, 0, "second run skips silently");
|
|
166
|
+
assert.equal(
|
|
167
|
+
second.warnings.length,
|
|
168
|
+
0,
|
|
169
|
+
"second run must NOT warn — files are already restored from first run",
|
|
170
|
+
);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("_isAlreadyRestoredApplyError detects the git stash apply already-exists error", () => {
|
|
175
|
+
// Real-world stderr produced by git when an --include-untracked stash is
|
|
176
|
+
// applied while the file already exists in the working tree.
|
|
177
|
+
const realError: { stderr: string } = {
|
|
178
|
+
stderr: "leftover.txt already exists, no checkout\nCould not restore untracked files from stash entry\n",
|
|
179
|
+
};
|
|
180
|
+
assert.equal(_isAlreadyRestoredApplyError(realError), true);
|
|
181
|
+
|
|
182
|
+
// Buffer-form stderr (when encoding is not set explicitly).
|
|
183
|
+
const bufErr = { stderr: Buffer.from("foo.ts already exists, no checkout\n") };
|
|
184
|
+
assert.equal(_isAlreadyRestoredApplyError(bufErr), true);
|
|
185
|
+
|
|
186
|
+
// Some Node versions surface the message in err.message.
|
|
187
|
+
const messageOnly = new Error("Command failed: git stash apply\nfoo.ts already exists, no checkout");
|
|
188
|
+
assert.equal(_isAlreadyRestoredApplyError(messageOnly), true);
|
|
189
|
+
|
|
190
|
+
// Unrelated errors must NOT be classified as already-restored.
|
|
191
|
+
const realConflict: { stderr: string } = {
|
|
192
|
+
stderr: "CONFLICT (content): Merge conflict in lib/models.ts\n",
|
|
193
|
+
};
|
|
194
|
+
assert.equal(_isAlreadyRestoredApplyError(realConflict), false);
|
|
195
|
+
|
|
196
|
+
// Defensive null/undefined handling.
|
|
197
|
+
assert.equal(_isAlreadyRestoredApplyError(null), false);
|
|
198
|
+
assert.equal(_isAlreadyRestoredApplyError(undefined), false);
|
|
199
|
+
assert.equal(_isAlreadyRestoredApplyError("not an error"), false);
|
|
200
|
+
assert.equal(_isAlreadyRestoredApplyError({}), false);
|
|
201
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// GSD-2 + src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts
|
|
2
|
+
// Regression: parallel-orchestrator's `_createMilestoneWorktree` must
|
|
3
|
+
// fast-forward a reused milestone branch onto integration before creating
|
|
4
|
+
// the worktree, matching the behavior added to the auto-mode path in
|
|
5
|
+
// commit 8996cb68e (#5549 post-merge audit, R3).
|
|
6
|
+
|
|
7
|
+
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { execFileSync } from "node:child_process";
|
|
10
|
+
import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
|
|
14
|
+
import { _createMilestoneWorktree } from "../parallel-orchestrator.js";
|
|
15
|
+
|
|
16
|
+
const NO_PROMPT_ENV = {
|
|
17
|
+
...process.env,
|
|
18
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
19
|
+
GIT_AUTHOR_NAME: "test",
|
|
20
|
+
GIT_AUTHOR_EMAIL: "test@example.com",
|
|
21
|
+
GIT_COMMITTER_NAME: "test",
|
|
22
|
+
GIT_COMMITTER_EMAIL: "test@example.com",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function git(cwd: string, ...args: string[]): string {
|
|
26
|
+
return execFileSync("git", args, {
|
|
27
|
+
cwd,
|
|
28
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29
|
+
encoding: "utf-8",
|
|
30
|
+
env: NO_PROMPT_ENV,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function rev(cwd: string, ref: string): string {
|
|
35
|
+
return git(cwd, "rev-parse", ref).trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("_createMilestoneWorktree fast-forwards reused milestone branches (#5549 R3)", () => {
|
|
39
|
+
let repo: string;
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
repo = mkdtempSync(join(tmpdir(), "parallel-orch-ff-"));
|
|
43
|
+
git(repo, "init", "-q", "-b", "main");
|
|
44
|
+
git(repo, "config", "user.email", "test@example.com");
|
|
45
|
+
git(repo, "config", "user.name", "test");
|
|
46
|
+
writeFileSync(join(repo, "seed.txt"), "seed\n");
|
|
47
|
+
git(repo, "add", "seed.txt");
|
|
48
|
+
git(repo, "commit", "-q", "-m", "initial");
|
|
49
|
+
// Minimal .gsd/ structure so syncGsdStateToWorktree doesn't crash on a
|
|
50
|
+
// bare repo. We don't care if it copies anything — only that the FF ran.
|
|
51
|
+
mkdirSync(join(repo, ".gsd"), { recursive: true });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
rmSync(repo, { recursive: true, force: true });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("reused milestone branch behind main is fast-forwarded before worktree creation", () => {
|
|
59
|
+
// Worker N drained M001 in a previous run, leaving milestone/M001 forked
|
|
60
|
+
// from old main. Worker N+1 picks up M002 — but the milestone/M002 branch
|
|
61
|
+
// was created from old main in a sibling run, so it's now N commits behind.
|
|
62
|
+
git(repo, "branch", "milestone/M002");
|
|
63
|
+
const m002Initial = rev(repo, "milestone/M002");
|
|
64
|
+
|
|
65
|
+
writeFileSync(join(repo, "seed.txt"), "main moved forward\n");
|
|
66
|
+
git(repo, "add", "seed.txt");
|
|
67
|
+
git(repo, "commit", "-q", "-m", "main advanced");
|
|
68
|
+
const mainTip = rev(repo, "main");
|
|
69
|
+
|
|
70
|
+
assert.notEqual(m002Initial, mainTip, "main must be ahead before the test");
|
|
71
|
+
|
|
72
|
+
// _createMilestoneWorktree may throw inside createWorktree/syncGsdStateToWorktree
|
|
73
|
+
// (e.g. if the worktree-manager has stricter requirements than this minimal
|
|
74
|
+
// repo provides). The fast-forward runs BEFORE those calls, so the branch
|
|
75
|
+
// ref should have moved regardless. Catch and assert on observable state.
|
|
76
|
+
try {
|
|
77
|
+
_createMilestoneWorktree(repo, "M002");
|
|
78
|
+
} catch {
|
|
79
|
+
// Fine — we only care that FF executed.
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
assert.equal(
|
|
83
|
+
rev(repo, "milestone/M002"),
|
|
84
|
+
mainTip,
|
|
85
|
+
"milestone/M002 must be fast-forwarded to main's tip before worktree is built",
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("diverged milestone branch is NOT touched (would lose work)", () => {
|
|
90
|
+
git(repo, "checkout", "-q", "-b", "milestone/M002");
|
|
91
|
+
writeFileSync(join(repo, "wip.txt"), "milestone-only work\n");
|
|
92
|
+
git(repo, "add", "wip.txt");
|
|
93
|
+
git(repo, "commit", "-q", "-m", "M002 work");
|
|
94
|
+
const m002Tip = rev(repo, "milestone/M002");
|
|
95
|
+
|
|
96
|
+
git(repo, "checkout", "-q", "main");
|
|
97
|
+
writeFileSync(join(repo, "seed.txt"), "main moved forward\n");
|
|
98
|
+
git(repo, "add", "seed.txt");
|
|
99
|
+
git(repo, "commit", "-q", "-m", "main advanced");
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
_createMilestoneWorktree(repo, "M002");
|
|
103
|
+
} catch {
|
|
104
|
+
// ignored
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
assert.equal(
|
|
108
|
+
rev(repo, "milestone/M002"),
|
|
109
|
+
m002Tip,
|
|
110
|
+
"diverged milestone branch must NOT be touched — would lose committed work",
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -8,48 +8,35 @@
|
|
|
8
8
|
* The fix makes isGhostMilestone treat a "queued" DB row with no disk
|
|
9
9
|
* artifacts (CONTEXT, ROADMAP, SUMMARY) as a ghost.
|
|
10
10
|
*
|
|
11
|
-
* This
|
|
11
|
+
* This behavior test exercises isGhostMilestone against real DB rows and
|
|
12
|
+
* milestone artifacts.
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import { describe, test } from 'node:test';
|
|
15
16
|
import assert from 'node:assert/strict';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const source = readFileSync(join(__dirname, '..', 'state.ts'), 'utf-8');
|
|
17
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { tmpdir } from 'node:os';
|
|
20
|
+
import { closeDatabase, insertMilestone, openDatabase } from '../gsd-db.ts';
|
|
21
|
+
import { clearPathCache } from '../paths.ts';
|
|
22
|
+
import { isGhostMilestone } from '../state.ts';
|
|
24
23
|
|
|
25
24
|
describe('isGhostMilestone phantom queued detection (#3671)', () => {
|
|
26
|
-
test('
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']ROADMAP["']\)/,
|
|
43
|
-
'should check for ROADMAP file');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('checks for SUMMARY disk artifact', () => {
|
|
47
|
-
assert.match(source, /resolveMilestoneFile\(basePath,\s*mid,\s*["']SUMMARY["']\)/,
|
|
48
|
-
'should check for SUMMARY file');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('returns !hasContent for queued rows (ghost if no artifacts)', () => {
|
|
52
|
-
assert.match(source, /return !hasContent/,
|
|
53
|
-
'should return !hasContent for queued phantom milestones');
|
|
25
|
+
test('queued DB row with no artifacts is a ghost, but content makes it real', () => {
|
|
26
|
+
const base = mkdtempSync(join(tmpdir(), 'gsd-phantom-ghost-'));
|
|
27
|
+
try {
|
|
28
|
+
openDatabase(':memory:');
|
|
29
|
+
insertMilestone({ id: 'M001', title: 'Reserved only', status: 'queued' });
|
|
30
|
+
mkdirSync(join(base, '.gsd', 'milestones', 'M001'), { recursive: true });
|
|
31
|
+
|
|
32
|
+
assert.equal(isGhostMilestone(base, 'M001'), true);
|
|
33
|
+
|
|
34
|
+
writeFileSync(join(base, '.gsd', 'milestones', 'M001', 'M001-CONTEXT.md'), '# Context\n');
|
|
35
|
+
clearPathCache();
|
|
36
|
+
assert.equal(isGhostMilestone(base, 'M001'), false);
|
|
37
|
+
} finally {
|
|
38
|
+
closeDatabase();
|
|
39
|
+
rmSync(base, { recursive: true, force: true });
|
|
40
|
+
}
|
|
54
41
|
});
|
|
55
42
|
});
|
|
@@ -8,32 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
import { describe, test } from 'node:test';
|
|
10
10
|
import assert from 'node:assert/strict';
|
|
11
|
-
import {
|
|
12
|
-
import { fileURLToPath } from 'node:url';
|
|
13
|
-
import { dirname, join } from 'node:path';
|
|
14
|
-
|
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
-
const __dirname = dirname(__filename);
|
|
17
|
-
|
|
18
|
-
const dbSrc = readFileSync(
|
|
19
|
-
join(__dirname, '..', 'gsd-db.ts'),
|
|
20
|
-
'utf-8',
|
|
21
|
-
);
|
|
11
|
+
import { closeDatabase, getMilestone, insertMilestone, openDatabase } from '../gsd-db.ts';
|
|
22
12
|
|
|
23
13
|
describe('insertMilestone defaults status to queued (#3695)', () => {
|
|
24
|
-
test('
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
test('default status is "queued" not "active"', () => {
|
|
30
|
-
// The status parameter should default to "queued" via nullish coalescing
|
|
31
|
-
assert.match(dbSrc, /m\.status\s*\?\?\s*"queued"/,
|
|
32
|
-
'insertMilestone should default status to "queued"');
|
|
33
|
-
});
|
|
14
|
+
test('omitted status persists as queued, not active', () => {
|
|
15
|
+
try {
|
|
16
|
+
openDatabase(':memory:');
|
|
17
|
+
insertMilestone({ id: 'M001', title: 'Reserved milestone' });
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
19
|
+
assert.equal(getMilestone('M001')?.status, 'queued');
|
|
20
|
+
} finally {
|
|
21
|
+
closeDatabase();
|
|
22
|
+
}
|
|
38
23
|
});
|
|
39
24
|
});
|