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
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// GSD-2 - Behavior coverage for tool target metadata.
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
|
|
9
|
+
import { createEditTool } from "./edit.js";
|
|
10
|
+
import { createFindTool } from "./find.js";
|
|
11
|
+
import { createGrepTool } from "./grep.js";
|
|
12
|
+
import { createLsTool } from "./ls.js";
|
|
13
|
+
import { createReadTool } from "./read.js";
|
|
14
|
+
import { createWriteTool } from "./write.js";
|
|
15
|
+
|
|
16
|
+
test("read metadata records resolved path without changing output text", async () => {
|
|
17
|
+
const cwd = mkdtempSync(join(tmpdir(), "gsd-read-target-"));
|
|
18
|
+
try {
|
|
19
|
+
const filePath = join(cwd, "fixture.txt");
|
|
20
|
+
writeFileSync(filePath, "one\ntwo\nthree\n", "utf8");
|
|
21
|
+
|
|
22
|
+
const result = await createReadTool(cwd).execute("read-1", {
|
|
23
|
+
path: "fixture.txt",
|
|
24
|
+
offset: 2,
|
|
25
|
+
limit: 1,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
assert.equal(result.details?.target?.resolvedPath, filePath);
|
|
29
|
+
assert.deepEqual(result.details?.target?.range, { start: 2, end: 2 });
|
|
30
|
+
assert.equal(result.content[0]?.type, "text");
|
|
31
|
+
assert.match(result.content[0]?.text ?? "", /^two/);
|
|
32
|
+
assert.equal((result.content[0]?.text ?? "").includes(filePath), false);
|
|
33
|
+
|
|
34
|
+
const zeroOffsetResult = await createReadTool(cwd).execute("read-zero-offset", {
|
|
35
|
+
path: "fixture.txt",
|
|
36
|
+
offset: 0,
|
|
37
|
+
limit: 1,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
assert.deepEqual(zeroOffsetResult.details?.target?.range, { start: 1, end: 1 });
|
|
41
|
+
} finally {
|
|
42
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("write metadata records resolved path without changing output text", async () => {
|
|
47
|
+
const cwd = mkdtempSync(join(tmpdir(), "gsd-write-target-"));
|
|
48
|
+
try {
|
|
49
|
+
const filePath = join(cwd, "out.txt");
|
|
50
|
+
const result = await createWriteTool(cwd).execute("write-1", {
|
|
51
|
+
path: "out.txt",
|
|
52
|
+
content: "hello",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
assert.equal(result.details?.target?.resolvedPath, filePath);
|
|
56
|
+
assert.equal(result.content[0]?.type, "text");
|
|
57
|
+
assert.equal(result.content[0]?.text, "Successfully wrote 5 bytes to out.txt");
|
|
58
|
+
} finally {
|
|
59
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("edit metadata records first changed line and resolved path", async () => {
|
|
64
|
+
const cwd = mkdtempSync(join(tmpdir(), "gsd-edit-target-"));
|
|
65
|
+
try {
|
|
66
|
+
const filePath = join(cwd, "edit.txt");
|
|
67
|
+
writeFileSync(filePath, "alpha\nbeta\ngamma\n", "utf8");
|
|
68
|
+
|
|
69
|
+
const result = await createEditTool(cwd).execute("edit-1", {
|
|
70
|
+
path: "edit.txt",
|
|
71
|
+
oldText: "beta",
|
|
72
|
+
newText: "delta",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
assert.equal(result.details?.target?.resolvedPath, filePath);
|
|
76
|
+
assert.equal(result.details?.target?.line, 2);
|
|
77
|
+
assert.equal(result.details?.firstChangedLine, 2);
|
|
78
|
+
} finally {
|
|
79
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("list and find metadata record resolved targets", async () => {
|
|
84
|
+
const cwd = mkdtempSync(join(tmpdir(), "gsd-search-target-"));
|
|
85
|
+
try {
|
|
86
|
+
const srcPath = join(cwd, "src");
|
|
87
|
+
const filePath = join(srcPath, "needle.txt");
|
|
88
|
+
mkdirSync(srcPath);
|
|
89
|
+
writeFileSync(filePath, "needle\n", "utf8");
|
|
90
|
+
|
|
91
|
+
const lsResult = await createLsTool(cwd).execute("ls-1", { path: "src" });
|
|
92
|
+
assert.equal(lsResult.details?.target?.resolvedPath, srcPath);
|
|
93
|
+
|
|
94
|
+
const findResult = await createFindTool(cwd, {
|
|
95
|
+
operations: {
|
|
96
|
+
exists: () => true,
|
|
97
|
+
glob: async () => [filePath],
|
|
98
|
+
},
|
|
99
|
+
}).execute("find-1", { path: "src", pattern: "needle" });
|
|
100
|
+
assert.equal(findResult.details?.target?.resolvedPath, srcPath);
|
|
101
|
+
assert.equal(findResult.details?.target?.pattern, "needle");
|
|
102
|
+
} finally {
|
|
103
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("grep metadata records resolved search target", async () => {
|
|
108
|
+
const cwd = mkdtempSync(join(tmpdir(), "gsd-grep-target-"));
|
|
109
|
+
try {
|
|
110
|
+
const srcPath = join(cwd, "src");
|
|
111
|
+
mkdirSync(srcPath);
|
|
112
|
+
writeFileSync(join(srcPath, "needle.txt"), "needle\n", "utf8");
|
|
113
|
+
|
|
114
|
+
const result = await createGrepTool(cwd).execute("grep-1", {
|
|
115
|
+
path: "src",
|
|
116
|
+
pattern: "needle",
|
|
117
|
+
literal: true,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
assert.equal(result.details?.target?.resolvedPath, srcPath);
|
|
121
|
+
assert.equal(result.details?.target?.pattern, "needle");
|
|
122
|
+
assert.equal(result.content[0]?.type, "text");
|
|
123
|
+
assert.match(result.content[0]?.text ?? "", /needle\.txt:1: needle/);
|
|
124
|
+
} finally {
|
|
125
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// GSD-2 - Shared target metadata for tool output rendering.
|
|
2
|
+
|
|
3
|
+
export type ToolTargetKind = "file" | "directory" | "search" | "command";
|
|
4
|
+
|
|
5
|
+
export type ToolTargetAction = "read" | "write" | "edit" | "list" | "find" | "grep" | "bash";
|
|
6
|
+
|
|
7
|
+
export interface ToolTargetRange {
|
|
8
|
+
start: number;
|
|
9
|
+
end?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ToolTargetMetadata {
|
|
13
|
+
kind: ToolTargetKind;
|
|
14
|
+
action: ToolTargetAction;
|
|
15
|
+
inputPath?: string;
|
|
16
|
+
resolvedPath?: string;
|
|
17
|
+
pattern?: string;
|
|
18
|
+
glob?: string;
|
|
19
|
+
line?: number;
|
|
20
|
+
range?: ToolTargetRange;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createToolTarget(target: ToolTargetMetadata): ToolTargetMetadata {
|
|
24
|
+
return target;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createReadFileTarget(
|
|
28
|
+
inputPath: string,
|
|
29
|
+
resolvedPath: string,
|
|
30
|
+
offset?: number,
|
|
31
|
+
limit?: number,
|
|
32
|
+
): ToolTargetMetadata {
|
|
33
|
+
const effectiveOffset = Math.max(1, offset ?? 1);
|
|
34
|
+
|
|
35
|
+
return createToolTarget({
|
|
36
|
+
kind: "file",
|
|
37
|
+
action: "read",
|
|
38
|
+
inputPath,
|
|
39
|
+
resolvedPath,
|
|
40
|
+
range:
|
|
41
|
+
offset !== undefined || limit !== undefined
|
|
42
|
+
? {
|
|
43
|
+
start: effectiveOffset,
|
|
44
|
+
end: limit !== undefined ? effectiveOffset + Math.max(0, limit - 1) : undefined,
|
|
45
|
+
}
|
|
46
|
+
: undefined,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -4,6 +4,7 @@ import { mkdir as fsMkdir, writeFile as fsWriteFile } from "fs/promises";
|
|
|
4
4
|
import { dirname } from "path";
|
|
5
5
|
import { notifyFileChanged } from "../lsp/client.js";
|
|
6
6
|
import { resolveToCwd } from "./path-utils.js";
|
|
7
|
+
import { createToolTarget, type ToolTargetMetadata } from "./tool-target.js";
|
|
7
8
|
|
|
8
9
|
const writeSchema = Type.Object({
|
|
9
10
|
path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
|
|
@@ -12,6 +13,10 @@ const writeSchema = Type.Object({
|
|
|
12
13
|
|
|
13
14
|
export type WriteToolInput = Static<typeof writeSchema>;
|
|
14
15
|
|
|
16
|
+
export interface WriteToolDetails {
|
|
17
|
+
target?: ToolTargetMetadata;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
21
|
* Pluggable operations for the write tool.
|
|
17
22
|
* Override these to delegate file writing to remote systems (e.g., SSH).
|
|
@@ -50,7 +55,7 @@ export function createWriteTool(cwd: string, options?: WriteToolOptions): AgentT
|
|
|
50
55
|
const absolutePath = resolveToCwd(path, cwd);
|
|
51
56
|
const dir = dirname(absolutePath);
|
|
52
57
|
|
|
53
|
-
return new Promise<{ content: Array<{ type: "text"; text: string }>; details: undefined }>(
|
|
58
|
+
return new Promise<{ content: Array<{ type: "text"; text: string }>; details: WriteToolDetails | undefined }>(
|
|
54
59
|
(resolve, reject) => {
|
|
55
60
|
// Check if already aborted
|
|
56
61
|
if (signal?.aborted) {
|
|
@@ -98,7 +103,14 @@ export function createWriteTool(cwd: string, options?: WriteToolOptions): AgentT
|
|
|
98
103
|
|
|
99
104
|
resolve({
|
|
100
105
|
content: [{ type: "text", text: `Successfully wrote ${content.length} bytes to ${path}` }],
|
|
101
|
-
details:
|
|
106
|
+
details: {
|
|
107
|
+
target: createToolTarget({
|
|
108
|
+
kind: "file",
|
|
109
|
+
action: "write",
|
|
110
|
+
inputPath: path,
|
|
111
|
+
resolvedPath: absolutePath,
|
|
112
|
+
}),
|
|
113
|
+
},
|
|
102
114
|
});
|
|
103
115
|
} catch (error: any) {
|
|
104
116
|
// Clean up abort handler
|
package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts
CHANGED
|
@@ -113,10 +113,124 @@ describe("ToolExecutionComponent", () => {
|
|
|
113
113
|
assert.deepEqual(component.getRollupPhase()?.label, "Other tool actions");
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
+
test("renders compact read rows with target metadata", () => {
|
|
117
|
+
const rendered = renderToolCollapsed(
|
|
118
|
+
"read",
|
|
119
|
+
{ path: "src/Inspector.tsx" },
|
|
120
|
+
{
|
|
121
|
+
content: [{ type: "text", text: "source" }],
|
|
122
|
+
isError: false,
|
|
123
|
+
details: {
|
|
124
|
+
target: {
|
|
125
|
+
kind: "file",
|
|
126
|
+
action: "read",
|
|
127
|
+
inputPath: "src/Inspector.tsx",
|
|
128
|
+
resolvedPath: "/tmp/project/src/Inspector.tsx",
|
|
129
|
+
range: { start: 4, end: 12 },
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
assert.match(rendered, /read .*src\/Inspector\.tsx:4-12/);
|
|
136
|
+
assert.doesNotMatch(rendered, /source/);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("renders compact edit rows with target metadata", () => {
|
|
140
|
+
const rendered = renderToolCollapsed(
|
|
141
|
+
"edit",
|
|
142
|
+
{ path: "src/Inspector.tsx" },
|
|
143
|
+
{
|
|
144
|
+
content: [{ type: "text", text: "Updated src/Inspector.tsx" }],
|
|
145
|
+
isError: false,
|
|
146
|
+
details: {
|
|
147
|
+
target: {
|
|
148
|
+
kind: "file",
|
|
149
|
+
action: "edit",
|
|
150
|
+
inputPath: "src/Inspector.tsx",
|
|
151
|
+
resolvedPath: "/tmp/project/src/Inspector.tsx",
|
|
152
|
+
line: 42,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
assert.match(rendered, /edit .*src\/Inspector\.tsx:42/);
|
|
159
|
+
assert.doesNotMatch(rendered, /Updated src\/Inspector\.tsx/);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("renders compact write rows with target metadata", () => {
|
|
163
|
+
const rendered = renderToolCollapsed(
|
|
164
|
+
"write",
|
|
165
|
+
{ path: "src/output.ts", content: "ok" },
|
|
166
|
+
{
|
|
167
|
+
content: [{ type: "text", text: "Successfully wrote 2 bytes to src/output.ts" }],
|
|
168
|
+
isError: false,
|
|
169
|
+
details: {
|
|
170
|
+
target: {
|
|
171
|
+
kind: "file",
|
|
172
|
+
action: "write",
|
|
173
|
+
inputPath: "src/output.ts",
|
|
174
|
+
resolvedPath: "/tmp/project/src/output.ts",
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
assert.match(rendered, /write .*src\/output\.ts/);
|
|
181
|
+
assert.doesNotMatch(rendered, /Successfully wrote/);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("renders compact bash rows with command preview", () => {
|
|
185
|
+
const rendered = renderToolCollapsed(
|
|
186
|
+
"bash",
|
|
187
|
+
{ command: "npm run typecheck -- --watch false" },
|
|
188
|
+
{ content: [{ type: "text", text: "ok" }], isError: false, details: { cwd: "/tmp/project" } },
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
assert.match(rendered, /bash npm run typecheck -- --watch false/);
|
|
192
|
+
assert.doesNotMatch(rendered, /\bok\b/);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("keeps failed tools expanded and error visible", () => {
|
|
196
|
+
const rendered = renderToolCollapsed(
|
|
197
|
+
"edit",
|
|
198
|
+
{ path: "src/Inspector.tsx" },
|
|
199
|
+
{
|
|
200
|
+
content: [{ type: "text", text: "Could not find target text" }],
|
|
201
|
+
isError: true,
|
|
202
|
+
details: {
|
|
203
|
+
target: {
|
|
204
|
+
kind: "file",
|
|
205
|
+
action: "edit",
|
|
206
|
+
inputPath: "src/Inspector.tsx",
|
|
207
|
+
resolvedPath: "/tmp/project/src/Inspector.tsx",
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
assert.match(rendered, /Could not find target text/);
|
|
214
|
+
assert.match(rendered, /edit/);
|
|
215
|
+
});
|
|
216
|
+
|
|
116
217
|
test("renders phase-based summaries for rolled-up tool executions", () => {
|
|
117
218
|
const phases: ToolExecutionPhase[] = [
|
|
118
219
|
{ label: "Setup / shell", count: 6, durationMs: 12 },
|
|
119
|
-
{
|
|
220
|
+
{
|
|
221
|
+
label: "Context reads",
|
|
222
|
+
count: 4,
|
|
223
|
+
durationMs: 6,
|
|
224
|
+
actionLabel: "read",
|
|
225
|
+
targets: ["/tmp/project/src/a.ts", "/tmp/project/src/b.ts"],
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
label: "File changes",
|
|
229
|
+
count: 3,
|
|
230
|
+
durationMs: 5,
|
|
231
|
+
actionLabel: "edit",
|
|
232
|
+
targets: ["/tmp/project/src/Inspector.tsx:42", "/tmp/project/src/CompareView.tsx:8"],
|
|
233
|
+
},
|
|
120
234
|
{ label: "Requirement writes", count: 4, durationMs: 4 },
|
|
121
235
|
{ label: "Memory lookups", count: 4, durationMs: 4 },
|
|
122
236
|
{ label: "Finalization", count: 1, durationMs: 1 },
|
|
@@ -124,7 +238,10 @@ describe("ToolExecutionComponent", () => {
|
|
|
124
238
|
const rendered = stripAnsi(new ToolPhaseSummaryComponent(phases).render(120).join("\n"));
|
|
125
239
|
|
|
126
240
|
assert.match(rendered, /Setup \/ shell 6 actions\s+success · 12ms/);
|
|
127
|
-
assert.match(rendered, /Context reads
|
|
241
|
+
assert.match(rendered, /Context reads · 2 files\s+success · 6ms/);
|
|
242
|
+
assert.match(rendered, /src\/a\.ts/);
|
|
243
|
+
assert.match(rendered, /File changes · 2 files, 3 edits\s+success · 5ms/);
|
|
244
|
+
assert.match(rendered, /src\/Inspector\.tsx:42/);
|
|
128
245
|
assert.match(rendered, /Requirement writes 4 actions\s+success · 4ms/);
|
|
129
246
|
assert.match(rendered, /Memory lookups 4 actions\s+success · 4ms/);
|
|
130
247
|
assert.match(rendered, /Finalization 1 action\s+success · 1ms/);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Runtime tests for TUI tool cards, success notifications, and blocking errors.
|
|
1
3
|
// GSD2 TUI Tests - Runtime coverage for tool-card cleanup and success notification rendering.
|
|
2
4
|
// Runtime regression tests for the post-compaction tool-card cleanup and the
|
|
3
5
|
// green-bordered success-notification rendering. Replaces the source-grep
|
|
@@ -18,7 +20,7 @@ import { Container, Text } from "@gsd/pi-tui";
|
|
|
18
20
|
import stripAnsi from "strip-ansi";
|
|
19
21
|
|
|
20
22
|
import { initTheme, theme } from "../theme/theme.js";
|
|
21
|
-
import { renderExtensionNotifyInChat, shouldRenderExtensionNotifyInChat } from "../interactive-mode.js";
|
|
23
|
+
import { renderBlockingErrorBanner, renderExtensionNotifyInChat, shouldRenderExtensionNotifyInChat } from "../interactive-mode.js";
|
|
22
24
|
import { DynamicBorder } from "./dynamic-border.js";
|
|
23
25
|
import { ToolExecutionComponent } from "./tool-execution.js";
|
|
24
26
|
|
|
@@ -58,6 +60,34 @@ describe("Extension warning notifications", () => {
|
|
|
58
60
|
});
|
|
59
61
|
});
|
|
60
62
|
|
|
63
|
+
describe("Blocking error banner", () => {
|
|
64
|
+
it("keeps full error notifications renderable outside chat history", () => {
|
|
65
|
+
const banner = new Container();
|
|
66
|
+
const message = [
|
|
67
|
+
"Pre-execution checks failed: 3 blocking issues found",
|
|
68
|
+
" - [file] lib/types.ts: Task T01 references 'lib/types.ts'",
|
|
69
|
+
"See .gsd/milestones/M001/slices/S02/S02-PRE-EXEC-VERIFY.json for full details.",
|
|
70
|
+
].join("\n");
|
|
71
|
+
|
|
72
|
+
renderBlockingErrorBanner(banner, message);
|
|
73
|
+
|
|
74
|
+
const rendered = banner.render(140).map(stripAnsi).join("\n");
|
|
75
|
+
assert.match(rendered, /Error: Pre-execution checks failed: 3 blocking issues found/);
|
|
76
|
+
assert.match(rendered, /Task T01 references 'lib\/types\.ts'/);
|
|
77
|
+
assert.match(rendered, /S02-PRE-EXEC-VERIFY\.json/);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("clears the sticky banner when the blocking error is cleared", () => {
|
|
81
|
+
const banner = new Container();
|
|
82
|
+
|
|
83
|
+
renderBlockingErrorBanner(banner, "Provider failed");
|
|
84
|
+
assert.match(banner.render(80).map(stripAnsi).join("\n"), /Provider failed/);
|
|
85
|
+
|
|
86
|
+
renderBlockingErrorBanner(banner, undefined);
|
|
87
|
+
assert.equal(banner.render(80).map(stripAnsi).join("\n"), "");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
61
91
|
interface MockTui {
|
|
62
92
|
renderCount: number;
|
|
63
93
|
requestRender(): void;
|
|
@@ -111,9 +111,10 @@ function renderToolFrame(
|
|
|
111
111
|
const statusColor = opts.tone === "error" ? "toolError" : opts.tone === "pending" ? "toolRunning" : "toolSuccess";
|
|
112
112
|
const leftStyled = theme.fg(labelColor, theme.bold(opts.label));
|
|
113
113
|
const rightStyled = theme.fg(statusColor, opts.status);
|
|
114
|
-
const
|
|
114
|
+
const titleWidth = Math.max(1, outerWidth - 4);
|
|
115
|
+
const gap = Math.max(1, titleWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled));
|
|
115
116
|
const headerRow = `${leftStyled}${" ".repeat(gap)}${rightStyled}`;
|
|
116
|
-
const headerPad = Math.max(0,
|
|
117
|
+
const headerPad = Math.max(0, titleWidth - visibleWidth(headerRow));
|
|
117
118
|
|
|
118
119
|
const sourceLines = trimOuterBlankLines(contentLines);
|
|
119
120
|
const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
|
|
@@ -122,7 +123,7 @@ function renderToolFrame(
|
|
|
122
123
|
});
|
|
123
124
|
|
|
124
125
|
return style()
|
|
125
|
-
.border("
|
|
126
|
+
.border("rounded")
|
|
126
127
|
.borderColor((line) => theme.fg(line.startsWith("─") ? topColor : borderColor, line))
|
|
127
128
|
.title(headerRow + " ".repeat(headerPad))
|
|
128
129
|
.render(bodyLines, outerWidth);
|
|
@@ -157,6 +158,22 @@ export type ToolExecutionPhase = {
|
|
|
157
158
|
label: string;
|
|
158
159
|
count: number;
|
|
159
160
|
durationMs: number;
|
|
161
|
+
targets?: string[];
|
|
162
|
+
actionLabel?: string;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
type ToolTargetMetadata = {
|
|
166
|
+
kind?: string;
|
|
167
|
+
action?: string;
|
|
168
|
+
inputPath?: string;
|
|
169
|
+
resolvedPath?: string;
|
|
170
|
+
pattern?: string;
|
|
171
|
+
glob?: string;
|
|
172
|
+
line?: number;
|
|
173
|
+
range?: {
|
|
174
|
+
start?: number;
|
|
175
|
+
end?: number;
|
|
176
|
+
};
|
|
160
177
|
};
|
|
161
178
|
|
|
162
179
|
function formatElapsed(ms: number): string {
|
|
@@ -164,6 +181,104 @@ function formatElapsed(ms: number): string {
|
|
|
164
181
|
return `${Math.max(1, Math.round(ms / 1000))}s`;
|
|
165
182
|
}
|
|
166
183
|
|
|
184
|
+
function formatCommandPreview(command: string): string {
|
|
185
|
+
return truncateToWidth(command.replace(/\s+/g, " ").trim(), 64, "");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function appendLineOrRange(displayPath: string | undefined, target: ToolTargetMetadata): string | undefined {
|
|
189
|
+
if (!displayPath) return undefined;
|
|
190
|
+
if (typeof target.line === "number" && Number.isFinite(target.line)) {
|
|
191
|
+
return `${displayPath}:${target.line}`;
|
|
192
|
+
}
|
|
193
|
+
const start = target.range?.start;
|
|
194
|
+
if (typeof start === "number" && Number.isFinite(start)) {
|
|
195
|
+
const end = target.range?.end;
|
|
196
|
+
const suffix =
|
|
197
|
+
typeof end === "number" && Number.isFinite(end) && end !== start
|
|
198
|
+
? `${start}-${end}`
|
|
199
|
+
: `${start}`;
|
|
200
|
+
return `${displayPath}:${suffix}`;
|
|
201
|
+
}
|
|
202
|
+
return displayPath;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function formatToolTarget(target: ToolTargetMetadata): string | undefined {
|
|
206
|
+
const path = target.resolvedPath || target.inputPath;
|
|
207
|
+
const displayPath = path ? shortenPath(path) : undefined;
|
|
208
|
+
if (target.kind === "search") {
|
|
209
|
+
const searchTarget = displayPath ?? target.inputPath ?? ".";
|
|
210
|
+
const label = target.pattern ? `${target.pattern} in ${searchTarget}` : searchTarget;
|
|
211
|
+
return target.glob ? `${label} (${target.glob})` : label;
|
|
212
|
+
}
|
|
213
|
+
return appendLineOrRange(displayPath, target);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function formatArgsPathTarget(path: string | null, args: Record<string, unknown>): string | undefined {
|
|
217
|
+
if (!path) return undefined;
|
|
218
|
+
const start = typeof args.offset === "number" ? args.offset : undefined;
|
|
219
|
+
const limit = typeof args.limit === "number" ? args.limit : undefined;
|
|
220
|
+
const range =
|
|
221
|
+
start !== undefined || limit !== undefined
|
|
222
|
+
? {
|
|
223
|
+
start: start ?? 1,
|
|
224
|
+
end: limit !== undefined ? (start ?? 1) + Math.max(0, limit - 1) : undefined,
|
|
225
|
+
}
|
|
226
|
+
: undefined;
|
|
227
|
+
return appendLineOrRange(shortenPath(path), { range });
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function stripLineSuffix(target: string): string {
|
|
231
|
+
return target.replace(/:\d+(?:-\d+)?$/, "");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function uniqueTargets(targets: string[] | undefined): string[] {
|
|
235
|
+
const seen = new Set<string>();
|
|
236
|
+
const unique: string[] = [];
|
|
237
|
+
for (const target of targets ?? []) {
|
|
238
|
+
if (!target || seen.has(target)) continue;
|
|
239
|
+
seen.add(target);
|
|
240
|
+
unique.push(target);
|
|
241
|
+
}
|
|
242
|
+
return unique;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function summarizePhaseLabel(phase: ToolExecutionPhase): string {
|
|
246
|
+
const phaseTargets = uniqueTargets(phase.targets);
|
|
247
|
+
const baseTargets = uniqueTargets(phaseTargets.map(stripLineSuffix));
|
|
248
|
+
if (phase.label === "File changes" && baseTargets.length > 0) {
|
|
249
|
+
const fileWord = baseTargets.length === 1 ? "file" : "files";
|
|
250
|
+
const actionWord =
|
|
251
|
+
phase.actionLabel === "write"
|
|
252
|
+
? phase.count === 1
|
|
253
|
+
? "write"
|
|
254
|
+
: "writes"
|
|
255
|
+
: phase.actionLabel === undefined
|
|
256
|
+
? phase.count === 1
|
|
257
|
+
? "action"
|
|
258
|
+
: "actions"
|
|
259
|
+
: phase.count === 1
|
|
260
|
+
? "edit"
|
|
261
|
+
: "edits";
|
|
262
|
+
return `${phase.label} · ${baseTargets.length} ${fileWord}, ${phase.count} ${actionWord}`;
|
|
263
|
+
}
|
|
264
|
+
if (phase.label === "Context reads" && baseTargets.length > 0) {
|
|
265
|
+
const fileWord = baseTargets.length === 1 ? "file" : "files";
|
|
266
|
+
return `${phase.label} · ${baseTargets.length} ${fileWord}`;
|
|
267
|
+
}
|
|
268
|
+
if (phase.label === "Setup / shell" && phaseTargets.length > 0) {
|
|
269
|
+
return `${phase.label} · ${phase.count} ${phase.count === 1 ? "command" : "commands"}`;
|
|
270
|
+
}
|
|
271
|
+
return `${phase.label} ${phase.count} ${phase.count === 1 ? "action" : "actions"}`;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function summarizePhaseTargets(phase: ToolExecutionPhase, width: number): string | undefined {
|
|
275
|
+
const phaseTargets = uniqueTargets(phase.targets);
|
|
276
|
+
if (phaseTargets.length === 0) return undefined;
|
|
277
|
+
const shown = phaseTargets.slice(0, 3);
|
|
278
|
+
const suffix = phaseTargets.length > shown.length ? ` +${phaseTargets.length - shown.length} more` : "";
|
|
279
|
+
return truncateToWidth(shown.join(" · ") + suffix, width, "");
|
|
280
|
+
}
|
|
281
|
+
|
|
167
282
|
/**
|
|
168
283
|
* Format tool args for the generic-renderer fallback. Produces a one-line
|
|
169
284
|
* `k=v, k=v` summary when every value is a primitive that fits inline; falls
|
|
@@ -607,10 +722,13 @@ export class ToolExecutionComponent extends Container {
|
|
|
607
722
|
if (!this.shouldRenderCompactSuccess()) return null;
|
|
608
723
|
const label = this.getPhaseLabel();
|
|
609
724
|
const endedAt = this.endedAt ?? Date.now();
|
|
725
|
+
const target = this.getCompactTarget();
|
|
610
726
|
return {
|
|
611
727
|
label,
|
|
612
728
|
count: 1,
|
|
613
729
|
durationMs: Math.max(0, endedAt - this.startedAt),
|
|
730
|
+
targets: target ? [target] : undefined,
|
|
731
|
+
actionLabel: this.getCompactAction(),
|
|
614
732
|
};
|
|
615
733
|
}
|
|
616
734
|
|
|
@@ -631,7 +749,52 @@ export class ToolExecutionComponent extends Container {
|
|
|
631
749
|
}
|
|
632
750
|
|
|
633
751
|
private getCompactSummary(frameLabel: string): string {
|
|
634
|
-
|
|
752
|
+
if (this.normalizedToolName === "bash") {
|
|
753
|
+
const command = str(this.args?.command);
|
|
754
|
+
return command ? `bash ${formatCommandPreview(command)}` : frameLabel;
|
|
755
|
+
}
|
|
756
|
+
const target = this.getCompactTarget();
|
|
757
|
+
return target ? `${this.getCompactAction()} ${target}` : frameLabel;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
private getCompactAction(): string {
|
|
761
|
+
const target = this.getTargetMetadata();
|
|
762
|
+
if (target?.action) return target.action === "list" ? "ls" : target.action;
|
|
763
|
+
return this.normalizedToolName;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
private getTargetMetadata(): ToolTargetMetadata | undefined {
|
|
767
|
+
const target = this.result?.details?.target;
|
|
768
|
+
return target && typeof target === "object" ? target : undefined;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
private getCompactTarget(): string | undefined {
|
|
772
|
+
const metadata = this.getTargetMetadata();
|
|
773
|
+
const metadataTarget = metadata ? formatToolTarget(metadata) : undefined;
|
|
774
|
+
if (metadataTarget) return metadataTarget;
|
|
775
|
+
|
|
776
|
+
const path = str(this.args?.file_path ?? this.args?.path);
|
|
777
|
+
if (path === null) return undefined;
|
|
778
|
+
if (this.normalizedToolName === "read" || this.normalizedToolName === "hashline_read") {
|
|
779
|
+
return formatArgsPathTarget(path, this.args);
|
|
780
|
+
}
|
|
781
|
+
if (this.normalizedToolName === "write" || this.normalizedToolName === "edit") {
|
|
782
|
+
return path ? shortenPath(path) : undefined;
|
|
783
|
+
}
|
|
784
|
+
if (this.normalizedToolName === "ls") {
|
|
785
|
+
return shortenPath(path || ".");
|
|
786
|
+
}
|
|
787
|
+
if (this.normalizedToolName === "find") {
|
|
788
|
+
const pattern = str(this.args?.pattern);
|
|
789
|
+
return pattern ? `${pattern} in ${shortenPath(path || ".")}` : shortenPath(path || ".");
|
|
790
|
+
}
|
|
791
|
+
if (this.normalizedToolName === "grep") {
|
|
792
|
+
const pattern = str(this.args?.pattern);
|
|
793
|
+
const glob = str(this.args?.glob);
|
|
794
|
+
const label = pattern ? `${pattern} in ${shortenPath(path || ".")}` : shortenPath(path || ".");
|
|
795
|
+
return glob ? `${label} (${glob})` : label;
|
|
796
|
+
}
|
|
797
|
+
return undefined;
|
|
635
798
|
}
|
|
636
799
|
|
|
637
800
|
private updateDisplay(): void {
|
|
@@ -861,6 +1024,10 @@ export class ToolExecutionComponent extends Container {
|
|
|
861
1024
|
// Truncation warnings
|
|
862
1025
|
const truncation = this.result.details?.truncation;
|
|
863
1026
|
const fullOutputPath = this.result.details?.fullOutputPath;
|
|
1027
|
+
const cwd = this.result.details?.cwd;
|
|
1028
|
+
if (this.expanded && typeof cwd === "string" && cwd.length > 0) {
|
|
1029
|
+
this.contentBox.addChild(new Text(`\n${theme.fg("muted", `cwd ${shortenPath(cwd)}`)}`, 0, 0));
|
|
1030
|
+
}
|
|
864
1031
|
if (truncation?.truncated || fullOutputPath) {
|
|
865
1032
|
const warnings: string[] = [];
|
|
866
1033
|
if (fullOutputPath) {
|
|
@@ -1288,19 +1455,21 @@ export class ToolPhaseSummaryComponent extends Container {
|
|
|
1288
1455
|
}
|
|
1289
1456
|
|
|
1290
1457
|
getPhases(): ToolExecutionPhase[] {
|
|
1291
|
-
return this.phases.map((phase) => ({ ...phase }));
|
|
1458
|
+
return this.phases.map((phase) => ({ ...phase, targets: phase.targets ? [...phase.targets] : undefined }));
|
|
1292
1459
|
}
|
|
1293
1460
|
|
|
1294
1461
|
override render(width: number): string[] {
|
|
1295
1462
|
const frameWidth = Math.max(20, width);
|
|
1296
|
-
const rows = this.phases.
|
|
1297
|
-
const left =
|
|
1463
|
+
const rows = this.phases.flatMap((phase) => {
|
|
1464
|
+
const left = summarizePhaseLabel(phase);
|
|
1298
1465
|
const right = `success · ${formatElapsed(phase.durationMs)}`;
|
|
1299
1466
|
const contentWidth = Math.max(1, frameWidth - 2);
|
|
1300
1467
|
const leftWidth = Math.max(1, contentWidth - visibleWidth(right) - 1);
|
|
1301
1468
|
const leftText = truncateToWidth(left, leftWidth, "");
|
|
1302
1469
|
const gap = Math.max(1, contentWidth - visibleWidth(leftText) - visibleWidth(right));
|
|
1303
|
-
|
|
1470
|
+
const summaryRow = `${theme.fg("toolSuccess", leftText)}${" ".repeat(gap)}${theme.fg("toolSuccess", right)}`;
|
|
1471
|
+
const targetRow = summarizePhaseTargets(phase, contentWidth);
|
|
1472
|
+
return targetRow ? [summaryRow, theme.fg("muted", targetRow)] : [summaryRow];
|
|
1304
1473
|
});
|
|
1305
1474
|
|
|
1306
1475
|
return ["", ...style().border("minimal").borderColor((text) => theme.fg("toolSuccess", text)).render(rows, frameWidth)];
|