gsd-pi 2.77.0-dev.1d17f366c → 2.77.0-dev.2daa994b6
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/headless.js +25 -4
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/gsd/auto/phases.js +5 -18
- package/dist/resources/extensions/gsd/auto/session.js +6 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +37 -8
- package/dist/resources/extensions/gsd/auto-post-unit.js +79 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-start.js +75 -24
- package/dist/resources/extensions/gsd/auto.js +34 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +9 -1
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +7 -1
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gsd-db.js +1 -1
- package/dist/resources/extensions/gsd/guided-flow.js +2 -4
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +5 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +334 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +51 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/index.js +3 -1
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- 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 +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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.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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- 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-paths-manifest.json +17 -17
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/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/package.json +1 -3
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/workflow-tools.test.ts +80 -39
- package/packages/native/package.json +1 -1
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +29 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +39 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- 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/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- 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 +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +36 -12
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +41 -12
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/scripts/install.js +15 -1
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +80 -72
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +33 -1
- package/src/resources/extensions/gsd/auto/phases.ts +6 -17
- package/src/resources/extensions/gsd/auto/session.ts +7 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +40 -8
- package/src/resources/extensions/gsd/auto-post-unit.ts +81 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-start.ts +97 -4
- package/src/resources/extensions/gsd/auto.ts +37 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +9 -1
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +7 -1
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/git-service.ts +16 -0
- package/src/resources/extensions/gsd/gsd-db.ts +1 -1
- package/src/resources/extensions/gsd/guided-flow.ts +2 -4
- package/src/resources/extensions/gsd/journal.ts +11 -1
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +5 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +25 -292
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +22 -16
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +492 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +53 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/index.ts +3 -1
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{vidAVJkURvTJ0_V2-64ro → gYYky7yfxW8txb9vU2TrJ}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{vidAVJkURvTJ0_V2-64ro → gYYky7yfxW8txb9vU2TrJ}/_ssgManifest.js +0 -0
|
@@ -1,294 +1,359 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
overlaySrc.includes('"2 Timeline"'),
|
|
28
|
-
"has Timeline tab label",
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
assert.ok(
|
|
32
|
-
overlaySrc.includes('"3 Deps"'),
|
|
33
|
-
"has Deps tab label",
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
assert.ok(
|
|
37
|
-
overlaySrc.includes('"5 Health"'),
|
|
38
|
-
"has Health tab label",
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
assert.ok(
|
|
42
|
-
overlaySrc.includes('"6 Agent"'),
|
|
43
|
-
"has Agent tab label",
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
assert.ok(
|
|
47
|
-
overlaySrc.includes('"7 Changes"'),
|
|
48
|
-
"has Changes tab label",
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
assert.ok(
|
|
52
|
-
overlaySrc.includes('"8 Knowledge"'),
|
|
53
|
-
"has Knowledge tab label",
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
assert.ok(
|
|
57
|
-
overlaySrc.includes('"9 Captures"'),
|
|
58
|
-
"has Captures tab label",
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
assert.ok(
|
|
62
|
-
overlaySrc.includes('"0 Export"'),
|
|
63
|
-
"has Export tab label",
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
console.log("\n=== Overlay: Filter Mode ===");
|
|
67
|
-
|
|
68
|
-
assert.ok(
|
|
69
|
-
overlaySrc.includes('filterMode = false'),
|
|
70
|
-
"filterMode initialized to false",
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
assert.ok(
|
|
74
|
-
overlaySrc.includes('filterText = ""'),
|
|
75
|
-
"filterText initialized to empty string",
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
assert.ok(
|
|
79
|
-
overlaySrc.includes('filterField:'),
|
|
80
|
-
"has filterField state",
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
// Filter mode entry via "/"
|
|
84
|
-
assert.ok(
|
|
85
|
-
overlaySrc.includes('data === "/"') || overlaySrc.includes("data === '/'"),
|
|
86
|
-
"/ key enters filter mode",
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
// Filter field cycling via "f"
|
|
90
|
-
assert.ok(
|
|
91
|
-
overlaySrc.includes('data === "f"') || overlaySrc.includes("data === 'f'"),
|
|
92
|
-
"f key cycles filter field",
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
console.log("\n=== Overlay: Tab Switching ===");
|
|
96
|
-
|
|
97
|
-
// Supports 1-9,0 keys
|
|
98
|
-
assert.ok(
|
|
99
|
-
overlaySrc.includes('"1234567890"'),
|
|
100
|
-
"supports keys 1-9,0 for tab switching",
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// Tab wraps with TAB_COUNT
|
|
104
|
-
assert.ok(
|
|
105
|
-
overlaySrc.includes("% TAB_COUNT"),
|
|
106
|
-
"tab key wraps around TAB_COUNT",
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
assert.ok(
|
|
110
|
-
overlaySrc.includes('Key.shift("tab")') || overlaySrc.includes("Key.shift('tab')"),
|
|
111
|
-
"supports Shift+Tab for reverse tab switching",
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
console.log("\n=== Overlay: Page/Half-Page Scroll ===");
|
|
115
|
-
|
|
116
|
-
assert.ok(
|
|
117
|
-
overlaySrc.includes("Key.pageUp"),
|
|
118
|
-
"has Key.pageUp handler",
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
assert.ok(
|
|
122
|
-
overlaySrc.includes("Key.pageDown"),
|
|
123
|
-
"has Key.pageDown handler",
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
assert.ok(
|
|
127
|
-
overlaySrc.includes('Key.ctrl("u")'),
|
|
128
|
-
"has Ctrl+U half-page scroll",
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
assert.ok(
|
|
132
|
-
overlaySrc.includes('Key.ctrl("d")'),
|
|
133
|
-
"has Ctrl+D half-page scroll",
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
console.log("\n=== Overlay: Mouse Support ===");
|
|
137
|
-
|
|
138
|
-
assert.ok(
|
|
139
|
-
overlaySrc.includes("parseSGRMouse"),
|
|
140
|
-
"has parseSGRMouse method",
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
assert.ok(
|
|
144
|
-
overlaySrc.includes("?1003h"),
|
|
145
|
-
"enables mouse tracking in constructor",
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
assert.ok(
|
|
149
|
-
overlaySrc.includes("?1003l"),
|
|
150
|
-
"disables mouse tracking in dispose",
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
console.log("\n=== Overlay: Collapsible Milestones ===");
|
|
154
|
-
|
|
155
|
-
assert.ok(
|
|
156
|
-
overlaySrc.includes("collapsedMilestones"),
|
|
157
|
-
"has collapsedMilestones state",
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
console.log("\n=== Overlay: Help Overlay ===");
|
|
161
|
-
|
|
162
|
-
assert.ok(
|
|
163
|
-
overlaySrc.includes("showHelp"),
|
|
164
|
-
"has showHelp state",
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
assert.ok(
|
|
168
|
-
overlaySrc.includes('data === "?"'),
|
|
169
|
-
"? key toggles help",
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
console.log("\n=== Overlay: Export Key Interception ===");
|
|
173
|
-
|
|
174
|
-
assert.ok(
|
|
175
|
-
overlaySrc.includes("activeTab === 9"),
|
|
176
|
-
"export key handling checks for tab 0 (index 9)",
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
assert.ok(
|
|
180
|
-
overlaySrc.includes('handleExportKey'),
|
|
181
|
-
"has handleExportKey method",
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
assert.ok(
|
|
185
|
-
overlaySrc.includes('"m"') && overlaySrc.includes('"j"') && overlaySrc.includes('"s"'),
|
|
186
|
-
"handles m, j, s keys for export",
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
console.log("\n=== Overlay: Footer ===");
|
|
190
|
-
|
|
191
|
-
assert.ok(
|
|
192
|
-
overlaySrc.includes("1-9,0"),
|
|
193
|
-
"footer hint shows 1-9,0 tab range",
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
assert.ok(
|
|
197
|
-
overlaySrc.includes("PgUp/PgDn"),
|
|
198
|
-
"footer hint mentions PgUp/PgDn",
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
assert.ok(
|
|
202
|
-
overlaySrc.includes("? help"),
|
|
203
|
-
"footer hint mentions ? for help",
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
console.log("\n=== Overlay: Scroll Offsets ===");
|
|
207
|
-
|
|
208
|
-
assert.ok(
|
|
209
|
-
overlaySrc.includes(`new Array(TAB_COUNT).fill(0)`),
|
|
210
|
-
"scroll offsets sized to TAB_COUNT",
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
console.log("\n=== Overlay: Terminal Resize Handling ===");
|
|
214
|
-
|
|
215
|
-
assert.ok(
|
|
216
|
-
overlaySrc.includes('resizeHandler'),
|
|
217
|
-
"has resizeHandler property",
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
assert.ok(
|
|
221
|
-
overlaySrc.includes('"resize"'),
|
|
222
|
-
"listens for resize events",
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
assert.ok(
|
|
226
|
-
overlaySrc.includes('removeListener("resize"'),
|
|
227
|
-
"removes resize listener on dispose",
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
console.log("\n=== Overlay: Shared Imports ===");
|
|
231
|
-
|
|
232
|
-
assert.ok(
|
|
233
|
-
overlaySrc.includes('from "../shared/mod.js"'),
|
|
234
|
-
"imports from shared barrel",
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
test("visualizer overlay closes on escape in filter and help submodes", async () => {
|
|
238
|
-
const mod = await import("../visualizer-overlay.js");
|
|
239
|
-
|
|
240
|
-
const mockTui = { requestRender: () => {} };
|
|
241
|
-
const mockTheme = {
|
|
242
|
-
fg: (_color: string, text: string) => text,
|
|
243
|
-
bold: (text: string) => text,
|
|
1
|
+
/**
|
|
2
|
+
* GSD visualizer overlay — behaviour tests.
|
|
3
|
+
*
|
|
4
|
+
* These tests drive the overlay through its public surface:
|
|
5
|
+
* - construct an instance
|
|
6
|
+
* - feed input events (keystrokes, SGR mouse sequences)
|
|
7
|
+
* - observe the rendered line array and mutable state
|
|
8
|
+
*
|
|
9
|
+
* The previous version of this file was 39 `overlaySrc.includes(...)`
|
|
10
|
+
* assertions — a pure source-grep. Replaced with behaviour-driven tests.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { test } from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
|
|
16
|
+
import { GSDVisualizerOverlay } from "../visualizer-overlay.ts";
|
|
17
|
+
|
|
18
|
+
function makeTui() {
|
|
19
|
+
const renders: number[] = [];
|
|
20
|
+
return {
|
|
21
|
+
renders,
|
|
22
|
+
tui: {
|
|
23
|
+
requestRender: () => {
|
|
24
|
+
renders.push(Date.now());
|
|
25
|
+
},
|
|
26
|
+
},
|
|
244
27
|
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const mockTheme = {
|
|
31
|
+
fg: (_color: string, text: string) => text,
|
|
32
|
+
bold: (text: string) => text,
|
|
33
|
+
} as any;
|
|
34
|
+
|
|
35
|
+
function makeOverlay(t: { after: (fn: () => void) => void }, onClose: () => void = () => {}) {
|
|
36
|
+
const { tui, renders } = makeTui();
|
|
37
|
+
const overlay = new GSDVisualizerOverlay(tui as any, mockTheme, onClose);
|
|
38
|
+
t.after(() => overlay.dispose());
|
|
39
|
+
return { overlay, renders };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function stripAnsi(s: string): string {
|
|
43
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ─── Tab bar rendering ───────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
test("overlay renders 10 tabs (Progress, Timeline, Deps, Metrics, Health, Agent, Changes, Knowledge, Captures, Export)", (t) => {
|
|
49
|
+
const { overlay } = makeOverlay(t);
|
|
50
|
+
overlay.loading = true; // body shows loading text, but tab bar renders regardless
|
|
51
|
+
|
|
52
|
+
// Use a very wide terminal so the tab bar is not truncated.
|
|
53
|
+
const lines = overlay.render(200).map(stripAnsi);
|
|
54
|
+
const tabBar = lines.find((l) => l.includes("Progress") && l.includes("Export"));
|
|
55
|
+
assert.ok(tabBar, `expected a tab-bar line containing all labels, got:\n${lines.slice(0, 5).join("\n")}`);
|
|
56
|
+
for (const label of ["Progress", "Timeline", "Deps", "Metrics", "Health", "Agent", "Changes", "Knowledge", "Captures", "Export"]) {
|
|
57
|
+
assert.ok(tabBar!.includes(label), `tab bar missing label ${label}`);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("overlay shows a Captures badge count when pending captures are present", (t) => {
|
|
62
|
+
const { overlay } = makeOverlay(t);
|
|
63
|
+
overlay.loading = true;
|
|
64
|
+
overlay.data = { captures: { pendingCount: 7 } } as any;
|
|
65
|
+
|
|
66
|
+
const lines = overlay.render(120).map(stripAnsi);
|
|
67
|
+
const tabBar = lines.find((l) => l.includes("Captures"))!;
|
|
68
|
+
assert.ok(tabBar.includes("(7)"), `captures tab should carry (7) badge, got: ${tabBar}`);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// ─── Tab switching via digit keys ────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
test("overlay switches tabs via 1–9,0 digit keys", (t) => {
|
|
74
|
+
const { overlay } = makeOverlay(t);
|
|
75
|
+
|
|
76
|
+
const cases: Array<[string, number]> = [
|
|
77
|
+
["1", 0],
|
|
78
|
+
["2", 1],
|
|
79
|
+
["3", 2],
|
|
80
|
+
["4", 3],
|
|
81
|
+
["5", 4],
|
|
82
|
+
["6", 5],
|
|
83
|
+
["7", 6],
|
|
84
|
+
["8", 7],
|
|
85
|
+
["9", 8],
|
|
86
|
+
["0", 9],
|
|
87
|
+
];
|
|
88
|
+
for (const [key, expected] of cases) {
|
|
89
|
+
overlay.handleInput(key);
|
|
90
|
+
assert.equal(overlay.activeTab, expected, `key ${key} should select tab ${expected}`);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("overlay Tab key cycles forward and wraps around at TAB_COUNT", (t) => {
|
|
95
|
+
const { overlay } = makeOverlay(t);
|
|
96
|
+
overlay.activeTab = 9;
|
|
97
|
+
overlay.handleInput("\t");
|
|
98
|
+
assert.equal(overlay.activeTab, 0, "Tab wraps from 9 back to 0");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("overlay Shift+Tab cycles backward and wraps", (t) => {
|
|
102
|
+
const { overlay } = makeOverlay(t);
|
|
103
|
+
overlay.activeTab = 0;
|
|
104
|
+
overlay.handleInput("\u001b[Z");
|
|
105
|
+
assert.equal(overlay.activeTab, 9, "Shift+Tab wraps from 0 to 9");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ─── Filter mode ─────────────────────────────────────────────────────────
|
|
109
|
+
|
|
110
|
+
test("overlay / enters filter mode and typed characters accumulate in filterText", (t) => {
|
|
111
|
+
const { overlay } = makeOverlay(t);
|
|
112
|
+
assert.equal(overlay.filterMode, false, "starts out of filter mode");
|
|
113
|
+
assert.equal(overlay.filterText, "", "starts with empty filter text");
|
|
114
|
+
|
|
115
|
+
overlay.handleInput("/");
|
|
116
|
+
assert.equal(overlay.filterMode, true, "/ enters filter mode");
|
|
117
|
+
|
|
118
|
+
overlay.handleInput("f");
|
|
119
|
+
overlay.handleInput("o");
|
|
120
|
+
overlay.handleInput("o");
|
|
121
|
+
assert.equal(overlay.filterText, "foo");
|
|
122
|
+
|
|
123
|
+
overlay.handleInput("\r"); // enter — exits filter mode
|
|
124
|
+
assert.equal(overlay.filterMode, false, "Enter exits filter mode");
|
|
125
|
+
assert.equal(overlay.filterText, "foo", "filter text persists after exit");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("overlay filter backspace deletes last character", (t) => {
|
|
129
|
+
const { overlay } = makeOverlay(t);
|
|
130
|
+
overlay.handleInput("/");
|
|
131
|
+
overlay.handleInput("a");
|
|
132
|
+
overlay.handleInput("b");
|
|
133
|
+
overlay.handleInput("c");
|
|
134
|
+
overlay.handleInput("\u007f"); // backspace
|
|
135
|
+
assert.equal(overlay.filterText, "ab");
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("overlay f key cycles filter field on Progress tab: all → status → risk → keyword → all", (t) => {
|
|
139
|
+
const { overlay } = makeOverlay(t);
|
|
140
|
+
overlay.activeTab = 0;
|
|
141
|
+
assert.equal(overlay.filterField, "all");
|
|
142
|
+
overlay.handleInput("f");
|
|
143
|
+
assert.equal(overlay.filterField, "status");
|
|
144
|
+
overlay.handleInput("f");
|
|
145
|
+
assert.equal(overlay.filterField, "risk");
|
|
146
|
+
overlay.handleInput("f");
|
|
147
|
+
assert.equal(overlay.filterField, "keyword");
|
|
148
|
+
overlay.handleInput("f");
|
|
149
|
+
assert.equal(overlay.filterField, "all", "cycles back to all");
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("overlay f key on non-Progress tabs only toggles all ↔ keyword", (t) => {
|
|
153
|
+
const { overlay } = makeOverlay(t);
|
|
154
|
+
overlay.activeTab = 2; // Deps tab
|
|
155
|
+
overlay.filterField = "all";
|
|
156
|
+
overlay.handleInput("f");
|
|
157
|
+
assert.equal(overlay.filterField, "keyword");
|
|
158
|
+
overlay.handleInput("f");
|
|
159
|
+
assert.equal(overlay.filterField, "all");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ─── Help overlay ────────────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
test("overlay ? key shows help, and pressing ? again dismisses it in-place", (t) => {
|
|
165
|
+
let closed = false;
|
|
166
|
+
const { overlay } = makeOverlay(t, () => {
|
|
167
|
+
closed = true;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
overlay.handleInput("?");
|
|
171
|
+
assert.equal(overlay.showHelp, true, "? toggles help on");
|
|
172
|
+
|
|
173
|
+
overlay.handleInput("?");
|
|
174
|
+
assert.equal(overlay.showHelp, false, "? pressed again dismisses help");
|
|
175
|
+
assert.equal(closed, false, "toggling help does not close the overlay");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// ─── Escape / Ctrl+C close behaviour ─────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
test("overlay Escape closes when no sub-mode is active", (t) => {
|
|
181
|
+
let closed = false;
|
|
182
|
+
const { overlay } = makeOverlay(t, () => {
|
|
183
|
+
closed = true;
|
|
184
|
+
});
|
|
185
|
+
overlay.handleInput("\u001b");
|
|
186
|
+
assert.equal(closed, true);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("overlay Ctrl+C closes even while filter mode is active", (t) => {
|
|
190
|
+
let closed = false;
|
|
191
|
+
const { overlay } = makeOverlay(t, () => {
|
|
192
|
+
closed = true;
|
|
193
|
+
});
|
|
194
|
+
overlay.filterMode = true;
|
|
195
|
+
overlay.handleInput("\u0003"); // Ctrl+C
|
|
196
|
+
assert.equal(closed, true, "Ctrl+C must close even in filter mode");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("overlay Escape closes even when help is visible (top-level Escape short-circuits)", (t) => {
|
|
200
|
+
let closed = false;
|
|
201
|
+
const { overlay } = makeOverlay(t, () => {
|
|
202
|
+
closed = true;
|
|
203
|
+
});
|
|
204
|
+
overlay.showHelp = true;
|
|
205
|
+
overlay.handleInput("\u001b");
|
|
206
|
+
assert.equal(closed, true, "Escape calls onClose regardless of sub-mode");
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// ─── Scroll behaviour ────────────────────────────────────────────────────
|
|
245
210
|
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
211
|
+
test("overlay j / Down scrolls one line forward, k / Up scrolls back", (t) => {
|
|
212
|
+
const { overlay } = makeOverlay(t);
|
|
213
|
+
overlay.activeTab = 1;
|
|
214
|
+
overlay.scrollOffsets[1] = 5;
|
|
215
|
+
|
|
216
|
+
overlay.handleInput("j");
|
|
217
|
+
assert.equal(overlay.scrollOffsets[1], 6);
|
|
218
|
+
|
|
219
|
+
overlay.handleInput("k");
|
|
220
|
+
assert.equal(overlay.scrollOffsets[1], 5);
|
|
221
|
+
|
|
222
|
+
overlay.handleInput("\u001b[B"); // Down arrow
|
|
223
|
+
assert.equal(overlay.scrollOffsets[1], 6);
|
|
224
|
+
|
|
225
|
+
overlay.handleInput("\u001b[A"); // Up arrow
|
|
226
|
+
assert.equal(overlay.scrollOffsets[1], 5);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("overlay k / Up does not scroll below zero", (t) => {
|
|
230
|
+
const { overlay } = makeOverlay(t);
|
|
231
|
+
overlay.scrollOffsets[0] = 0;
|
|
232
|
+
overlay.handleInput("k");
|
|
233
|
+
assert.equal(overlay.scrollOffsets[0], 0);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("overlay g jumps to top, G jumps to bottom-sentinel", (t) => {
|
|
237
|
+
const { overlay } = makeOverlay(t);
|
|
238
|
+
overlay.scrollOffsets[0] = 50;
|
|
239
|
+
overlay.handleInput("g");
|
|
240
|
+
assert.equal(overlay.scrollOffsets[0], 0);
|
|
241
|
+
overlay.handleInput("G");
|
|
242
|
+
assert.ok(overlay.scrollOffsets[0] >= 100, "G sets a large offset sentinel");
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("overlay Ctrl+U / Ctrl+D scroll half-page", (t) => {
|
|
246
|
+
const { overlay } = makeOverlay(t);
|
|
247
|
+
overlay.scrollOffsets[0] = 100;
|
|
248
|
+
overlay.handleInput("\u0004"); // Ctrl+D
|
|
249
|
+
assert.ok(
|
|
250
|
+
overlay.scrollOffsets[0] > 100,
|
|
251
|
+
`Ctrl+D should move forward, got ${overlay.scrollOffsets[0]}`,
|
|
251
252
|
);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
assert.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
let closedHelp = false;
|
|
258
|
-
const helpOverlay = new mod.GSDVisualizerOverlay(
|
|
259
|
-
mockTui,
|
|
260
|
-
mockTheme as any,
|
|
261
|
-
() => { closedHelp = true; },
|
|
253
|
+
const afterDown = overlay.scrollOffsets[0];
|
|
254
|
+
overlay.handleInput("\u0015"); // Ctrl+U
|
|
255
|
+
assert.ok(
|
|
256
|
+
overlay.scrollOffsets[0] < afterDown,
|
|
257
|
+
"Ctrl+U should move backward",
|
|
262
258
|
);
|
|
263
|
-
helpOverlay.showHelp = true;
|
|
264
|
-
helpOverlay.handleInput("\u001b");
|
|
265
|
-
assert.equal(closedHelp, true, "Escape closes while help overlay is visible");
|
|
266
|
-
helpOverlay.dispose();
|
|
267
259
|
});
|
|
268
260
|
|
|
269
|
-
test("
|
|
270
|
-
const
|
|
261
|
+
test("overlay PageUp / PageDown scroll one viewport", (t) => {
|
|
262
|
+
const { overlay } = makeOverlay(t);
|
|
263
|
+
overlay.scrollOffsets[0] = 50;
|
|
264
|
+
overlay.handleInput("\u001b[6~"); // Page Down
|
|
265
|
+
assert.ok(overlay.scrollOffsets[0] > 50);
|
|
266
|
+
const after = overlay.scrollOffsets[0];
|
|
267
|
+
overlay.handleInput("\u001b[5~"); // Page Up
|
|
268
|
+
assert.ok(overlay.scrollOffsets[0] < after);
|
|
269
|
+
});
|
|
271
270
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
271
|
+
// ─── Mouse wheel + click ─────────────────────────────────────────────────
|
|
272
|
+
|
|
273
|
+
test("overlay SGR mouse wheel up/down scrolls active tab", (t) => {
|
|
274
|
+
const { overlay } = makeOverlay(t);
|
|
275
|
+
overlay.scrollOffsets[0] = 20;
|
|
276
|
+
// SGR mouse wheel down: button 65
|
|
277
|
+
overlay.handleInput("\u001b[<65;10;10M");
|
|
278
|
+
assert.equal(overlay.scrollOffsets[0], 23, "wheel-down scrolls +3");
|
|
279
|
+
// Wheel up: button 64
|
|
280
|
+
overlay.handleInput("\u001b[<64;10;10M");
|
|
281
|
+
assert.equal(overlay.scrollOffsets[0], 20, "wheel-up scrolls −3");
|
|
282
|
+
});
|
|
277
283
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
mockTheme as any,
|
|
281
|
-
() => {},
|
|
282
|
-
);
|
|
284
|
+
test("overlay click on Captures tab badge selects that tab", (t) => {
|
|
285
|
+
const { overlay } = makeOverlay(t);
|
|
283
286
|
overlay.loading = true;
|
|
284
287
|
overlay.data = { captures: { pendingCount: 3 } } as any;
|
|
285
288
|
|
|
286
289
|
const lines = overlay.render(120);
|
|
287
|
-
const tabLine = lines.find((line
|
|
290
|
+
const tabLine = lines.find((line) => line.includes("Captures") && line.includes("(3)"))!;
|
|
288
291
|
assert.ok(tabLine, "rendered tab bar includes captures badge");
|
|
289
|
-
const plain = tabLine
|
|
292
|
+
const plain = stripAnsi(tabLine);
|
|
290
293
|
const badgeColumn = plain.indexOf("(3)") + 2;
|
|
291
|
-
overlay.handleInput(`\
|
|
294
|
+
overlay.handleInput(`\u001b[<0;${badgeColumn};2M`);
|
|
292
295
|
assert.equal(overlay.activeTab, 8, "clicking the badge area selects the captures tab");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// ─── Collapse state on Progress tab ──────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
test("overlay exposes collapsedMilestones set for Progress-tab collapse tracking", (t) => {
|
|
301
|
+
const { overlay } = makeOverlay(t);
|
|
302
|
+
assert.ok(overlay.collapsedMilestones instanceof Set);
|
|
303
|
+
assert.equal(overlay.collapsedMilestones.size, 0);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// ─── Loading state rendering ─────────────────────────────────────────────
|
|
307
|
+
|
|
308
|
+
test("overlay renders a Loading… marker when no data is loaded yet", (t) => {
|
|
309
|
+
const { overlay } = makeOverlay(t);
|
|
310
|
+
overlay.loading = true;
|
|
311
|
+
|
|
312
|
+
const lines = overlay.render(120).map(stripAnsi);
|
|
313
|
+
assert.ok(
|
|
314
|
+
lines.some((l) => l.includes("Loading")),
|
|
315
|
+
"expected Loading… indicator in render output",
|
|
316
|
+
);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ─── Footer hint ─────────────────────────────────────────────────────────
|
|
320
|
+
|
|
321
|
+
test("overlay footer hint mentions tab navigation, filter, scroll, and help", (t) => {
|
|
322
|
+
const { overlay } = makeOverlay(t);
|
|
323
|
+
overlay.loading = true;
|
|
324
|
+
|
|
325
|
+
const lines = overlay.render(120).map(stripAnsi).join("\n");
|
|
326
|
+
assert.ok(lines.includes("1-9,0"), "footer shows 1-9,0 tab range hint");
|
|
327
|
+
assert.ok(lines.includes("PgUp/PgDn") || lines.includes("PgUp"), "footer mentions PgUp/PgDn");
|
|
328
|
+
assert.ok(lines.includes("? help"), "footer mentions ? help");
|
|
329
|
+
assert.ok(lines.includes("/"), "footer mentions / for filter");
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// ─── Scroll offsets array is sized to TAB_COUNT ──────────────────────────
|
|
333
|
+
|
|
334
|
+
test("overlay scrollOffsets array has one slot per tab (10 tabs total)", (t) => {
|
|
335
|
+
const { overlay } = makeOverlay(t);
|
|
336
|
+
assert.equal(overlay.scrollOffsets.length, 10, "scrollOffsets sized to TAB_COUNT=10");
|
|
337
|
+
assert.ok(overlay.scrollOffsets.every((n: number) => n === 0), "initialized to zero");
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// ─── Dispose cleanup ─────────────────────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
test("overlay dispose is idempotent and flips the disposed flag", (t) => {
|
|
343
|
+
const { tui } = makeTui();
|
|
344
|
+
const overlay = new GSDVisualizerOverlay(tui as any, mockTheme, () => {});
|
|
345
|
+
// Ensure constructor-owned resources are released even if an assertion
|
|
346
|
+
// below fails — dispose() is documented as idempotent, so a teardown
|
|
347
|
+
// call after the body's explicit dispose is a no-op.
|
|
348
|
+
t.after(() => {
|
|
349
|
+
try { overlay.dispose(); } catch { /* already disposed */ }
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Sanity: disposed flag flips
|
|
353
|
+
assert.equal(overlay.disposed, false);
|
|
354
|
+
overlay.dispose();
|
|
355
|
+
assert.equal(overlay.disposed, true);
|
|
356
|
+
|
|
357
|
+
// Calling dispose again is safe (no throw)
|
|
293
358
|
overlay.dispose();
|
|
294
359
|
});
|