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,14 +1,37 @@
|
|
|
1
|
-
import test from "node:test";
|
|
1
|
+
import test, { mock } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import {
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
3
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
6
|
import { parseSlackReply, parseDiscordResponse, formatForDiscord, formatForSlack, parseSlackReactionResponse, formatForTelegram, parseTelegramResponse } from "../../remote-questions/format.ts";
|
|
7
7
|
import { resolveRemoteConfig, isValidChannelId } from "../../remote-questions/config.ts";
|
|
8
|
+
import { DiscordAdapter } from "../../remote-questions/discord-adapter.ts";
|
|
9
|
+
import { isRemoteConfigured } from "../../remote-questions/manager.ts";
|
|
10
|
+
import { handleRemote, saveRemoteQuestionsConfig } from "../../remote-questions/remote-command.ts";
|
|
11
|
+
import { SlackAdapter } from "../../remote-questions/slack-adapter.ts";
|
|
8
12
|
import { sanitizeError } from "../../shared/sanitize.ts";
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
function jsonResponse(body: unknown): Response {
|
|
15
|
+
return {
|
|
16
|
+
ok: true,
|
|
17
|
+
status: 200,
|
|
18
|
+
async json() { return body; },
|
|
19
|
+
async text() { return JSON.stringify(body); },
|
|
20
|
+
} as Response;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function withTempGsdHome<T>(fn: (home: string) => T | Promise<T>): Promise<T> {
|
|
24
|
+
const oldHome = process.env.GSD_HOME;
|
|
25
|
+
const home = mkdtempSync(join(tmpdir(), "gsd-remote-home-"));
|
|
26
|
+
try {
|
|
27
|
+
process.env.GSD_HOME = home;
|
|
28
|
+
return await fn(home);
|
|
29
|
+
} finally {
|
|
30
|
+
if (oldHome === undefined) delete process.env.GSD_HOME;
|
|
31
|
+
else process.env.GSD_HOME = oldHome;
|
|
32
|
+
rmSync(home, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
12
35
|
|
|
13
36
|
test("parseSlackReply handles single-number single-question answers", () => {
|
|
14
37
|
const result = parseSlackReply("2", [{
|
|
@@ -421,47 +444,91 @@ test("parseDiscordResponse handles multiple reactions for allowMultiple question
|
|
|
421
444
|
assert.deepEqual(result.answers.choice.answers, ["Alpha", "Gamma"]);
|
|
422
445
|
});
|
|
423
446
|
|
|
424
|
-
test("DiscordAdapter
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
447
|
+
test("DiscordAdapter validates guild, sends prompt URL, and acknowledges with checkmark", async () => {
|
|
448
|
+
const calls: Array<{ url: string; method: string }> = [];
|
|
449
|
+
const fetchMock = mock.method(globalThis, "fetch", async (url: string | URL, init?: RequestInit) => {
|
|
450
|
+
const href = String(url);
|
|
451
|
+
calls.push({ url: href, method: String(init?.method ?? "GET") });
|
|
452
|
+
if (href.endsWith("/users/@me")) return jsonResponse({ id: "bot-1" });
|
|
453
|
+
if (href.includes("/channels/12345678901234567") && !href.includes("/messages")) return jsonResponse({ guild_id: "guild-1" });
|
|
454
|
+
if (href.endsWith("/messages")) return jsonResponse({ id: "message-1" });
|
|
455
|
+
return jsonResponse({});
|
|
456
|
+
});
|
|
457
|
+
try {
|
|
458
|
+
const adapter = new DiscordAdapter("token", "12345678901234567");
|
|
459
|
+
await adapter.validate();
|
|
460
|
+
const result = await adapter.sendPrompt({
|
|
461
|
+
id: "discord-1",
|
|
462
|
+
channel: "discord",
|
|
463
|
+
createdAt: Date.now(),
|
|
464
|
+
timeoutAt: Date.now() + 60_000,
|
|
465
|
+
pollIntervalMs: 5000,
|
|
466
|
+
questions: [{
|
|
467
|
+
id: "q1",
|
|
468
|
+
header: "Pick",
|
|
469
|
+
question: "Choose",
|
|
470
|
+
allowMultiple: false,
|
|
471
|
+
options: [{ label: "A", description: "a" }],
|
|
472
|
+
}],
|
|
473
|
+
});
|
|
474
|
+
await adapter.acknowledgeAnswer(result.ref);
|
|
443
475
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
assert.ok(commandSrc.includes("users.conversations"), "Slack setup should query Slack channels");
|
|
450
|
-
assert.ok(commandSrc.includes("Select a Slack channel"), "Slack setup should present a channel picker");
|
|
451
|
-
assert.ok(commandSrc.includes("Enter channel ID manually"), "Slack setup should preserve manual fallback");
|
|
476
|
+
assert.equal(result.ref.threadUrl, "https://discord.com/channels/guild-1/12345678901234567/message-1");
|
|
477
|
+
assert.ok(calls.some((call) => call.method === "PUT" && call.url.includes(encodeURIComponent("✅"))));
|
|
478
|
+
} finally {
|
|
479
|
+
fetchMock.mock.restore();
|
|
480
|
+
}
|
|
452
481
|
});
|
|
453
482
|
|
|
454
|
-
test("
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
483
|
+
test("SlackAdapter polls reactions and acknowledges with white_check_mark", async () => {
|
|
484
|
+
const calls: Array<{ url: string; method: string; body?: string }> = [];
|
|
485
|
+
const fetchMock = mock.method(globalThis, "fetch", async (url: string | URL, init?: RequestInit) => {
|
|
486
|
+
const href = String(url);
|
|
487
|
+
calls.push({ url: href, method: String(init?.method ?? "GET"), body: String(init?.body ?? "") });
|
|
488
|
+
if (href.includes("/auth.test")) return jsonResponse({ ok: true, user_id: "bot-1" });
|
|
489
|
+
if (href.includes("/chat.postMessage")) return jsonResponse({ ok: true, ts: "123.456", channel: "C12345678" });
|
|
490
|
+
if (href.includes("/reactions.get")) {
|
|
491
|
+
return jsonResponse({
|
|
492
|
+
ok: true,
|
|
493
|
+
message: { reactions: [{ name: "two", count: 1, users: ["human-1"] }] },
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
return jsonResponse({ ok: true });
|
|
497
|
+
});
|
|
498
|
+
try {
|
|
499
|
+
const adapter = new SlackAdapter("xoxb-test", "C12345678");
|
|
500
|
+
await adapter.validate();
|
|
501
|
+
const prompt = {
|
|
502
|
+
id: "slack-1",
|
|
503
|
+
channel: "slack" as const,
|
|
504
|
+
createdAt: Date.now(),
|
|
505
|
+
timeoutAt: Date.now() + 60_000,
|
|
506
|
+
pollIntervalMs: 5000,
|
|
507
|
+
questions: [{
|
|
508
|
+
id: "q1",
|
|
509
|
+
header: "Pick",
|
|
510
|
+
question: "Choose",
|
|
511
|
+
allowMultiple: false,
|
|
512
|
+
options: [
|
|
513
|
+
{ label: "A", description: "a" },
|
|
514
|
+
{ label: "B", description: "b" },
|
|
515
|
+
],
|
|
516
|
+
}],
|
|
517
|
+
};
|
|
518
|
+
const sent = await adapter.sendPrompt(prompt);
|
|
519
|
+
const answer = await adapter.pollAnswer(prompt, sent.ref);
|
|
520
|
+
await adapter.acknowledgeAnswer(sent.ref);
|
|
521
|
+
|
|
522
|
+
assert.deepEqual(answer, { answers: { q1: { answers: ["B"] } } });
|
|
523
|
+
assert.ok(calls.some((call) => call.url.includes("/reactions.get")));
|
|
524
|
+
assert.ok(calls.some((call) =>
|
|
525
|
+
call.url.includes("/reactions.add")
|
|
526
|
+
&& typeof call.body === "string"
|
|
527
|
+
&& call.body.includes("white_check_mark")
|
|
528
|
+
));
|
|
529
|
+
} finally {
|
|
530
|
+
fetchMock.mock.restore();
|
|
531
|
+
}
|
|
465
532
|
});
|
|
466
533
|
|
|
467
534
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -630,71 +697,29 @@ test("sanitizeError strips Telegram bot token patterns", () => {
|
|
|
630
697
|
assert.ok(!result.includes("1234567890:ABC"), "should strip Telegram bot token");
|
|
631
698
|
});
|
|
632
699
|
|
|
633
|
-
test("DiscordAdapter source-level: sendPrompt sets threadUrl in ref", () => {
|
|
634
|
-
const adapterSrc = readFileSync(
|
|
635
|
-
join(__dirname, "..", "..", "remote-questions", "discord-adapter.ts"),
|
|
636
|
-
"utf-8",
|
|
637
|
-
);
|
|
638
|
-
assert.ok(
|
|
639
|
-
adapterSrc.includes("threadUrl: messageUrl"),
|
|
640
|
-
"sendPrompt should set threadUrl to the constructed message URL",
|
|
641
|
-
);
|
|
642
|
-
});
|
|
643
|
-
|
|
644
700
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
645
701
|
// Auth.json Token Hydration Tests
|
|
646
702
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
647
703
|
|
|
648
|
-
test("
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
join(__dirname, "..", "..", "remote-questions", "config.ts"),
|
|
668
|
-
"utf-8",
|
|
669
|
-
);
|
|
670
|
-
const statusFnIdx = configSrc.indexOf("export function getRemoteConfigStatus()");
|
|
671
|
-
const hydrationInStatus = configSrc.indexOf("hydrateRemoteTokensFromAuth()", statusFnIdx);
|
|
672
|
-
assert.ok(hydrationInStatus > statusFnIdx, "hydrateRemoteTokensFromAuth should be called inside getRemoteConfigStatus");
|
|
673
|
-
});
|
|
674
|
-
|
|
675
|
-
test("config source-level: AUTH_PROVIDER_ENV_MAP covers all three remote channels", () => {
|
|
676
|
-
const configSrc = readFileSync(
|
|
677
|
-
join(__dirname, "..", "..", "remote-questions", "config.ts"),
|
|
678
|
-
"utf-8",
|
|
679
|
-
);
|
|
680
|
-
assert.ok(configSrc.includes("discord_bot"), "AUTH_PROVIDER_ENV_MAP should include discord_bot");
|
|
681
|
-
assert.ok(configSrc.includes("slack_bot"), "AUTH_PROVIDER_ENV_MAP should include slack_bot");
|
|
682
|
-
assert.ok(configSrc.includes("telegram_bot"), "AUTH_PROVIDER_ENV_MAP should include telegram_bot");
|
|
683
|
-
assert.ok(configSrc.includes("DISCORD_BOT_TOKEN"), "should map discord_bot to DISCORD_BOT_TOKEN");
|
|
684
|
-
assert.ok(configSrc.includes("SLACK_BOT_TOKEN"), "should map slack_bot to SLACK_BOT_TOKEN");
|
|
685
|
-
assert.ok(configSrc.includes("TELEGRAM_BOT_TOKEN"), "should map telegram_bot to TELEGRAM_BOT_TOKEN");
|
|
686
|
-
});
|
|
687
|
-
|
|
688
|
-
test("config source-level: hydration skips env vars already set", () => {
|
|
689
|
-
const configSrc = readFileSync(
|
|
690
|
-
join(__dirname, "..", "..", "remote-questions", "config.ts"),
|
|
691
|
-
"utf-8",
|
|
692
|
-
);
|
|
693
|
-
// The guard that skips already-set vars must be present.
|
|
694
|
-
assert.ok(
|
|
695
|
-
configSrc.includes("!process.env[envVar]"),
|
|
696
|
-
"hydrateRemoteTokensFromAuth should skip env vars that are already populated",
|
|
697
|
-
);
|
|
704
|
+
test("resolveRemoteConfig uses configured channel and existing environment token", async () => {
|
|
705
|
+
const saved = process.env.SLACK_BOT_TOKEN;
|
|
706
|
+
try {
|
|
707
|
+
await withTempGsdHome(() => {
|
|
708
|
+
process.env.SLACK_BOT_TOKEN = "xoxb-existing";
|
|
709
|
+
saveRemoteQuestionsConfig("slack", "C12345678");
|
|
710
|
+
assert.deepEqual(resolveRemoteConfig(), {
|
|
711
|
+
channel: "slack",
|
|
712
|
+
channelId: "C12345678",
|
|
713
|
+
timeoutMs: 5 * 60 * 1000,
|
|
714
|
+
pollIntervalMs: 5 * 1000,
|
|
715
|
+
token: "xoxb-existing",
|
|
716
|
+
});
|
|
717
|
+
assert.equal(isRemoteConfigured(), true);
|
|
718
|
+
});
|
|
719
|
+
} finally {
|
|
720
|
+
if (saved === undefined) delete process.env.SLACK_BOT_TOKEN;
|
|
721
|
+
else process.env.SLACK_BOT_TOKEN = saved;
|
|
722
|
+
}
|
|
698
723
|
});
|
|
699
724
|
|
|
700
725
|
test("resolveRemoteConfig returns null when preferences are absent (no env side-effects)", () => {
|
|
@@ -725,150 +750,25 @@ test("resolveRemoteConfig returns null when preferences are absent (no env side-
|
|
|
725
750
|
}
|
|
726
751
|
});
|
|
727
752
|
|
|
728
|
-
test("
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
"utf-8",
|
|
750
|
-
);
|
|
751
|
-
|
|
752
|
-
const remoteCallIdx = src.indexOf("tryRemoteQuestions(params.questions");
|
|
753
|
-
const hasUIGuardIdx = src.indexOf("if (!ctx.hasUI)");
|
|
754
|
-
|
|
755
|
-
assert.ok(remoteCallIdx !== -1, "tryRemoteQuestions call should exist in ask-user-questions.ts");
|
|
756
|
-
assert.ok(hasUIGuardIdx !== -1, "!ctx.hasUI guard should exist in ask-user-questions.ts");
|
|
757
|
-
assert.ok(
|
|
758
|
-
remoteCallIdx < hasUIGuardIdx,
|
|
759
|
-
"tryRemoteQuestions must be called before the !ctx.hasUI guard — otherwise remote questions are skipped in interactive mode",
|
|
760
|
-
);
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
764
|
-
// Race model tests (#3810) — local TUI races against remote channel
|
|
765
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
766
|
-
|
|
767
|
-
test("ask-user-questions source-level: raceRemoteAndLocal function exists", () => {
|
|
768
|
-
const src = readFileSync(
|
|
769
|
-
join(__dirname, "..", "..", "ask-user-questions.ts"),
|
|
770
|
-
"utf-8",
|
|
771
|
-
);
|
|
772
|
-
assert.ok(
|
|
773
|
-
src.includes("async function raceRemoteAndLocal("),
|
|
774
|
-
"raceRemoteAndLocal helper should exist for racing local TUI against remote channel",
|
|
775
|
-
);
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
test("ask-user-questions source-level: race path uses isRemoteConfigured for routing", () => {
|
|
779
|
-
const src = readFileSync(
|
|
780
|
-
join(__dirname, "..", "..", "ask-user-questions.ts"),
|
|
781
|
-
"utf-8",
|
|
782
|
-
);
|
|
783
|
-
assert.ok(
|
|
784
|
-
src.includes("isRemoteConfigured()"),
|
|
785
|
-
"execute() should call isRemoteConfigured() for lightweight routing decision",
|
|
786
|
-
);
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
test("ask-user-questions source-level: race path checks both hasRemote and ctx.hasUI", () => {
|
|
790
|
-
// Regression: #3810 — the race should only activate when BOTH remote and local UI
|
|
791
|
-
// are available. Headless mode should still use remote-only, and no-remote should
|
|
792
|
-
// use local-only.
|
|
793
|
-
const src = readFileSync(
|
|
794
|
-
join(__dirname, "..", "..", "ask-user-questions.ts"),
|
|
795
|
-
"utf-8",
|
|
796
|
-
);
|
|
797
|
-
assert.ok(
|
|
798
|
-
src.includes("hasRemote && ctx.hasUI"),
|
|
799
|
-
"Race path should require both remote configured and local UI available",
|
|
800
|
-
);
|
|
801
|
-
assert.ok(
|
|
802
|
-
src.includes("hasRemote && !ctx.hasUI"),
|
|
803
|
-
"Headless path should handle remote-only when no local UI",
|
|
804
|
-
);
|
|
805
|
-
});
|
|
806
|
-
|
|
807
|
-
test("ask-user-questions source-level: race treats remote timeout as non-win", () => {
|
|
808
|
-
// Regression: the whole point of the race is that a remote timeout should NOT
|
|
809
|
-
// block the local TUI. The race helper must filter out timed_out results.
|
|
810
|
-
const src = readFileSync(
|
|
811
|
-
join(__dirname, "..", "..", "ask-user-questions.ts"),
|
|
812
|
-
"utf-8",
|
|
813
|
-
);
|
|
814
|
-
const raceFnStart = src.indexOf("async function raceRemoteAndLocal(");
|
|
815
|
-
const raceFnEnd = src.indexOf("\n}", raceFnStart);
|
|
816
|
-
const raceFnBody = src.slice(raceFnStart, raceFnEnd);
|
|
817
|
-
assert.ok(
|
|
818
|
-
raceFnBody.includes("timed_out"),
|
|
819
|
-
"raceRemoteAndLocal should check for timed_out in remote results",
|
|
820
|
-
);
|
|
821
|
-
assert.ok(
|
|
822
|
-
raceFnBody.includes("details?.error"),
|
|
823
|
-
"raceRemoteAndLocal should check for error in remote results",
|
|
824
|
-
);
|
|
825
|
-
});
|
|
826
|
-
|
|
827
|
-
test("ask-user-questions source-level: race uses AbortController to cancel loser", () => {
|
|
828
|
-
const src = readFileSync(
|
|
829
|
-
join(__dirname, "..", "..", "ask-user-questions.ts"),
|
|
830
|
-
"utf-8",
|
|
831
|
-
);
|
|
832
|
-
assert.ok(
|
|
833
|
-
src.includes("new AbortController()"),
|
|
834
|
-
"Race path should create an AbortController for cancellation",
|
|
835
|
-
);
|
|
836
|
-
assert.ok(
|
|
837
|
-
src.includes("controller.abort()"),
|
|
838
|
-
"raceRemoteAndLocal should abort the controller to cancel the losing side",
|
|
839
|
-
);
|
|
840
|
-
});
|
|
841
|
-
|
|
842
|
-
test("manager source-level: isRemoteConfigured export exists", () => {
|
|
843
|
-
const src = readFileSync(
|
|
844
|
-
join(__dirname, "..", "..", "remote-questions", "manager.ts"),
|
|
845
|
-
"utf-8",
|
|
846
|
-
);
|
|
847
|
-
assert.ok(
|
|
848
|
-
src.includes("export function isRemoteConfigured()"),
|
|
849
|
-
"manager.ts should export isRemoteConfigured for lightweight config checking",
|
|
850
|
-
);
|
|
851
|
-
// Must delegate to resolveRemoteConfig — no separate config parsing
|
|
852
|
-
const fnStart = src.indexOf("export function isRemoteConfigured()");
|
|
853
|
-
const fnEnd = src.indexOf("\n}", fnStart);
|
|
854
|
-
const fnBody = src.slice(fnStart, fnEnd);
|
|
855
|
-
assert.ok(
|
|
856
|
-
fnBody.includes("resolveRemoteConfig()"),
|
|
857
|
-
"isRemoteConfigured should delegate to resolveRemoteConfig",
|
|
858
|
-
);
|
|
859
|
-
});
|
|
860
|
-
|
|
861
|
-
test("config source-level: removeProviderToken uses auth.remove not auth.set with empty key", () => {
|
|
862
|
-
const commandSrc = readFileSync(
|
|
863
|
-
join(__dirname, "..", "..", "remote-questions", "remote-command.ts"),
|
|
864
|
-
"utf-8",
|
|
865
|
-
);
|
|
866
|
-
// removeProviderToken should call auth.remove(provider), not auth.set(provider, { key: "" }).
|
|
867
|
-
// Setting an empty key pollutes the credentials array and shadows valid tokens.
|
|
868
|
-
const fnStart = commandSrc.indexOf("function removeProviderToken");
|
|
869
|
-
assert.ok(fnStart !== -1, "removeProviderToken should exist");
|
|
870
|
-
const fnEnd = commandSrc.indexOf("\n}", fnStart);
|
|
871
|
-
const fnBody = commandSrc.slice(fnStart, fnEnd);
|
|
872
|
-
assert.ok(fnBody.includes("auth.remove("), "removeProviderToken should call auth.remove()");
|
|
873
|
-
assert.ok(!fnBody.includes('key: ""'), "removeProviderToken should not set an empty key");
|
|
753
|
+
test("remote disconnect removes active env token and disables remote config", async () => {
|
|
754
|
+
const saved = process.env.DISCORD_BOT_TOKEN;
|
|
755
|
+
try {
|
|
756
|
+
await withTempGsdHome(async () => {
|
|
757
|
+
process.env.DISCORD_BOT_TOKEN = "discord-token";
|
|
758
|
+
saveRemoteQuestionsConfig("discord", "12345678901234567");
|
|
759
|
+
assert.equal(isRemoteConfigured(), true);
|
|
760
|
+
|
|
761
|
+
const notifications: string[] = [];
|
|
762
|
+
await handleRemote("disconnect", {
|
|
763
|
+
ui: { notify(message: string) { notifications.push(message); } },
|
|
764
|
+
} as any, {} as any);
|
|
765
|
+
|
|
766
|
+
assert.equal(process.env.DISCORD_BOT_TOKEN, undefined);
|
|
767
|
+
assert.equal(resolveRemoteConfig(), null);
|
|
768
|
+
assert.ok(notifications.some((message) => message.includes("disconnected")));
|
|
769
|
+
});
|
|
770
|
+
} finally {
|
|
771
|
+
if (saved === undefined) delete process.env.DISCORD_BOT_TOKEN;
|
|
772
|
+
else process.env.DISCORD_BOT_TOKEN = saved;
|
|
773
|
+
}
|
|
874
774
|
});
|
|
@@ -1,38 +1,50 @@
|
|
|
1
|
-
// GSD2 — Regression test for
|
|
2
|
-
// Ensures auto.ts imports resource-loader via package resolution, not a
|
|
3
|
-
// relative path that breaks when deployed to ~/.gsd/agent/extensions/gsd/.
|
|
1
|
+
// GSD2 — Regression test for deployed resource-loader resolution behavior
|
|
4
2
|
|
|
5
3
|
import { describe, test } from "node:test";
|
|
6
4
|
import assert from "node:assert/strict";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
8
5
|
import { join } from "node:path";
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import { pathToFileURL } from "node:url";
|
|
7
|
+
import { refreshResumeResourcesAndDb } from "../auto.ts";
|
|
11
8
|
|
|
12
9
|
describe("resource-loader import path", () => {
|
|
13
|
-
test("
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
test("refreshResumeResourcesAndDb resolves resource-loader from GSD_PKG_ROOT", async () => {
|
|
11
|
+
const pkgRoot = "/tmp/gsd-pkg-root";
|
|
12
|
+
const agentDir = "/tmp/gsd-agent";
|
|
13
|
+
const basePath = "/tmp/project-root";
|
|
14
|
+
const imports: string[] = [];
|
|
15
|
+
const initializedDirs: string[] = [];
|
|
16
|
+
const openedProjectRoots: string[] = [];
|
|
17
|
+
let primed = false;
|
|
18
|
+
|
|
19
|
+
await refreshResumeResourcesAndDb(basePath, {
|
|
20
|
+
env: {
|
|
21
|
+
GSD_PKG_ROOT: pkgRoot,
|
|
22
|
+
GSD_CODING_AGENT_DIR: agentDir,
|
|
23
|
+
} as NodeJS.ProcessEnv,
|
|
24
|
+
importModule: async (specifier: string) => {
|
|
25
|
+
imports.push(specifier);
|
|
26
|
+
if (specifier.endsWith("resource-loader.js")) {
|
|
27
|
+
return {
|
|
28
|
+
initResources: (dir: string) => initializedDirs.push(dir),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (specifier === "./prompt-loader.js") {
|
|
32
|
+
return {
|
|
33
|
+
primeCache: () => {
|
|
34
|
+
primed = true;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`Unexpected import ${specifier}`);
|
|
39
|
+
},
|
|
40
|
+
openProjectDb: async (projectRoot: string) => {
|
|
41
|
+
openedProjectRoots.push(projectRoot);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
24
44
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
assert.ok(
|
|
30
|
-
autoSrc.includes('process.env.GSD_PKG_ROOT'),
|
|
31
|
-
"auto.ts should use GSD_PKG_ROOT to resolve resource-loader",
|
|
32
|
-
);
|
|
33
|
-
assert.ok(
|
|
34
|
-
autoSrc.includes('pathToFileURL'),
|
|
35
|
-
"auto.ts should convert path to file URL for cross-platform import()",
|
|
36
|
-
);
|
|
45
|
+
assert.equal(imports[0], pathToFileURL(join(pkgRoot, "dist", "resource-loader.js")).href);
|
|
46
|
+
assert.deepEqual(initializedDirs, [agentDir]);
|
|
47
|
+
assert.equal(primed, true);
|
|
48
|
+
assert.deepEqual(openedProjectRoots, [basePath]);
|
|
37
49
|
});
|
|
38
50
|
});
|