@opengsd/gsd-pi 1.0.2-dev.e70300c → 1.0.2-dev.fb7ddf1
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/README.md +63 -12
- package/dist/headless-answers.js +2 -1
- package/dist/headless-events.d.ts +1 -0
- package/dist/headless-events.js +8 -1
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +44 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +81 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +38 -1
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +34 -1
- package/dist/resources/extensions/gsd/auto.js +40 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +7 -2
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
- package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +3 -20
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repo-identity.js +36 -6
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/extensions/subagent/index.js +8 -15
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/resources/skills/agent-browser/SKILL.md +1 -1
- package/dist/resources/skills/api-design/SKILL.md +1 -1
- package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
- package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/dist/resources/skills/forensics/SKILL.md +2 -2
- package/dist/resources/skills/grill-me/SKILL.md +1 -1
- package/dist/resources/skills/handoff/SKILL.md +1 -1
- package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/dist/resources/skills/observability/SKILL.md +1 -1
- package/dist/resources/skills/security-review/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/dist/resources/skills/tdd/SKILL.md +1 -1
- package/dist/resources/skills/write-docs/SKILL.md +1 -1
- package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- 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/api/update/route.js +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 +8 -8
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- 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/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.test.js +5 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +15 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/dist/workflow.test.js +1 -0
- package/packages/contracts/dist/workflow.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +7 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +47 -8
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +16 -14
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +48 -206
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +67 -220
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
- package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +96 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +47 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +45 -1
- package/src/resources/extensions/gsd/auto.ts +50 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +7 -2
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
- package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +3 -20
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repo-identity.ts +35 -7
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/extensions/subagent/index.ts +8 -15
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/src/resources/skills/agent-browser/SKILL.md +1 -1
- package/src/resources/skills/api-design/SKILL.md +1 -1
- package/src/resources/skills/code-optimizer/SKILL.md +6 -11
- package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/src/resources/skills/forensics/SKILL.md +2 -2
- package/src/resources/skills/grill-me/SKILL.md +1 -1
- package/src/resources/skills/handoff/SKILL.md +1 -1
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/src/resources/skills/observability/SKILL.md +1 -1
- package/src/resources/skills/security-review/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/src/resources/skills/tdd/SKILL.md +1 -1
- package/src/resources/skills/write-docs/SKILL.md +1 -1
- package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
- /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{szb-HAt0IoSx3docUZO-E → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
|
@@ -241,6 +241,36 @@ test('executeGsdExec: enforces per-call timeout override end-to-end', async () =
|
|
|
241
241
|
}
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
test('executeGsdExec: defaults to bash and accepts command alias', async () => {
|
|
245
|
+
const base = freshBase();
|
|
246
|
+
try {
|
|
247
|
+
const result = await executeGsdExec(
|
|
248
|
+
{ command: 'echo command-alias-defaults-to-bash' },
|
|
249
|
+
{ baseDir: base, preferences: { context_mode: { enabled: true } } },
|
|
250
|
+
);
|
|
251
|
+
assert.equal(result.isError, false);
|
|
252
|
+
assert.equal(result.details.runtime, 'bash');
|
|
253
|
+
assert.ok(result.content[0].text.includes('command-alias-defaults-to-bash'));
|
|
254
|
+
} finally {
|
|
255
|
+
cleanup(base);
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('executeGsdExec: accepts common runtime aliases', async () => {
|
|
260
|
+
const base = freshBase();
|
|
261
|
+
try {
|
|
262
|
+
const result = await executeGsdExec(
|
|
263
|
+
{ runtime: 'js', code: 'console.log("runtime-alias-node")' },
|
|
264
|
+
{ baseDir: base, preferences: { context_mode: { enabled: true } } },
|
|
265
|
+
);
|
|
266
|
+
assert.equal(result.isError, false);
|
|
267
|
+
assert.equal(result.details.runtime, 'node');
|
|
268
|
+
assert.ok(result.content[0].text.includes('runtime-alias-node'));
|
|
269
|
+
} finally {
|
|
270
|
+
cleanup(base);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
244
274
|
test('executeGsdExec: rejects empty script', async () => {
|
|
245
275
|
const base = freshBase();
|
|
246
276
|
try {
|
package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts
CHANGED
|
@@ -6,6 +6,7 @@ import assert from "node:assert/strict";
|
|
|
6
6
|
import { mkdtempSync, rmSync } from "node:fs";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
+
import { VISION_ASK_VARIANTS } from "../vision-ask.ts";
|
|
9
10
|
|
|
10
11
|
test("guided milestone prompt renders compact interview and context guidance", async (t) => {
|
|
11
12
|
const previousGsdHome = process.env.GSD_HOME;
|
|
@@ -31,6 +32,11 @@ test("guided milestone prompt renders compact interview and context guidance", a
|
|
|
31
32
|
|
|
32
33
|
assert.match(prompt, /M001 context written/);
|
|
33
34
|
assert.match(prompt, /Project Shape/);
|
|
35
|
+
assert.ok(
|
|
36
|
+
VISION_ASK_VARIANTS.some((opener) => prompt.includes(opener)),
|
|
37
|
+
"prompt should render a conversational opener variant",
|
|
38
|
+
);
|
|
39
|
+
assert.doesNotMatch(prompt, /\{\{visionAsk\}\}/);
|
|
34
40
|
assert.match(prompt, /default to `complex`/i);
|
|
35
41
|
assert.match(prompt, /3 or 4 concrete, researched options/);
|
|
36
42
|
assert.match(prompt, /"Other — let me discuss"/);
|
|
@@ -92,10 +92,10 @@ test('loadAndValidateAnswerFile — wrong types (non-string secret value)', (t)
|
|
|
92
92
|
// AnswerInjector — observeEvent + tryHandle
|
|
93
93
|
// ---------------------------------------------------------------------------
|
|
94
94
|
|
|
95
|
-
function makeToolExecutionStart(questions: Record<string, unknown>[]) {
|
|
95
|
+
function makeToolExecutionStart(questions: Record<string, unknown>[], toolName = 'ask_user_questions') {
|
|
96
96
|
return {
|
|
97
97
|
type: 'tool_execution_start',
|
|
98
|
-
toolName
|
|
98
|
+
toolName,
|
|
99
99
|
input: { questions },
|
|
100
100
|
};
|
|
101
101
|
}
|
|
@@ -140,6 +140,25 @@ test('observeEvent stores metadata', (t) => {
|
|
|
140
140
|
assert.strictEqual(injector.getStats().questionsDefaulted, 1);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
test('observeEvent stores metadata for MCP-scoped ask_user_questions', (t) => {
|
|
144
|
+
const injector = new AnswerInjector({ questions: { deploy_target: 'GCP' } });
|
|
145
|
+
|
|
146
|
+
injector.observeEvent(makeToolExecutionStart([{
|
|
147
|
+
id: 'deploy_target',
|
|
148
|
+
header: 'Deploy',
|
|
149
|
+
question: 'Where to deploy?',
|
|
150
|
+
options: [{ label: 'AWS' }, { label: 'GCP' }],
|
|
151
|
+
}], 'mcp__custom-workflow__ask_user_questions'));
|
|
152
|
+
|
|
153
|
+
const captured: string[] = [];
|
|
154
|
+
const captureStdin = (data: string) => { captured.push(data); };
|
|
155
|
+
const event = makeSelectEvent('req-1', 'Deploy: Where to deploy?', ['AWS', 'GCP']);
|
|
156
|
+
const handled = injector.tryHandle(event, captureStdin);
|
|
157
|
+
|
|
158
|
+
assert.strictEqual(handled, true);
|
|
159
|
+
assert.strictEqual(captured.length, 1);
|
|
160
|
+
});
|
|
161
|
+
|
|
143
162
|
test('tryHandle matches by question ID — single select', (t) => {
|
|
144
163
|
const injector = new AnswerInjector({ questions: { deploy_target: 'GCP' } });
|
|
145
164
|
|
|
@@ -312,7 +331,7 @@ test('tryHandle deferred resolution — observeEvent after tryHandle', async (t)
|
|
|
312
331
|
// ---------------------------------------------------------------------------
|
|
313
332
|
|
|
314
333
|
test('getSecretEnvVars returns secrets map', (t) => {
|
|
315
|
-
const secrets = { API_KEY: 'sk-123', DB_URL: '
|
|
334
|
+
const secrets = { API_KEY: 'sk-123', DB_URL: 'db-local-fixture' };
|
|
316
335
|
const injector = new AnswerInjector({ secrets });
|
|
317
336
|
|
|
318
337
|
assert.deepStrictEqual(injector.getSecretEnvVars(), secrets);
|
|
@@ -370,6 +370,49 @@ test("mergeCompletedMilestone — synthesizes roadmap from DB when projection is
|
|
|
370
370
|
}
|
|
371
371
|
});
|
|
372
372
|
|
|
373
|
+
test("mergeCompletedMilestone — stale worktree marker does not auto-commit dirty root overlap", async () => {
|
|
374
|
+
const savedCwd = process.cwd();
|
|
375
|
+
const repo = createTempRepo();
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
setupWorktreeIsolation(repo);
|
|
379
|
+
setupRoadmap(repo, "M011", "Dirty Root Recovery", ["S01: App shell"]);
|
|
380
|
+
|
|
381
|
+
createMilestoneBranch(repo, "M011", [
|
|
382
|
+
{ name: "index.html", content: "<h1>M011</h1>\n" },
|
|
383
|
+
]);
|
|
384
|
+
|
|
385
|
+
// Stale marker without a registered git worktree. Recovery must not treat
|
|
386
|
+
// the project root as a worktree and auto-commit this overlapping file to
|
|
387
|
+
// main before attempting the milestone merge.
|
|
388
|
+
mkdirSync(join(repo, ".gsd", "worktrees", "M011", ".gsd"), { recursive: true });
|
|
389
|
+
writeFileSync(join(repo, "index.html"), "<h1>local root draft</h1>\n");
|
|
390
|
+
|
|
391
|
+
process.chdir(repo);
|
|
392
|
+
const result = await mergeCompletedMilestone(repo, "M011");
|
|
393
|
+
|
|
394
|
+
assert.equal(result.success, false, "dirty overlap should block branch-mode recovery");
|
|
395
|
+
assert.match(
|
|
396
|
+
result.error ?? "",
|
|
397
|
+
/checkout|overwritten|untracked|would be overwritten/i,
|
|
398
|
+
"error should explain that checkout/dirty root state blocked recovery",
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
const subjects = run("git log --format=%s", repo);
|
|
402
|
+
assert.ok(
|
|
403
|
+
!subjects.includes("chore: auto-commit before milestone merge"),
|
|
404
|
+
"recovery must not auto-commit project-root overlap to main",
|
|
405
|
+
);
|
|
406
|
+
assert.equal(run("git branch --show-current", repo), "main");
|
|
407
|
+
assert.equal(run("git branch --list milestone/M011", repo).trim(), "milestone/M011");
|
|
408
|
+
assert.equal(run("git status --short -- index.html", repo), "?? index.html");
|
|
409
|
+
} finally {
|
|
410
|
+
process.chdir(savedCwd);
|
|
411
|
+
try { run("git reset --hard HEAD", repo); } catch { /* */ }
|
|
412
|
+
cleanup(repo);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
|
|
373
416
|
test("mergeCompletedMilestone — clean merge, session status cleaned up", async () => {
|
|
374
417
|
const savedCwd = process.cwd();
|
|
375
418
|
const repo = createTempRepo();
|
|
@@ -43,6 +43,14 @@ describe("hasInteractiveToolInFlight", () => {
|
|
|
43
43
|
assert.equal(hasInteractiveToolInFlight(), true);
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
test("returns true when MCP-scoped interactive tools are in-flight", () => {
|
|
47
|
+
markToolStart("call-1", true, "mcp__custom-workflow__ask_user_questions");
|
|
48
|
+
assert.equal(hasInteractiveToolInFlight(), true);
|
|
49
|
+
clearInFlightTools();
|
|
50
|
+
markToolStart("call-2", true, "mcp__custom-workflow__secure_env_collect");
|
|
51
|
+
assert.equal(hasInteractiveToolInFlight(), true);
|
|
52
|
+
});
|
|
53
|
+
|
|
46
54
|
test("returns false after interactive tool completes", () => {
|
|
47
55
|
markToolStart("call-1", true, "ask_user_questions");
|
|
48
56
|
assert.equal(hasInteractiveToolInFlight(), true);
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
formatKeyDashboard,
|
|
11
11
|
formatTestResults,
|
|
12
12
|
runKeyDoctor,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
formatDoctorFindings,
|
|
14
|
+
PROVIDER_REGISTRY,
|
|
15
|
+
getProviderAuthMode,
|
|
16
|
+
} from "../key-manager.ts";
|
|
16
17
|
|
|
17
18
|
function makeAuth(data: Record<string, any> = {}): AuthStorage {
|
|
18
19
|
return AuthStorage.inMemory(data);
|
|
@@ -76,6 +77,12 @@ test("describeCredential describes an empty API key", () => {
|
|
|
76
77
|
assert.equal(describeCredential({ type: "api_key", key: "" }), "empty key");
|
|
77
78
|
});
|
|
78
79
|
|
|
80
|
+
test("describeCredential describes external CLI sentinels without calling them API keys", () => {
|
|
81
|
+
const provider = PROVIDER_REGISTRY.find((p) => p.id === "claude-code");
|
|
82
|
+
assert.ok(provider);
|
|
83
|
+
assert.equal(describeCredential({ type: "api_key", key: "cli" }, provider), "external CLI");
|
|
84
|
+
});
|
|
85
|
+
|
|
79
86
|
test("describeCredential describes an OAuth token with expiry", () => {
|
|
80
87
|
const result = describeCredential({
|
|
81
88
|
type: "oauth",
|
|
@@ -149,7 +156,19 @@ test("PROVIDER_REGISTRY includes claude-code as a first-class LLM provider (#454
|
|
|
149
156
|
const entry = PROVIDER_REGISTRY.find((p) => p.id === "claude-code");
|
|
150
157
|
assert.ok(entry, "claude-code must be in PROVIDER_REGISTRY");
|
|
151
158
|
assert.equal(entry!.category, "llm");
|
|
152
|
-
assert.
|
|
159
|
+
assert.equal(getProviderAuthMode(entry!), "externalCli");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("PROVIDER_REGISTRY classifies only Copilot and Codex as browser OAuth LLM providers", () => {
|
|
163
|
+
const modes = Object.fromEntries(
|
|
164
|
+
PROVIDER_REGISTRY.filter((p) => p.category === "llm").map((p) => [p.id, getProviderAuthMode(p)]),
|
|
165
|
+
);
|
|
166
|
+
assert.equal(modes.anthropic, "apiKey");
|
|
167
|
+
assert.equal(modes["github-copilot"], "browserOAuth");
|
|
168
|
+
assert.equal(modes["openai-codex"], "browserOAuth");
|
|
169
|
+
assert.equal(modes["claude-code"], "externalCli");
|
|
170
|
+
assert.equal(modes["google-gemini-cli"], "externalCli");
|
|
171
|
+
assert.equal(modes["google-antigravity"], "externalCli");
|
|
153
172
|
});
|
|
154
173
|
|
|
155
174
|
test("PROVIDER_REGISTRY includes all tool/search providers", () => {
|
|
@@ -4,7 +4,7 @@ import { mkdtempSync, writeFileSync, mkdirSync } from "node:fs";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
|
|
7
|
-
import { discoverMcpServerNames, computeMcpDisallowedTools } from "../mcp-filter.ts";
|
|
7
|
+
import { discoverMcpServerNames, discoverWorkflowMcpServerName, computeMcpDisallowedTools } from "../mcp-filter.ts";
|
|
8
8
|
import type { ClaudeCodeMcpConfig } from "../preferences-types.ts";
|
|
9
9
|
|
|
10
10
|
// ─── discoverMcpServerNames ────────────────────────────────────────────────
|
|
@@ -57,6 +57,24 @@ describe("discoverMcpServerNames", () => {
|
|
|
57
57
|
const result = discoverMcpServerNames(dir);
|
|
58
58
|
assert.deepEqual(result, ["only-server"]);
|
|
59
59
|
});
|
|
60
|
+
|
|
61
|
+
it("discovers workflow server names by config signature", () => {
|
|
62
|
+
const dir = mkdtempSync(join(tmpdir(), "mcp-filter-test-"));
|
|
63
|
+
writeFileSync(
|
|
64
|
+
join(dir, ".mcp.json"),
|
|
65
|
+
JSON.stringify({
|
|
66
|
+
mcpServers: {
|
|
67
|
+
"custom-workflow": {
|
|
68
|
+
command: "node",
|
|
69
|
+
args: ["custom-cli.js"],
|
|
70
|
+
env: { GSD_WORKFLOW_PROJECT_ROOT: dir },
|
|
71
|
+
},
|
|
72
|
+
unrelated: { command: "npx", args: ["other"] },
|
|
73
|
+
},
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
assert.equal(discoverWorkflowMcpServerName(dir), "custom-workflow");
|
|
77
|
+
});
|
|
60
78
|
});
|
|
61
79
|
|
|
62
80
|
// ─── computeMcpDisallowedTools ─────────────────────────────────────────────
|
|
@@ -72,6 +72,30 @@ test("ensureProjectWorkflowMcpConfig preserves existing mcp servers", () => {
|
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
74
|
|
|
75
|
+
test("ensureProjectWorkflowMcpConfig uses custom workflow server name from env", () => {
|
|
76
|
+
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
|
|
77
|
+
mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const result = ensureProjectWorkflowMcpConfig(projectRoot, {
|
|
81
|
+
GSD_WORKFLOW_MCP_COMMAND: "node",
|
|
82
|
+
GSD_WORKFLOW_MCP_NAME: "custom-workflow",
|
|
83
|
+
GSD_WORKFLOW_MCP_ARGS: JSON.stringify(["server.js"]),
|
|
84
|
+
GSD_WORKFLOW_MCP_CWD: projectRoot,
|
|
85
|
+
});
|
|
86
|
+
assert.equal(result.status, "created");
|
|
87
|
+
assert.equal(result.serverName, "custom-workflow");
|
|
88
|
+
|
|
89
|
+
const parsed = JSON.parse(readFileSync(result.configPath, "utf-8")) as {
|
|
90
|
+
mcpServers?: Record<string, { command?: string; args?: string[] }>;
|
|
91
|
+
};
|
|
92
|
+
assert.ok(parsed.mcpServers?.["custom-workflow"]);
|
|
93
|
+
assert.equal(parsed.mcpServers?.[GSD_WORKFLOW_MCP_SERVER_NAME], undefined);
|
|
94
|
+
} finally {
|
|
95
|
+
rmSync(projectRoot, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
75
99
|
test("ensureProjectWorkflowMcpConfig is idempotent when config is already current", () => {
|
|
76
100
|
const projectRoot = mkdtempSync(join(tmpdir(), "gsd-mcp-init-"));
|
|
77
101
|
mkdirSync(join(projectRoot, ".gsd"), { recursive: true });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import {
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { copyFileSync, mkdtempSync, renameSync, rmSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { tmpdir } from "node:os";
|
|
5
6
|
import test from "node:test";
|
|
@@ -7,7 +8,9 @@ import test from "node:test";
|
|
|
7
8
|
import { ensureDbOpen } from "../bootstrap/dynamic-tools.ts";
|
|
8
9
|
import {
|
|
9
10
|
closeDatabase,
|
|
11
|
+
checkpointDatabase,
|
|
10
12
|
getAllMilestones,
|
|
13
|
+
_getAdapter,
|
|
11
14
|
insertMilestone,
|
|
12
15
|
insertSlice,
|
|
13
16
|
insertTask,
|
|
@@ -20,6 +23,20 @@ import {
|
|
|
20
23
|
import { writeGSDDirectory } from "../migrate/writer.ts";
|
|
21
24
|
import type { GSDProject } from "../migrate/types.ts";
|
|
22
25
|
|
|
26
|
+
const _require = createRequire(import.meta.url);
|
|
27
|
+
|
|
28
|
+
function openRawSqliteForTest(dbPath: string): { exec(sql: string): void; close(): void } {
|
|
29
|
+
try {
|
|
30
|
+
const mod = _require("node:sqlite") as { DatabaseSync: new (path: string) => { exec(sql: string): void; close(): void } };
|
|
31
|
+
return new mod.DatabaseSync(dbPath);
|
|
32
|
+
} catch {
|
|
33
|
+
type SqliteCtor = new (path: string) => { exec(sql: string): void; close(): void };
|
|
34
|
+
const mod = _require("better-sqlite3") as SqliteCtor | { default: SqliteCtor };
|
|
35
|
+
const DatabaseCtor: SqliteCtor = typeof mod === "function" ? mod : mod.default;
|
|
36
|
+
return new DatabaseCtor(dbPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
23
40
|
function makeBase(): string {
|
|
24
41
|
return mkdtempSync(join(tmpdir(), "gsd-migration-auto-check-"));
|
|
25
42
|
}
|
|
@@ -133,3 +150,41 @@ test("migration auto-check leaves matching DB hierarchy alone", async () => {
|
|
|
133
150
|
cleanup(base);
|
|
134
151
|
}
|
|
135
152
|
});
|
|
153
|
+
|
|
154
|
+
test("migration auto-check refreshes a stale open DB handle before comparing", async () => {
|
|
155
|
+
const base = makeBase();
|
|
156
|
+
try {
|
|
157
|
+
await writeGSDDirectory(projectFixture(), base);
|
|
158
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
159
|
+
insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
|
|
160
|
+
checkpointDatabase();
|
|
161
|
+
|
|
162
|
+
const dbPath = join(base, ".gsd", "gsd.db");
|
|
163
|
+
const replacementPath = join(base, ".gsd", "gsd-replacement.db");
|
|
164
|
+
copyFileSync(dbPath, replacementPath);
|
|
165
|
+
|
|
166
|
+
const replacement = openRawSqliteForTest(replacementPath);
|
|
167
|
+
try {
|
|
168
|
+
replacement.exec(`
|
|
169
|
+
INSERT INTO slices (milestone_id, id, title, status, risk, depends, demo, created_at, sequence)
|
|
170
|
+
VALUES ('M001', 'S01', 'Legacy Slice', 'pending', 'medium', '[]', 'Legacy slice demo', '', 1);
|
|
171
|
+
INSERT INTO tasks (milestone_id, slice_id, id, title, status, sequence)
|
|
172
|
+
VALUES ('M001', 'S01', 'T01', 'Legacy Task', 'pending', 1);
|
|
173
|
+
`);
|
|
174
|
+
} finally {
|
|
175
|
+
replacement.close();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const staleAdapter = _getAdapter();
|
|
179
|
+
renameSync(replacementPath, dbPath);
|
|
180
|
+
|
|
181
|
+
const result = await checkMarkdownHierarchyAgainstDb(base);
|
|
182
|
+
assert.notEqual(_getAdapter(), staleAdapter, "startup comparison must reopen the active DB handle");
|
|
183
|
+
assert.equal(result.action, "none");
|
|
184
|
+
assert.equal(result.reason, "in-sync");
|
|
185
|
+
assert.deepEqual(result.markdown, { milestones: 1, slices: 1, tasks: 1 });
|
|
186
|
+
assert.deepEqual(result.beforeDb, { milestones: 1, slices: 1, tasks: 1 });
|
|
187
|
+
} finally {
|
|
188
|
+
cleanup(base);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
@@ -11,6 +11,7 @@ import { visibleWidth } from "@gsd/pi-tui";
|
|
|
11
11
|
import { appendNotification, initNotificationStore, _resetNotificationStore } from "../notification-store.ts";
|
|
12
12
|
import { GSDNotificationOverlay, notificationOverlayOptions } from "../notification-overlay.ts";
|
|
13
13
|
import { wrapVisibleText } from "../tui/render-kit.ts";
|
|
14
|
+
import { assertFullOuterBorder } from "./tui-border-assertions.ts";
|
|
14
15
|
|
|
15
16
|
const fakeTheme = {
|
|
16
17
|
fg: (_color: string, text: string) => text,
|
|
@@ -92,7 +93,11 @@ describe("notification overlay — wrapText", () => {
|
|
|
92
93
|
t.after(() => overlay.dispose());
|
|
93
94
|
|
|
94
95
|
for (const width of [40, 80, 120]) {
|
|
95
|
-
|
|
96
|
+
const rendered = overlay.render(width);
|
|
97
|
+
assertLinesFit(rendered, width);
|
|
98
|
+
assertFullOuterBorder(rendered, width);
|
|
99
|
+
assert.match(rendered[0] ?? "", /^╭─ Notifications /);
|
|
100
|
+
assert.match(rendered.at(-1) ?? "", /^╰─+╯$/);
|
|
96
101
|
overlay.invalidate();
|
|
97
102
|
}
|
|
98
103
|
});
|
|
@@ -48,20 +48,27 @@ describe("auditOrphanedMilestoneBranches", () => {
|
|
|
48
48
|
const result = auditOrphanedMilestoneBranches(dir, "worktree");
|
|
49
49
|
assert.deepStrictEqual(result.recovered, []);
|
|
50
50
|
assert.deepStrictEqual(result.warnings, []);
|
|
51
|
+
assert.deepStrictEqual(result.actions, []);
|
|
52
|
+
assert.equal(result.blockingStrandedWork, null);
|
|
51
53
|
});
|
|
52
54
|
|
|
53
|
-
test("
|
|
54
|
-
// Create a milestone branch that would otherwise be detected
|
|
55
|
+
test("runs in none isolation mode and cleans safe completed residue", () => {
|
|
55
56
|
run("git branch milestone/M001", dir);
|
|
56
57
|
insertMilestone({ id: "M001", title: "Test", status: "complete" });
|
|
57
58
|
|
|
58
59
|
const result = auditOrphanedMilestoneBranches(dir, "none");
|
|
59
|
-
assert.
|
|
60
|
+
assert.ok(
|
|
61
|
+
result.recovered.some((r) => r.includes("Deleted merged branch milestone/M001")),
|
|
62
|
+
`should clean merged completed residue even in none mode; got: ${JSON.stringify(result.recovered)}`,
|
|
63
|
+
);
|
|
60
64
|
assert.deepStrictEqual(result.warnings, []);
|
|
65
|
+
assert.ok(
|
|
66
|
+
result.actions.some((action) => action.kind === "complete-merged-branch"),
|
|
67
|
+
"should record structured cleanup action",
|
|
68
|
+
);
|
|
61
69
|
|
|
62
|
-
// Branch should still exist
|
|
63
70
|
const branches = run("git branch --list milestone/M001", dir);
|
|
64
|
-
assert.
|
|
71
|
+
assert.equal(branches, "", "safe completed branch should be cleaned in none mode");
|
|
65
72
|
});
|
|
66
73
|
|
|
67
74
|
test("deletes merged branch for completed milestone", () => {
|
|
@@ -149,9 +156,12 @@ describe("auditOrphanedMilestoneBranches", () => {
|
|
|
149
156
|
// Must surface a warning so the user knows the worktree holds uncollapsed work
|
|
150
157
|
assert.ok(result.warnings.length > 0, "should warn about in-progress orphan");
|
|
151
158
|
assert.ok(
|
|
152
|
-
result.warnings.some(w => w.includes("milestone/M001") && w.includes("in-progress")),
|
|
153
|
-
`warning should mention milestone/M001 and in-progress state; got: ${JSON.stringify(result.warnings)}`,
|
|
159
|
+
result.warnings.some(w => w.includes("Stranded work") && w.includes("milestone/M001") && w.includes("in-progress")),
|
|
160
|
+
`warning should mention stranded milestone/M001 and in-progress state; got: ${JSON.stringify(result.warnings)}`,
|
|
154
161
|
);
|
|
162
|
+
assert.equal(result.blockingStrandedWork?.milestoneId, "M001");
|
|
163
|
+
assert.equal(result.blockingStrandedWork?.recoveryMode, "branch");
|
|
164
|
+
assert.equal(result.blockingStrandedWork?.commitsAhead, 1);
|
|
155
165
|
|
|
156
166
|
// Branch must still exist
|
|
157
167
|
const branches = run("git branch --list milestone/M001", dir);
|
|
@@ -184,6 +194,53 @@ describe("auditOrphanedMilestoneBranches", () => {
|
|
|
184
194
|
result.warnings.some(w => w.includes(".gsd/worktrees/M001") || w.includes("worktree")),
|
|
185
195
|
`warning should reference the worktree location; got: ${JSON.stringify(result.warnings)}`,
|
|
186
196
|
);
|
|
197
|
+
assert.equal(result.blockingStrandedWork?.recoveryMode, "worktree");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("detects dirty in-progress worktree even when branch has no commits ahead", () => {
|
|
201
|
+
run("git branch milestone/M001", dir);
|
|
202
|
+
|
|
203
|
+
const wtDir = join(dir, ".gsd", "worktrees", "M001");
|
|
204
|
+
mkdirSync(wtDir, { recursive: true });
|
|
205
|
+
writeFileSync(join(wtDir, ".git"), `gitdir: ${join(dir, ".git", "worktrees", "M001")}\n`);
|
|
206
|
+
writeFileSync(join(wtDir, "dirty.txt"), "uncommitted work\n");
|
|
207
|
+
|
|
208
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
209
|
+
|
|
210
|
+
const result = auditOrphanedMilestoneBranches(dir, "worktree", {
|
|
211
|
+
hasChanges: (basePath) => basePath === wtDir,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
assert.deepStrictEqual(result.recovered, []);
|
|
215
|
+
assert.ok(
|
|
216
|
+
result.warnings.some((w) => w.includes("uncommitted changes")),
|
|
217
|
+
`dirty worktree should be treated as stranded work; got: ${JSON.stringify(result.warnings)}`,
|
|
218
|
+
);
|
|
219
|
+
assert.equal(result.blockingStrandedWork?.milestoneId, "M001");
|
|
220
|
+
assert.equal(result.blockingStrandedWork?.dirtyWorktree, true);
|
|
221
|
+
assert.equal(result.blockingStrandedWork?.recoveryMode, "worktree");
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("detects dirty in-progress worktree even when milestone branch is absent", () => {
|
|
225
|
+
const wtDir = join(dir, ".gsd", "worktrees", "M001");
|
|
226
|
+
mkdirSync(wtDir, { recursive: true });
|
|
227
|
+
writeFileSync(join(wtDir, ".git"), `gitdir: ${join(dir, ".git", "worktrees", "M001")}\n`);
|
|
228
|
+
writeFileSync(join(wtDir, "dirty.txt"), "branchless work\n");
|
|
229
|
+
|
|
230
|
+
insertMilestone({ id: "M001", title: "Test", status: "active" });
|
|
231
|
+
|
|
232
|
+
const result = auditOrphanedMilestoneBranches(dir, "none", {
|
|
233
|
+
hasChanges: (basePath) => basePath === wtDir,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
assert.deepStrictEqual(result.recovered, []);
|
|
237
|
+
assert.ok(
|
|
238
|
+
result.warnings.some((w) => w.includes("Stranded work") && w.includes("M001")),
|
|
239
|
+
`branchless dirty worktree should block; got: ${JSON.stringify(result.warnings)}`,
|
|
240
|
+
);
|
|
241
|
+
assert.equal(result.blockingStrandedWork?.branch, undefined);
|
|
242
|
+
assert.equal(result.blockingStrandedWork?.dirtyWorktree, true);
|
|
243
|
+
assert.equal(result.blockingStrandedWork?.recoveryMode, "worktree");
|
|
187
244
|
});
|
|
188
245
|
|
|
189
246
|
test("cleans up orphaned worktree directory for merged milestone", () => {
|
|
@@ -359,7 +416,7 @@ describe("auditOrphanedMilestoneBranches", () => {
|
|
|
359
416
|
assert.ok(existsSync(wtDir), "active milestone worktree dir must be preserved");
|
|
360
417
|
});
|
|
361
418
|
|
|
362
|
-
test("#5879 —
|
|
419
|
+
test("#5879 — cleans branch-less complete orphan in 'none' isolation mode", () => {
|
|
363
420
|
insertMilestone({ id: "M001", title: "Test", status: "complete" });
|
|
364
421
|
|
|
365
422
|
const wtDir = join(dir, ".gsd", "worktrees", "M001");
|
|
@@ -368,7 +425,10 @@ describe("auditOrphanedMilestoneBranches", () => {
|
|
|
368
425
|
|
|
369
426
|
const result = auditOrphanedMilestoneBranches(dir, "none");
|
|
370
427
|
|
|
371
|
-
assert.
|
|
372
|
-
|
|
428
|
+
assert.ok(
|
|
429
|
+
result.recovered.some((r) => r.includes("M001") && r.includes("branch already deleted")),
|
|
430
|
+
`none mode should still clean safe completed residue; got: ${JSON.stringify(result.recovered)}`,
|
|
431
|
+
);
|
|
432
|
+
assert.ok(!existsSync(wtDir), "completed orphan worktree dir should be cleaned in none mode");
|
|
373
433
|
});
|
|
374
434
|
});
|
|
@@ -5,6 +5,7 @@ import { describe, it } from "node:test";
|
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
6
|
|
|
7
7
|
import { visibleWidth } from "@gsd/pi-tui";
|
|
8
|
+
import { assertFullOuterBorder } from "./tui-border-assertions.ts";
|
|
8
9
|
|
|
9
10
|
function assertLinesFit(lines: string[], width: number): void {
|
|
10
11
|
for (const line of lines) {
|
|
@@ -51,6 +52,9 @@ describe("parallel-monitor-overlay", () => {
|
|
|
51
52
|
const joined = lines.join("\n");
|
|
52
53
|
assert.ok(joined.includes("Parallel Monitor"), "should include title");
|
|
53
54
|
assert.ok(joined.includes("No parallel workers found"), "should show empty state");
|
|
55
|
+
assertFullOuterBorder(lines, 80);
|
|
56
|
+
assert.match(lines[0] ?? "", /^╭─ GSD Parallel Monitor /);
|
|
57
|
+
assert.match(lines.at(-1) ?? "", /^╰─+╯$/);
|
|
54
58
|
|
|
55
59
|
// Dispose should not throw
|
|
56
60
|
overlay.dispose();
|
|
@@ -105,7 +109,9 @@ describe("parallel-monitor-overlay", () => {
|
|
|
105
109
|
);
|
|
106
110
|
|
|
107
111
|
for (const width of [40, 80, 120]) {
|
|
108
|
-
|
|
112
|
+
const lines = overlay.render(width);
|
|
113
|
+
assertLinesFit(lines, width);
|
|
114
|
+
assertFullOuterBorder(lines, width);
|
|
109
115
|
overlay.invalidate();
|
|
110
116
|
}
|
|
111
117
|
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
openDatabase,
|
|
20
20
|
} from "../gsd-db.ts";
|
|
21
21
|
import { createWorktree } from "../worktree-manager.ts";
|
|
22
|
+
import { _resetLogs, drainLogs, setStderrLoggingEnabled } from "../workflow-logger.ts";
|
|
22
23
|
|
|
23
24
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
24
25
|
|
|
@@ -190,7 +191,9 @@ test('getActiveMilestoneId skips parked', async () => {
|
|
|
190
191
|
// ─── Test 10: discardMilestone removes directory ──────────────────────
|
|
191
192
|
test('discardMilestone removes directory', async () => {
|
|
192
193
|
const base = createFixtureBase();
|
|
194
|
+
const previousStderr = setStderrLoggingEnabled(false);
|
|
193
195
|
try {
|
|
196
|
+
_resetLogs();
|
|
194
197
|
createMilestone(base, 'M001', { withRoadmap: true });
|
|
195
198
|
clearCaches();
|
|
196
199
|
|
|
@@ -200,7 +203,13 @@ test('discardMilestone removes directory', async () => {
|
|
|
200
203
|
const success = discardMilestone(base, 'M001');
|
|
201
204
|
assert.ok(success, 'discardMilestone returns true');
|
|
202
205
|
assert.ok(!existsSync(mDir), 'milestone dir removed after discard');
|
|
206
|
+
const logs = drainLogs();
|
|
207
|
+
assert.ok(
|
|
208
|
+
logs.some((entry) => entry.message.includes('discardMilestone DB cleanup skipped for M001: database unavailable')),
|
|
209
|
+
'discardMilestone warns when DB cleanup is skipped',
|
|
210
|
+
);
|
|
203
211
|
} finally {
|
|
212
|
+
setStderrLoggingEnabled(previousStderr);
|
|
204
213
|
cleanup(base);
|
|
205
214
|
}
|
|
206
215
|
});
|