gsd-pi 2.80.0-dev.3065f7bfa → 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 +32 -8
- package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- 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-post-unit.js +81 -76
- package/dist/resources/extensions/gsd/auto-start.js +41 -6
- package/dist/resources/extensions/gsd/auto-worktree.js +98 -80
- package/dist/resources/extensions/gsd/auto.js +84 -29
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +62 -13
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +20 -26
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +29 -12
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -9
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -7
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -10
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -9
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +60 -26
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
- 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/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
- package/dist/resources/extensions/gsd/git-service.js +37 -1
- package/dist/resources/extensions/gsd/guided-flow.js +14 -4
- package/dist/resources/extensions/gsd/init-wizard.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
- 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/worktree-resolver.js +22 -1
- 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 +17 -17
- 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/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 +17 -17
- 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/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +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/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/types.d.ts +2 -2
- 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/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/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
- 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.ts +84 -8
- package/src/resources/extensions/gsd/auto/phases.ts +43 -8
- package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -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-post-unit.ts +93 -78
- package/src/resources/extensions/gsd/auto-start.ts +56 -6
- package/src/resources/extensions/gsd/auto-worktree.ts +118 -72
- package/src/resources/extensions/gsd/auto.ts +121 -29
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +76 -12
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +20 -26
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +27 -12
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +7 -9
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +4 -7
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +6 -10
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +5 -9
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +64 -26
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
- 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/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
- package/src/resources/extensions/gsd/git-service.ts +41 -2
- package/src/resources/extensions/gsd/guided-flow.ts +19 -4
- package/src/resources/extensions/gsd/init-wizard.ts +5 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -4
- 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 +15 -0
- 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 +1 -217
- 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/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.test.ts +140 -0
- 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/crash-handler-secondary.test.ts +35 -31
- 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/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 -59
- 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/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/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/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 +113 -0
- 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-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-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 -90
- 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/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 +61 -1
- 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/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/token-profile.test.ts +84 -309
- 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 +6 -101
- 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-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-main-branch.test.ts +20 -18
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +36 -0
- 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/worktree-resolver.ts +34 -1
- 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/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{O2WvnXROue6l7nAp_4dhC → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
|
@@ -1,93 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Regression test for #3628 — restore tool set after discuss flow scoping
|
|
3
|
-
*
|
|
4
|
-
* The discuss flow narrows the active tool set to avoid "grammar too complex"
|
|
5
|
-
* errors. Without restoring after sendMessage, the narrowed tools leaked into
|
|
6
|
-
* subsequent dispatches, breaking plan/execute flows.
|
|
7
|
-
*
|
|
8
|
-
* The fix saves the full tool set before scoping and restores it after
|
|
9
|
-
* sendMessage returns.
|
|
2
|
+
* Regression test for #3628 — restore tool set after discuss flow scoping.
|
|
10
3
|
*/
|
|
11
4
|
|
|
12
|
-
import
|
|
13
|
-
import assert from
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
assert.ok(tryIdx < firstMutation && firstMutation < finallyIdx, 'scoping mutation must be inside try/finally')
|
|
70
|
-
assert.ok(tryIdx < workflowRead && workflowRead < finallyIdx, 'workflow file read must be inside try/finally')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('savedTools is restored after sendMessage', () => {
|
|
74
|
-
// #4573: guided-flow.ts now contains multiple `triggerTurn: true` calls
|
|
75
|
-
// (ready-phrase and empty-turn recovery paths). The discuss-flow scoping
|
|
76
|
-
// sendMessage is the one that follows `tools: currentTools`, so
|
|
77
|
-
// anchor the search there rather than at the first `triggerTurn: true`.
|
|
78
|
-
const savedToolsAssign = src.indexOf('tools: currentTools')
|
|
79
|
-
assert.ok(savedToolsAssign !== -1, 'savedTools must capture currentTools')
|
|
80
|
-
|
|
81
|
-
const sendMsg = src.indexOf('triggerTurn: true', savedToolsAssign)
|
|
82
|
-
assert.ok(sendMsg !== -1, 'discuss-flow sendMessage with triggerTurn must exist after savedTools capture')
|
|
83
|
-
|
|
84
|
-
// After sendMessage, savedTools should be restored via the shared helper.
|
|
85
|
-
// Use fromIdx to anchor at the discuss-flow sendMessage, not the first
|
|
86
|
-
// triggerTurn: true occurrence in the file.
|
|
87
|
-
const afterSend = extractSourceRegion(src, 'triggerTurn: true', { fromIdx: savedToolsAssign })
|
|
88
|
-
assert.ok(
|
|
89
|
-
afterSend.includes('restoreGsdWorkflowTools(pi, savedTools)'),
|
|
90
|
-
'restoreGsdWorkflowTools(pi, savedTools) must restore the full scoped state',
|
|
91
|
-
)
|
|
92
|
-
})
|
|
93
|
-
})
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
|
|
11
|
+
import { _dispatchWorkflowForTest } from "../guided-flow.ts";
|
|
12
|
+
|
|
13
|
+
test("discuss workflow scopes tools for the queued turn and restores the full tool set", async () => {
|
|
14
|
+
const dir = mkdtempSync(join(tmpdir(), "gsd-discuss-tools-"));
|
|
15
|
+
const workflowPath = join(dir, "GSD-WORKFLOW.md");
|
|
16
|
+
const originalWorkflowPath = process.env.GSD_WORKFLOW_PATH;
|
|
17
|
+
const originalTools = [
|
|
18
|
+
"gsd_task_complete",
|
|
19
|
+
"gsd_summary_save",
|
|
20
|
+
"shell_exec",
|
|
21
|
+
"gsd_plan_milestone",
|
|
22
|
+
];
|
|
23
|
+
let activeTools = [...originalTools];
|
|
24
|
+
let sentTools: string[] | null = null;
|
|
25
|
+
let triggerTurn = false;
|
|
26
|
+
|
|
27
|
+
const pi = {
|
|
28
|
+
getActiveTools: () => [...activeTools],
|
|
29
|
+
setActiveTools: (tools: string[]) => {
|
|
30
|
+
activeTools = [...tools];
|
|
31
|
+
},
|
|
32
|
+
sendMessage: (_message: unknown, options?: { triggerTurn?: boolean }) => {
|
|
33
|
+
sentTools = [...activeTools];
|
|
34
|
+
triggerTurn = options?.triggerTurn === true;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
writeFileSync(workflowPath, "# Workflow\n", "utf-8");
|
|
40
|
+
process.env.GSD_WORKFLOW_PATH = workflowPath;
|
|
41
|
+
|
|
42
|
+
await _dispatchWorkflowForTest(
|
|
43
|
+
pi as any,
|
|
44
|
+
"Interview the user.",
|
|
45
|
+
"gsd-discuss",
|
|
46
|
+
undefined,
|
|
47
|
+
"discuss-milestone",
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
assert.deepEqual(sentTools, ["gsd_summary_save"]);
|
|
51
|
+
assert.deepEqual(activeTools, originalTools);
|
|
52
|
+
assert.equal(triggerTurn, true);
|
|
53
|
+
} finally {
|
|
54
|
+
if (originalWorkflowPath === undefined) {
|
|
55
|
+
delete process.env.GSD_WORKFLOW_PATH;
|
|
56
|
+
} else {
|
|
57
|
+
process.env.GSD_WORKFLOW_PATH = originalWorkflowPath;
|
|
58
|
+
}
|
|
59
|
+
rmSync(dir, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tests for fix of #3723: auto-mode resume/crash-recovery dispatches
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* During resume, the paused-session metadata may record `worktreePath` that
|
|
6
|
-
* was active when the session paused. The resume path must use that path (or
|
|
7
|
-
* derive the worktree path via filesystem lookup) to set the dispatch context
|
|
8
|
-
* (`s.basePath`), rather than defaulting to the project root.
|
|
9
|
-
*
|
|
10
|
-
* The fix adds an early worktree-path resolution step in the paused-session
|
|
11
|
-
* resume block of auto.ts — immediately after `s.basePath = base` — so that
|
|
12
|
-
* the correct dispatch directory is used before the dispatch loop runs.
|
|
2
|
+
* Tests for fix of #3723: auto-mode resume/crash-recovery dispatches from
|
|
3
|
+
* the paused milestone worktree when that worktree still exists.
|
|
13
4
|
*/
|
|
14
5
|
|
|
15
6
|
import test from "node:test";
|
|
@@ -18,95 +9,8 @@ import { readFileSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
|
18
9
|
import { join } from "node:path";
|
|
19
10
|
import { tmpdir } from "node:os";
|
|
20
11
|
import { randomUUID } from "node:crypto";
|
|
21
|
-
import { fileURLToPath } from "node:url";
|
|
22
|
-
import { dirname } from "node:path";
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
const autoSrc = readFileSync(join(__dirname, "..", "auto.ts"), "utf-8");
|
|
26
|
-
|
|
27
|
-
// ── Source-structure tests ────────────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Extract the paused-session resume block from auto.ts.
|
|
31
|
-
*
|
|
32
|
-
* The block we care about is the `if (s.paused) { ... }` section inside
|
|
33
|
-
* startAuto, which contains `s.basePath = base` (line ~1473) followed by the
|
|
34
|
-
* `enterMilestone` call.
|
|
35
|
-
*
|
|
36
|
-
* We find it by locating the `s.basePath = base` assignment that appears
|
|
37
|
-
* WITHIN the s.paused branch (there's only one: all other basePath assignments
|
|
38
|
-
* use originalBasePath or a different value). We extract from that assignment
|
|
39
|
-
* up to just before `enterMilestone(`.
|
|
40
|
-
*/
|
|
41
|
-
function getBasepathToEnterMilestoneSegment(): string {
|
|
42
|
-
// Find `s.basePath = base;` in the s.paused branch
|
|
43
|
-
// This assignment appears uniquely inside the resume block
|
|
44
|
-
const assignPattern = "s.basePath = base;";
|
|
45
|
-
const assignIdx = autoSrc.indexOf(assignPattern);
|
|
46
|
-
assert.ok(
|
|
47
|
-
assignIdx > -1,
|
|
48
|
-
`auto.ts must contain '${assignPattern}' in the resume block`,
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
// Find the next enterMilestone call after this assignment
|
|
52
|
-
const enterMilestoneIdx = autoSrc.indexOf("enterMilestone(", assignIdx);
|
|
53
|
-
assert.ok(
|
|
54
|
-
enterMilestoneIdx > assignIdx,
|
|
55
|
-
"auto.ts must call enterMilestone after the s.basePath = base assignment",
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
// Return the code between the assignment and enterMilestone
|
|
59
|
-
return autoSrc.slice(assignIdx, enterMilestoneIdx);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
test("auto.ts resume block resolves paused-session worktreePath and applies it to s.basePath before entering worktree (fixes #3723)", () => {
|
|
63
|
-
// The segment between `s.basePath = base` and `enterMilestone(` must
|
|
64
|
-
// contain logic that resolves the paused-session worktreePath and applies
|
|
65
|
-
// it to s.basePath when the worktree exists on disk.
|
|
66
|
-
//
|
|
67
|
-
// The fix reads the worktree path from freshStartAssessment.pausedSession
|
|
68
|
-
// (since `meta` is out of scope at this point in startAuto) and assigns
|
|
69
|
-
// it to s.basePath, guarded by existsSync.
|
|
70
|
-
//
|
|
71
|
-
// Without this fix, the dispatch loop runs from `base` (project root)
|
|
72
|
-
// instead of the worktree, causing split-brain execution (#3723).
|
|
73
|
-
const segment = getBasepathToEnterMilestoneSegment();
|
|
74
|
-
|
|
75
|
-
// The fix uses freshStartAssessment.pausedSession?.worktreePath via a
|
|
76
|
-
// local variable (resumeWorktreePath) and assigns to s.basePath.
|
|
77
|
-
const hasWorktreePathResolution =
|
|
78
|
-
segment.includes("worktreePath") &&
|
|
79
|
-
segment.includes("existsSync") &&
|
|
80
|
-
segment.includes("s.basePath =");
|
|
81
|
-
|
|
82
|
-
assert.ok(
|
|
83
|
-
hasWorktreePathResolution,
|
|
84
|
-
"auto.ts must resolve the paused-session worktreePath, check existsSync, and assign " +
|
|
85
|
-
"s.basePath before enterMilestone — crash-recovery currently dispatches from project root " +
|
|
86
|
-
"instead of milestone worktree (issue #3723). The fix belongs between `s.basePath = base` " +
|
|
87
|
-
"and the enterMilestone call.",
|
|
88
|
-
);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("auto.ts worktreePath assignment in resume block guards against non-existent path (fixes #3723)", () => {
|
|
92
|
-
// The assignment to s.basePath from the paused-session worktreePath must
|
|
93
|
-
// be guarded by existsSync to avoid setting an invalid basePath if the
|
|
94
|
-
// worktree was cleaned up between pause and resume.
|
|
95
|
-
const segment = getBasepathToEnterMilestoneSegment();
|
|
96
|
-
|
|
97
|
-
// Must have existsSync guard AND a worktreePath reference AND s.basePath assignment
|
|
98
|
-
const hasGuardedAssignment =
|
|
99
|
-
segment.includes("existsSync") &&
|
|
100
|
-
segment.includes("worktreePath") &&
|
|
101
|
-
segment.includes("s.basePath =");
|
|
102
|
-
|
|
103
|
-
assert.ok(
|
|
104
|
-
hasGuardedAssignment,
|
|
105
|
-
"auto.ts must guard the s.basePath = worktreePath assignment with existsSync (fixes #3723)",
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
// ── Functional tests ──────────────────────────────────────────────────────────
|
|
13
|
+
import { _resolvePausedResumeBasePathForTest } from "../auto.ts";
|
|
110
14
|
|
|
111
15
|
function makeTmpBase(): string {
|
|
112
16
|
const base = join(tmpdir(), `gsd-resume-wt-${randomUUID()}`);
|
|
@@ -115,7 +19,7 @@ function makeTmpBase(): string {
|
|
|
115
19
|
}
|
|
116
20
|
|
|
117
21
|
function cleanup(base: string): void {
|
|
118
|
-
try { rmSync(base, { recursive: true, force: true }); } catch { /* */ }
|
|
22
|
+
try { rmSync(base, { recursive: true, force: true }); } catch { /* noop */ }
|
|
119
23
|
}
|
|
120
24
|
|
|
121
25
|
function writePausedSession(
|
|
@@ -142,7 +46,6 @@ function makeWorktreePath(base: string, milestoneId: string): string {
|
|
|
142
46
|
|
|
143
47
|
function setupWorktreeOnDisk(wt: string): void {
|
|
144
48
|
mkdirSync(wt, { recursive: true });
|
|
145
|
-
// Simulate a git worktree: .git file with gitdir pointer
|
|
146
49
|
writeFileSync(
|
|
147
50
|
join(wt, ".git"),
|
|
148
51
|
"gitdir: /project/.git/worktrees/M001-test\n",
|
|
@@ -150,81 +53,46 @@ function setupWorktreeOnDisk(wt: string): void {
|
|
|
150
53
|
);
|
|
151
54
|
}
|
|
152
55
|
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
"utf-8",
|
|
167
|
-
);
|
|
168
|
-
}
|
|
56
|
+
test("resume base path uses paused-session worktreePath when the worktree exists", () => {
|
|
57
|
+
const base = makeTmpBase();
|
|
58
|
+
const wt = makeWorktreePath(base, "M001-test");
|
|
59
|
+
try {
|
|
60
|
+
setupWorktreeOnDisk(wt);
|
|
61
|
+
assert.equal(
|
|
62
|
+
_resolvePausedResumeBasePathForTest(base, wt),
|
|
63
|
+
wt,
|
|
64
|
+
);
|
|
65
|
+
} finally {
|
|
66
|
+
cleanup(base);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
169
69
|
|
|
170
|
-
test("
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
70
|
+
test("resume base path falls back to project root when paused worktree is missing", () => {
|
|
71
|
+
const base = makeTmpBase();
|
|
72
|
+
const wt = makeWorktreePath(base, "M001-test");
|
|
73
|
+
try {
|
|
74
|
+
assert.equal(
|
|
75
|
+
_resolvePausedResumeBasePathForTest(base, wt),
|
|
76
|
+
base,
|
|
77
|
+
);
|
|
78
|
+
} finally {
|
|
79
|
+
cleanup(base);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("read paused-session metadata round-trips worktreePath from paused-session.json", () => {
|
|
176
84
|
const base = makeTmpBase();
|
|
177
85
|
const wt = makeWorktreePath(base, "M001-test");
|
|
178
86
|
try {
|
|
179
87
|
setupWorktreeOnDisk(wt);
|
|
180
88
|
writePausedSession(base, "M001-test", wt);
|
|
181
89
|
|
|
182
|
-
// Simulate readPausedSessionMetadata without importing the full module
|
|
183
90
|
const pausedPath = join(base, ".gsd", "runtime", "paused-session.json");
|
|
184
91
|
const meta = JSON.parse(readFileSync(pausedPath, "utf-8"));
|
|
185
92
|
|
|
186
|
-
assert.ok(meta, "paused-session metadata must be readable");
|
|
187
93
|
assert.equal(meta.milestoneId, "M001-test");
|
|
188
|
-
assert.equal(meta.worktreePath, wt
|
|
94
|
+
assert.equal(meta.worktreePath, wt);
|
|
189
95
|
} finally {
|
|
190
96
|
cleanup(base);
|
|
191
97
|
}
|
|
192
98
|
});
|
|
193
|
-
|
|
194
|
-
test("auto.ts resume block uses worktreePath from freshStartAssessment.pausedSession as dispatch basePath when worktree exists (#3723)", () => {
|
|
195
|
-
// End-to-end structural verification: the auto.ts source must contain code
|
|
196
|
-
// that reads the worktreePath from freshStartAssessment.pausedSession AND
|
|
197
|
-
// applies it to s.basePath (guarded by existsSync) between the
|
|
198
|
-
// `s.basePath = base` assignment and `enterMilestone`.
|
|
199
|
-
//
|
|
200
|
-
// This is the core of the #3723 fix. Without this check, a session that
|
|
201
|
-
// paused while operating inside a worktree will resume dispatching from the
|
|
202
|
-
// project root, not the worktree — causing split-brain execution where some
|
|
203
|
-
// operations target the worktree and others target the project root.
|
|
204
|
-
const segment = getBasepathToEnterMilestoneSegment();
|
|
205
|
-
|
|
206
|
-
// Must reference freshStartAssessment.pausedSession?.worktreePath or
|
|
207
|
-
// equivalent local variable, AND contain an existsSync guard
|
|
208
|
-
const hasAssessmentWorktreePath =
|
|
209
|
-
segment.includes("freshStartAssessment.pausedSession") &&
|
|
210
|
-
segment.includes("worktreePath");
|
|
211
|
-
|
|
212
|
-
assert.ok(
|
|
213
|
-
hasAssessmentWorktreePath,
|
|
214
|
-
"auto.ts must read worktreePath from freshStartAssessment.pausedSession between " +
|
|
215
|
-
"s.basePath=base and enterMilestone",
|
|
216
|
-
);
|
|
217
|
-
assert.ok(
|
|
218
|
-
segment.includes("existsSync"),
|
|
219
|
-
"auto.ts must guard worktreePath usage with existsSync",
|
|
220
|
-
);
|
|
221
|
-
// The actual basePath re-assignment must be present in the segment
|
|
222
|
-
// (note: there are multiple `s.basePath =` assignments — we need one after
|
|
223
|
-
// the initial `s.basePath = base` assignment within this segment)
|
|
224
|
-
const worktreeAssignIdx = segment.lastIndexOf("s.basePath =");
|
|
225
|
-
const baseAssignIdx = segment.indexOf("s.basePath = base");
|
|
226
|
-
assert.ok(
|
|
227
|
-
worktreeAssignIdx > baseAssignIdx,
|
|
228
|
-
"auto.ts must assign s.basePath to the worktree path after `s.basePath = base` in the resume block",
|
|
229
|
-
);
|
|
230
|
-
});
|
|
@@ -1,51 +1,67 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Regression test for #3624 — cap run-uat dispatch attempts
|
|
3
|
-
*
|
|
4
|
-
* When verification commands fail before writing a verdict, the run-uat
|
|
5
|
-
* dispatch rule fires repeatedly in an infinite loop. The fix adds a
|
|
6
|
-
* MAX_UAT_ATTEMPTS constant and calls incrementUatCount before dispatch
|
|
7
|
-
* to cap the number of attempts.
|
|
8
|
-
*
|
|
9
|
-
* Structural verification test — reads source to confirm MAX_UAT_ATTEMPTS
|
|
10
|
-
* and incrementUatCount exist.
|
|
2
|
+
* Regression test for #3624 — cap run-uat dispatch attempts.
|
|
11
3
|
*/
|
|
12
4
|
|
|
13
|
-
import
|
|
14
|
-
import assert from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
const __dirname = dirname(__filename);
|
|
11
|
+
import { DISPATCH_RULES, getUatCount } from "../auto-dispatch.ts";
|
|
21
12
|
|
|
22
|
-
|
|
13
|
+
function makeUatProject(): string {
|
|
14
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-uat-cap-"));
|
|
15
|
+
const milestone = join(base, ".gsd", "milestones", "M001");
|
|
16
|
+
mkdirSync(join(milestone, "slices", "S01"), { recursive: true });
|
|
17
|
+
mkdirSync(join(milestone, "slices", "S02"), { recursive: true });
|
|
18
|
+
writeFileSync(
|
|
19
|
+
join(milestone, "M001-ROADMAP.md"),
|
|
20
|
+
[
|
|
21
|
+
"# M001: UAT Cap",
|
|
22
|
+
"",
|
|
23
|
+
"## Slices",
|
|
24
|
+
"- [x] **S01: Completed slice** `risk:low`",
|
|
25
|
+
" Demo: done.",
|
|
26
|
+
"- [ ] **S02: Remaining slice** `risk:low`",
|
|
27
|
+
" Demo: pending.",
|
|
28
|
+
].join("\n"),
|
|
29
|
+
"utf-8",
|
|
30
|
+
);
|
|
31
|
+
writeFileSync(
|
|
32
|
+
join(milestone, "slices", "S01", "S01-UAT.md"),
|
|
33
|
+
"# UAT\n\nRun the checks. No verdict has been written yet.\n",
|
|
34
|
+
"utf-8",
|
|
35
|
+
);
|
|
36
|
+
return base;
|
|
37
|
+
}
|
|
23
38
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
39
|
+
test("run-uat dispatch stops after three attempts without a verdict", async () => {
|
|
40
|
+
const basePath = makeUatProject();
|
|
41
|
+
const rule = DISPATCH_RULES.find((r) => r.name === "run-uat (post-completion)");
|
|
42
|
+
assert.ok(rule, "run-uat dispatch rule is registered");
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
const ctx = {
|
|
45
|
+
state: { phase: "planning", activeSlice: null },
|
|
46
|
+
mid: "M001",
|
|
47
|
+
midTitle: "UAT Cap",
|
|
48
|
+
basePath,
|
|
49
|
+
prefs: { uat_dispatch: true },
|
|
50
|
+
};
|
|
34
51
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
52
|
+
try {
|
|
53
|
+
for (let i = 1; i <= 3; i++) {
|
|
54
|
+
const action = await rule.match(ctx as any);
|
|
55
|
+
assert.equal(action?.action, "dispatch");
|
|
56
|
+
assert.equal(action?.unitType, "run-uat");
|
|
57
|
+
assert.equal(getUatCount(basePath, "M001", "S01"), i);
|
|
58
|
+
}
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
assert.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
test('attempts are compared against MAX_UAT_ATTEMPTS', () => {
|
|
48
|
-
assert.match(source, /attempts\s*>\s*MAX_UAT_ATTEMPTS/,
|
|
49
|
-
'dispatch should check attempts > MAX_UAT_ATTEMPTS');
|
|
50
|
-
});
|
|
60
|
+
const capped = await rule.match(ctx as any);
|
|
61
|
+
assert.equal(capped?.action, "stop");
|
|
62
|
+
assert.match(capped?.reason ?? "", /dispatched 3 times/);
|
|
63
|
+
assert.equal(getUatCount(basePath, "M001", "S01"), 4);
|
|
64
|
+
} finally {
|
|
65
|
+
rmSync(basePath, { recursive: true, force: true });
|
|
66
|
+
}
|
|
51
67
|
});
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
3
|
|
|
6
4
|
import {
|
|
7
5
|
clearSessionModelOverride,
|
|
@@ -9,8 +7,6 @@ import {
|
|
|
9
7
|
setSessionModelOverride,
|
|
10
8
|
} from "../session-model-override.js";
|
|
11
9
|
|
|
12
|
-
const phasesSource = readFileSync(join(import.meta.dirname, "..", "auto", "phases.ts"), "utf-8");
|
|
13
|
-
|
|
14
10
|
test("setSessionModelOverride stores provider/model for the session", () => {
|
|
15
11
|
const sessionId = `session-override-${Date.now()}`;
|
|
16
12
|
setSessionModelOverride(sessionId, { provider: "openai-codex", id: "gpt-5.4" });
|
|
@@ -27,9 +23,18 @@ test("clearSessionModelOverride removes the session override", () => {
|
|
|
27
23
|
assert.equal(getSessionModelOverride(sessionId), undefined);
|
|
28
24
|
});
|
|
29
25
|
|
|
30
|
-
test("
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
26
|
+
test("session model overrides are isolated by session id", () => {
|
|
27
|
+
const first = `session-first-${Date.now()}`;
|
|
28
|
+
const second = `session-second-${Date.now()}`;
|
|
29
|
+
setSessionModelOverride(first, { provider: "openai-codex", id: "gpt-5.4" });
|
|
30
|
+
setSessionModelOverride(second, { provider: "anthropic", id: "claude-sonnet-4-6" });
|
|
31
|
+
|
|
32
|
+
assert.deepEqual(getSessionModelOverride(first), {
|
|
33
|
+
provider: "openai-codex",
|
|
34
|
+
id: "gpt-5.4",
|
|
35
|
+
});
|
|
36
|
+
assert.deepEqual(getSessionModelOverride(second), {
|
|
37
|
+
provider: "anthropic",
|
|
38
|
+
id: "claude-sonnet-4-6",
|
|
39
|
+
});
|
|
35
40
|
});
|
|
@@ -206,6 +206,83 @@ test("session_start does NOT call setFooter or suppress gsd-health when isAutoAc
|
|
|
206
206
|
assert.equal(healthWidgetHideCount, 0, "gsd-health must NOT be hidden when isAutoActive() is false");
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
+
test("session_start installs the welcome screen as the TUI header", async (t) => {
|
|
210
|
+
const dir = join(
|
|
211
|
+
tmpdir(),
|
|
212
|
+
`gsd-welcome-header-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
213
|
+
);
|
|
214
|
+
mkdirSync(join(dir, "bin"), { recursive: true });
|
|
215
|
+
mkdirSync(join(dir, "dist"), { recursive: true });
|
|
216
|
+
writeFileSync(join(dir, "bin", "welcome-screen.js"), "export const stale = true;\n", "utf-8");
|
|
217
|
+
writeFileSync(
|
|
218
|
+
join(dir, "dist", "welcome-screen.js"),
|
|
219
|
+
[
|
|
220
|
+
"export function buildWelcomeScreenLines(opts) {",
|
|
221
|
+
" return [`welcome ${opts.version} ${opts.remoteChannel ?? 'none'} ${opts.width}`];",
|
|
222
|
+
"}",
|
|
223
|
+
"",
|
|
224
|
+
].join("\n"),
|
|
225
|
+
"utf-8",
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const originalCwd = process.cwd();
|
|
229
|
+
const originalGsdPkgRoot = process.env.GSD_PKG_ROOT;
|
|
230
|
+
const originalGsdBinPath = process.env.GSD_BIN_PATH;
|
|
231
|
+
const originalGsdVersion = process.env.GSD_VERSION;
|
|
232
|
+
const originalFirstRunBanner = process.env.GSD_FIRST_RUN_BANNER;
|
|
233
|
+
process.chdir(dir);
|
|
234
|
+
process.env.GSD_PKG_ROOT = dir;
|
|
235
|
+
process.env.GSD_BIN_PATH = join(dir, "bin", "loader.js");
|
|
236
|
+
process.env.GSD_VERSION = "9.9.9-test";
|
|
237
|
+
delete process.env.GSD_FIRST_RUN_BANNER;
|
|
238
|
+
t.after(() => {
|
|
239
|
+
process.chdir(originalCwd);
|
|
240
|
+
if (originalGsdPkgRoot === undefined) delete process.env.GSD_PKG_ROOT;
|
|
241
|
+
else process.env.GSD_PKG_ROOT = originalGsdPkgRoot;
|
|
242
|
+
if (originalGsdBinPath === undefined) delete process.env.GSD_BIN_PATH;
|
|
243
|
+
else process.env.GSD_BIN_PATH = originalGsdBinPath;
|
|
244
|
+
if (originalGsdVersion === undefined) delete process.env.GSD_VERSION;
|
|
245
|
+
else process.env.GSD_VERSION = originalGsdVersion;
|
|
246
|
+
if (originalFirstRunBanner === undefined) delete process.env.GSD_FIRST_RUN_BANNER;
|
|
247
|
+
else process.env.GSD_FIRST_RUN_BANNER = originalFirstRunBanner;
|
|
248
|
+
try { rmSync(dir, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
|
|
252
|
+
const pi = {
|
|
253
|
+
on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
|
|
254
|
+
handlers.set(event, handler);
|
|
255
|
+
},
|
|
256
|
+
} as any;
|
|
257
|
+
|
|
258
|
+
registerHooks(pi, []);
|
|
259
|
+
|
|
260
|
+
const sessionStart = handlers.get("session_start");
|
|
261
|
+
assert.ok(sessionStart, "session_start handler must be registered");
|
|
262
|
+
|
|
263
|
+
let headerFactory: ((tui: unknown, theme: unknown) => { render(width: number): string[] }) | undefined;
|
|
264
|
+
await sessionStart!({}, {
|
|
265
|
+
hasUI: true,
|
|
266
|
+
ui: {
|
|
267
|
+
notify: () => {},
|
|
268
|
+
setStatus: () => {},
|
|
269
|
+
setFooter: () => {},
|
|
270
|
+
setHeader: (factory: typeof headerFactory) => {
|
|
271
|
+
headerFactory = factory;
|
|
272
|
+
},
|
|
273
|
+
setWorkingMessage: () => {},
|
|
274
|
+
onTerminalInput: () => () => {},
|
|
275
|
+
setWidget: () => {},
|
|
276
|
+
},
|
|
277
|
+
sessionManager: { getSessionId: () => null },
|
|
278
|
+
model: null,
|
|
279
|
+
} as any);
|
|
280
|
+
|
|
281
|
+
assert.equal(typeof headerFactory, "function", "session_start should install a header factory");
|
|
282
|
+
const header = headerFactory!({}, {});
|
|
283
|
+
assert.deepEqual(header.render(123), ["welcome 9.9.9-test none 123"]);
|
|
284
|
+
});
|
|
285
|
+
|
|
209
286
|
test("session_start and session_switch apply disabled model provider policy from current preferences", async (t) => {
|
|
210
287
|
const dir = join(
|
|
211
288
|
tmpdir(),
|