@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.a271e2d
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/onboarding.js +22 -3
- package/dist/resource-loader.js +3 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- 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 +62 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +37 -0
- 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 +21 -11
- 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.js +6 -1
- 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 +17 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- 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-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-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +6 -1
- 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/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- 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/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -3
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +11 -4
- 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.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/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/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
- 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 +6 -6
- 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/package.json +1 -1
- 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 +7 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +8 -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/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.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/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +28 -5
- 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/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 +8 -59
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +21 -72
- 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/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/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- 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 +74 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +46 -0
- 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 +43 -14
- 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.ts +6 -1
- 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 +18 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- 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-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-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +6 -1
- 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/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- 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/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -3
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -4
- 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.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 +21 -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 +12 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -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/context-chart.test.ts +9 -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-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/key-manager.test.ts +23 -4
- 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/post-unit-retry-on-orchestrator-bridge.test.ts +93 -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/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 +19 -0
- 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 +74 -1
- 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/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/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/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → QKed8_bmMc7zc3WLM7MW9}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → QKed8_bmMc7zc3WLM7MW9}/_ssgManifest.js +0 -0
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
scanSessionTokenTotals,
|
|
9
9
|
handleUsage,
|
|
10
10
|
} from "../commands-usage.ts";
|
|
11
|
+
import { assertFullOuterBorder } from "./tui-border-assertions.ts";
|
|
11
12
|
|
|
12
13
|
const TS = 1;
|
|
13
14
|
|
|
@@ -108,3 +109,99 @@ test("handleUsage emits JSON when --json is passed", async () => {
|
|
|
108
109
|
assert.equal(parsed.contextUsage.tokens, 10_000);
|
|
109
110
|
assert.equal(parsed.sessionTotals.input, 0);
|
|
110
111
|
});
|
|
112
|
+
|
|
113
|
+
test("handleUsage renders interactive usage output inside a full border", async () => {
|
|
114
|
+
let renderFn: ((width: number) => string[]) | undefined;
|
|
115
|
+
const messages: string[] = [];
|
|
116
|
+
const ctx = {
|
|
117
|
+
hasUI: true,
|
|
118
|
+
model: { provider: "claude-code", id: "claude-sonnet-4-6", contextWindow: 200_000 },
|
|
119
|
+
getContextUsage: () => ({ tokens: 10_000, contextWindow: 200_000, percent: 5 }),
|
|
120
|
+
sessionManager: { getEntries: () => [] },
|
|
121
|
+
ui: {
|
|
122
|
+
custom: async (factory: any) => {
|
|
123
|
+
const theme = {
|
|
124
|
+
fg: (_color: string, text: string) => text,
|
|
125
|
+
bold: (text: string) => text,
|
|
126
|
+
};
|
|
127
|
+
const component = factory({ requestRender: () => {} }, theme, {}, () => {});
|
|
128
|
+
renderFn = component.render;
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
131
|
+
notify(message: string) {
|
|
132
|
+
messages.push(message);
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
await handleUsage("", ctx as any);
|
|
138
|
+
|
|
139
|
+
assert.equal(messages.length, 0, "interactive usage should use the dialog instead of notify");
|
|
140
|
+
assert.ok(renderFn, "render function should have been captured");
|
|
141
|
+
const lines = renderFn!(80);
|
|
142
|
+
assertFullOuterBorder(lines, 80);
|
|
143
|
+
assert.match(lines.join("\n"), /claude-code\/claude-sonnet-4-6/);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test("handleUsage keeps short-terminal usage dialog scrollable", async () => {
|
|
147
|
+
const originalRowsDescriptor = Object.getOwnPropertyDescriptor(process.stdout, "rows");
|
|
148
|
+
Object.defineProperty(process.stdout, "rows", { value: 10, configurable: true });
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
let component: { render(width: number): string[]; handleInput(data: string): void } | undefined;
|
|
152
|
+
let closed = false;
|
|
153
|
+
const ctx = {
|
|
154
|
+
hasUI: true,
|
|
155
|
+
model: { provider: "claude-code", id: "claude-sonnet-4-6", contextWindow: 200_000 },
|
|
156
|
+
getContextUsage: () => ({ tokens: 10_000, contextWindow: 200_000, percent: 5 }),
|
|
157
|
+
sessionManager: {
|
|
158
|
+
getEntries: () => sessionEntries({
|
|
159
|
+
role: "assistant",
|
|
160
|
+
usage: {
|
|
161
|
+
input: 1000,
|
|
162
|
+
output: 200,
|
|
163
|
+
cacheRead: 500,
|
|
164
|
+
cacheWrite: 100,
|
|
165
|
+
totalTokens: 1800,
|
|
166
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0.05 },
|
|
167
|
+
},
|
|
168
|
+
content: [{ type: "toolCall", id: "tc-1", name: "read", arguments: {} }],
|
|
169
|
+
timestamp: TS,
|
|
170
|
+
}),
|
|
171
|
+
},
|
|
172
|
+
ui: {
|
|
173
|
+
custom: async (factory: any) => {
|
|
174
|
+
const theme = {
|
|
175
|
+
fg: (_color: string, text: string) => text,
|
|
176
|
+
bold: (text: string) => text,
|
|
177
|
+
};
|
|
178
|
+
component = factory({ requestRender: () => {} }, theme, {}, () => {
|
|
179
|
+
closed = true;
|
|
180
|
+
});
|
|
181
|
+
return true;
|
|
182
|
+
},
|
|
183
|
+
notify() {},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
await handleUsage("", ctx as any);
|
|
188
|
+
|
|
189
|
+
assert.ok(component, "usage dialog should render via custom UI");
|
|
190
|
+
const initialLines = component.render(80);
|
|
191
|
+
assert.ok(initialLines.length <= 8, `usage dialog should fit 80% terminal height, got ${initialLines.length}`);
|
|
192
|
+
|
|
193
|
+
for (let i = 0; i < 10; i++) component.handleInput("\u001b[B");
|
|
194
|
+
|
|
195
|
+
assert.equal(closed, false, "scroll keys should not close a scrollable usage dialog");
|
|
196
|
+
assert.match(component.render(80).join("\n"), /Tool calls: 1/);
|
|
197
|
+
|
|
198
|
+
component.handleInput("x");
|
|
199
|
+
assert.equal(closed, true, "non-scroll keys should close the usage dialog");
|
|
200
|
+
} finally {
|
|
201
|
+
if (originalRowsDescriptor) {
|
|
202
|
+
Object.defineProperty(process.stdout, "rows", originalRowsDescriptor);
|
|
203
|
+
} else {
|
|
204
|
+
delete (process.stdout as { rows?: number }).rows;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
@@ -10,6 +10,7 @@ import type { ContextBreakdownReport } from "../commands-context.ts";
|
|
|
10
10
|
import { buildContextChartHtml, writeContextChartHtml } from "../context-chart-html.ts";
|
|
11
11
|
import { formatContextChartText, getContextChartTotals } from "../context-overlay.ts";
|
|
12
12
|
import { buildContextBreakdown } from "../commands-context.ts";
|
|
13
|
+
import { assertFullOuterBorder } from "./tui-border-assertions.ts";
|
|
13
14
|
|
|
14
15
|
const TS = 1;
|
|
15
16
|
|
|
@@ -103,3 +104,11 @@ test("formatContextChartText includes chart sections", () => {
|
|
|
103
104
|
assert.match(text, /Conversation/);
|
|
104
105
|
assert.match(text, /█/);
|
|
105
106
|
});
|
|
107
|
+
|
|
108
|
+
test("formatContextChartText renders the context dialog inside a full border", () => {
|
|
109
|
+
const lines = formatContextChartText(SAMPLE_REPORT, 80).split("\n");
|
|
110
|
+
assertFullOuterBorder(lines, 80);
|
|
111
|
+
assert.match(lines[0] ?? "", /^╭─ Context Breakdown /);
|
|
112
|
+
assert.ok(lines.some((line) => line.startsWith("│")), "body rows should have side borders");
|
|
113
|
+
assert.match(lines.at(-1) ?? "", /^╰─+╯$/);
|
|
114
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GSD dashboard overlay dialog chrome tests.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
|
|
8
|
+
import { GSDDashboardOverlay } from "../dashboard-overlay.ts";
|
|
9
|
+
import { assertFullOuterBorder } from "./tui-border-assertions.ts";
|
|
10
|
+
|
|
11
|
+
const fakeTheme = {
|
|
12
|
+
fg: (_color: string, text: string) => text,
|
|
13
|
+
bold: (text: string) => text,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
test("GSDDashboardOverlay renders inside the shared full border", (t) => {
|
|
17
|
+
const overlay = new GSDDashboardOverlay({ requestRender() {} }, fakeTheme as any, () => {});
|
|
18
|
+
t.after(() => overlay.dispose());
|
|
19
|
+
|
|
20
|
+
const lines = overlay.render(100);
|
|
21
|
+
assertFullOuterBorder(lines, 100);
|
|
22
|
+
assert.match(lines[0] ?? "", /^╭─ GSD Dashboard /);
|
|
23
|
+
assert.ok(lines.some((line) => line.startsWith("│")), "body rows should have side borders");
|
|
24
|
+
assert.match(lines.at(-1) ?? "", /^╰─+╯$/);
|
|
25
|
+
});
|
|
@@ -19,6 +19,7 @@ const VALID_INVITE = "https://discord.gg/8NnkKuepmQ";
|
|
|
19
19
|
const FILES_WITH_INVITE_LINKS: string[] = [
|
|
20
20
|
"README.md",
|
|
21
21
|
"docs/dev/what-is-pi/15-pi-packages-the-ecosystem.md",
|
|
22
|
+
"packages/pi-coding-agent/README.md",
|
|
22
23
|
];
|
|
23
24
|
|
|
24
25
|
describe("Discord invite links (#2699)", () => {
|
|
@@ -9,7 +9,9 @@ const discussPrompt = readFileSync(promptPath, "utf-8");
|
|
|
9
9
|
test("discuss prompt: resilient vision framing", () => {
|
|
10
10
|
const hardenedPattern = /Say exactly:\s*"What's the vision\?"/;
|
|
11
11
|
assert.ok(!hardenedPattern.test(discussPrompt), "prompt no longer uses exact-verbosity lock");
|
|
12
|
-
assert.ok(discussPrompt.includes('Ask
|
|
12
|
+
assert.ok(discussPrompt.includes('Ask exactly this once: "{{visionAsk}}"'), "prompt asks the injected vision opener exactly once");
|
|
13
|
+
assert.ok(discussPrompt.includes("The opener is intentionally variable"), "prompt documents variable opener voice");
|
|
13
14
|
assert.ok(discussPrompt.includes("Special handling"), "prompt documents special handling");
|
|
14
|
-
assert.ok(discussPrompt.includes(
|
|
15
|
+
assert.ok(discussPrompt.includes("instead of repeating the opener"), "prompt forbids repeating the opener");
|
|
16
|
+
assert.ok(!discussPrompt.includes('"What\'s the vision?"'), "prompt no longer freezes the old opener");
|
|
15
17
|
});
|
|
@@ -111,7 +111,7 @@ describe("discuss tool scoping (#2949)", () => {
|
|
|
111
111
|
setCalls.push([...tools]);
|
|
112
112
|
activeTools = [...tools];
|
|
113
113
|
},
|
|
114
|
-
sendMessage: (message: unknown) => {
|
|
114
|
+
sendMessage: async (message: unknown) => {
|
|
115
115
|
sent.push(message);
|
|
116
116
|
sentTools = [...activeTools];
|
|
117
117
|
},
|
|
@@ -702,6 +702,48 @@ test("runProviderChecks reports ok for claude-code without any API key", () => {
|
|
|
702
702
|
rmSync(tmpHome, { recursive: true, force: true });
|
|
703
703
|
});
|
|
704
704
|
|
|
705
|
+
test("runProviderChecks reports errors for required Google CLI providers missing from PATH", () => {
|
|
706
|
+
const scenarios = [
|
|
707
|
+
{ provider: "google-gemini-cli", label: "Google Gemini CLI", model: "gemini-2.5-pro" },
|
|
708
|
+
{ provider: "google-antigravity", label: "Antigravity", model: "default" },
|
|
709
|
+
];
|
|
710
|
+
|
|
711
|
+
for (const { provider, label, model } of scenarios) {
|
|
712
|
+
const repo = realpathSync(mkdtempSync(join(tmpdir(), `gsd-providers-${provider}-repo-`)));
|
|
713
|
+
mkdirSync(join(repo, ".gsd"), { recursive: true });
|
|
714
|
+
writeFileSync(
|
|
715
|
+
join(repo, ".gsd", "PREFERENCES.md"),
|
|
716
|
+
[
|
|
717
|
+
"---",
|
|
718
|
+
"models:",
|
|
719
|
+
" execution:",
|
|
720
|
+
` model: ${model}`,
|
|
721
|
+
` provider: ${provider}`,
|
|
722
|
+
"---",
|
|
723
|
+
"",
|
|
724
|
+
].join("\n"),
|
|
725
|
+
);
|
|
726
|
+
|
|
727
|
+
const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), `gsd-providers-${provider}-home-`)));
|
|
728
|
+
|
|
729
|
+
withEnv({
|
|
730
|
+
HOME: tmpHome,
|
|
731
|
+
PATH: tmpHome,
|
|
732
|
+
}, () => {
|
|
733
|
+
withCwd(repo, () => {
|
|
734
|
+
const results = runProviderChecks();
|
|
735
|
+
const cli = results.find(r => r.name === provider);
|
|
736
|
+
assert.ok(cli, `${provider} result should exist`);
|
|
737
|
+
assert.equal(cli!.status, "error", `${provider} should error when the CLI binary is missing`);
|
|
738
|
+
assert.ok(cli!.detail?.includes(label), "should explain which CLI must be installed");
|
|
739
|
+
});
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
rmSync(repo, { recursive: true, force: true });
|
|
743
|
+
rmSync(tmpHome, { recursive: true, force: true });
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
|
|
705
747
|
test("runProviderChecks reports ok for Anthropic via claude-code binary in PATH", () => {
|
|
706
748
|
// Simulate a user who has no Anthropic API key but has the claude CLI installed.
|
|
707
749
|
// Their PREFERENCES use a claude model without an explicit provider, so the doctor
|
|
@@ -736,6 +778,69 @@ test("runProviderChecks reports ok for Anthropic via claude-code binary in PATH"
|
|
|
736
778
|
});
|
|
737
779
|
});
|
|
738
780
|
|
|
781
|
+
test("runProviderChecks ignores external CLI auth sentinels when the CLI is missing", () => {
|
|
782
|
+
const scenarios = [
|
|
783
|
+
{
|
|
784
|
+
requiredProvider: "anthropic",
|
|
785
|
+
routeProvider: "claude-code",
|
|
786
|
+
model: "claude-sonnet-4-6",
|
|
787
|
+
env: {
|
|
788
|
+
ANTHROPIC_API_KEY: undefined,
|
|
789
|
+
ANTHROPIC_OAUTH_TOKEN: undefined,
|
|
790
|
+
COPILOT_GITHUB_TOKEN: undefined,
|
|
791
|
+
GH_TOKEN: undefined,
|
|
792
|
+
GITHUB_TOKEN: undefined,
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
requiredProvider: "google",
|
|
797
|
+
routeProvider: "google-gemini-cli",
|
|
798
|
+
model: "gemini-2.5-pro",
|
|
799
|
+
env: {
|
|
800
|
+
GEMINI_API_KEY: undefined,
|
|
801
|
+
GOOGLE_API_KEY: undefined,
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
];
|
|
805
|
+
|
|
806
|
+
for (const { requiredProvider, routeProvider, model, env } of scenarios) {
|
|
807
|
+
const repo = realpathSync(mkdtempSync(join(tmpdir(), `gsd-providers-${routeProvider}-sentinel-repo-`)));
|
|
808
|
+
const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), `gsd-providers-${routeProvider}-sentinel-home-`)));
|
|
809
|
+
const agentDir = join(tmpHome, ".gsd", "agent");
|
|
810
|
+
mkdirSync(join(repo, ".gsd"), { recursive: true });
|
|
811
|
+
mkdirSync(agentDir, { recursive: true });
|
|
812
|
+
writeFileSync(
|
|
813
|
+
join(repo, ".gsd", "PREFERENCES.md"),
|
|
814
|
+
[
|
|
815
|
+
"---",
|
|
816
|
+
"models:",
|
|
817
|
+
` execution: ${model}`,
|
|
818
|
+
"---",
|
|
819
|
+
"",
|
|
820
|
+
].join("\n"),
|
|
821
|
+
);
|
|
822
|
+
writeFileSync(join(agentDir, "auth.json"), JSON.stringify({
|
|
823
|
+
[routeProvider]: { type: "api_key", key: "cli" },
|
|
824
|
+
}));
|
|
825
|
+
|
|
826
|
+
withEnv({
|
|
827
|
+
...env,
|
|
828
|
+
HOME: tmpHome,
|
|
829
|
+
PATH: tmpHome,
|
|
830
|
+
}, () => {
|
|
831
|
+
withCwd(repo, () => {
|
|
832
|
+
const results = runProviderChecks();
|
|
833
|
+
const provider = results.find(r => r.name === requiredProvider);
|
|
834
|
+
assert.ok(provider, `${requiredProvider} result should exist`);
|
|
835
|
+
assert.equal(provider!.status, "error", `${routeProvider} sentinel should not satisfy ${requiredProvider}`);
|
|
836
|
+
});
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
rmSync(repo, { recursive: true, force: true });
|
|
840
|
+
rmSync(tmpHome, { recursive: true, force: true });
|
|
841
|
+
}
|
|
842
|
+
});
|
|
843
|
+
|
|
739
844
|
test("runProviderChecks detects claude.cmd in PATH on Windows (#4503)", { skip: process.platform !== "win32" }, () => {
|
|
740
845
|
const tmpHome = realpathSync(mkdtempSync(join(tmpdir(), "gsd-providers-cc-win-route-home-")));
|
|
741
846
|
const binDir = join(tmpHome, "bin");
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { afterEach, test } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { closeDatabase } from "../gsd-db.ts";
|
|
3
|
+
import { _getAdapter, closeDatabase, insertMilestone, openDatabase } from "../gsd-db.ts";
|
|
4
4
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
7
|
import { filterDoctorIssues } from "../doctor-format.ts";
|
|
8
8
|
import { checkEngineHealth } from "../doctor-engine-checks.ts";
|
|
9
|
+
import { appendEvent } from "../workflow-events.ts";
|
|
9
10
|
|
|
10
11
|
afterEach(() => {
|
|
11
12
|
closeDatabase();
|
|
@@ -41,3 +42,102 @@ test("checkEngineHealth reports db_unavailable when gsd.db exists but the DB is
|
|
|
41
42
|
assert.equal(dbIssue.unitId, "project");
|
|
42
43
|
assert.equal(dbIssue.file, ".gsd/gsd.db");
|
|
43
44
|
});
|
|
45
|
+
|
|
46
|
+
test("checkEngineHealth reads canonical reopen events from worktree bases", async (t) => {
|
|
47
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-doctor-reopen-worktree-"));
|
|
48
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
49
|
+
|
|
50
|
+
const gsdDir = join(base, ".gsd");
|
|
51
|
+
const worktree = join(gsdDir, "worktrees", "M001");
|
|
52
|
+
mkdirSync(join(worktree, ".gsd"), { recursive: true });
|
|
53
|
+
writeFileSync(join(worktree, ".git"), "gitdir: ../../../../.git/worktrees/M001\n", "utf-8");
|
|
54
|
+
|
|
55
|
+
openDatabase(join(gsdDir, "gsd.db"));
|
|
56
|
+
insertMilestone({ id: "M001", title: "Reopened", status: "active" });
|
|
57
|
+
const db = _getAdapter()!;
|
|
58
|
+
db.prepare(
|
|
59
|
+
`INSERT INTO workers (
|
|
60
|
+
worker_id, host, pid, started_at, version, last_heartbeat_at, status, project_root_realpath
|
|
61
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
62
|
+
).run("worker-1", "localhost", 1, "2026-01-01T00:00:00.000Z", "test", "2026-01-01T00:00:00.000Z", "stopped", base);
|
|
63
|
+
db.prepare(
|
|
64
|
+
`INSERT INTO unit_dispatches (
|
|
65
|
+
trace_id, worker_id, milestone_lease_token, milestone_id,
|
|
66
|
+
unit_type, unit_id, status, attempt_n, started_at, ended_at
|
|
67
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
68
|
+
).run(
|
|
69
|
+
"trace-1",
|
|
70
|
+
"worker-1",
|
|
71
|
+
1,
|
|
72
|
+
"M001",
|
|
73
|
+
"complete-milestone",
|
|
74
|
+
"M001",
|
|
75
|
+
"completed",
|
|
76
|
+
1,
|
|
77
|
+
"2026-01-01T00:00:00.000Z",
|
|
78
|
+
"2026-01-01T00:00:01.000Z",
|
|
79
|
+
);
|
|
80
|
+
appendEvent(base, {
|
|
81
|
+
cmd: "reopen-milestone",
|
|
82
|
+
params: { milestoneId: "M001" },
|
|
83
|
+
ts: "2026-01-01T00:00:02.000Z",
|
|
84
|
+
actor: "agent",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const issues: any[] = [];
|
|
88
|
+
await checkEngineHealth(worktree, issues, []);
|
|
89
|
+
|
|
90
|
+
assert.equal(
|
|
91
|
+
issues.some((issue) => issue.code === "completed_milestone_reopened"),
|
|
92
|
+
false,
|
|
93
|
+
"canonical reopen event should exempt the reopened milestone from doctor drift errors",
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("checkEngineHealth treats explicit reopen as authoritative when dispatch timestamps are missing", async (t) => {
|
|
98
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-doctor-reopen-no-dispatch-time-"));
|
|
99
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
100
|
+
|
|
101
|
+
const gsdDir = join(base, ".gsd");
|
|
102
|
+
mkdirSync(gsdDir, { recursive: true });
|
|
103
|
+
|
|
104
|
+
openDatabase(join(gsdDir, "gsd.db"));
|
|
105
|
+
insertMilestone({ id: "M001", title: "Reopened", status: "active" });
|
|
106
|
+
const db = _getAdapter()!;
|
|
107
|
+
db.prepare(
|
|
108
|
+
`INSERT INTO workers (
|
|
109
|
+
worker_id, host, pid, started_at, version, last_heartbeat_at, status, project_root_realpath
|
|
110
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
111
|
+
).run("worker-1", "localhost", 1, "2026-01-01T00:00:00.000Z", "test", "2026-01-01T00:00:00.000Z", "stopped", base);
|
|
112
|
+
db.exec("PRAGMA writable_schema = ON");
|
|
113
|
+
db.prepare(
|
|
114
|
+
`UPDATE sqlite_schema
|
|
115
|
+
SET sql = replace(sql, 'started_at TEXT NOT NULL', 'started_at TEXT')
|
|
116
|
+
WHERE type = 'table' AND name = 'unit_dispatches'`,
|
|
117
|
+
).run();
|
|
118
|
+
db.exec("PRAGMA writable_schema = OFF");
|
|
119
|
+
closeDatabase();
|
|
120
|
+
openDatabase(join(gsdDir, "gsd.db"));
|
|
121
|
+
const reopenedDb = _getAdapter()!;
|
|
122
|
+
reopenedDb.prepare(
|
|
123
|
+
`INSERT INTO unit_dispatches (
|
|
124
|
+
trace_id, worker_id, milestone_lease_token, milestone_id,
|
|
125
|
+
unit_type, unit_id, status, attempt_n, started_at, ended_at
|
|
126
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
127
|
+
).run("trace-1", "worker-1", 1, "M001", "complete-milestone", "M001", "completed", 1, null, null);
|
|
128
|
+
appendEvent(base, {
|
|
129
|
+
cmd: "reopen-milestone",
|
|
130
|
+
params: { milestoneId: "M001" },
|
|
131
|
+
ts: "2026-01-01T00:00:02.000Z",
|
|
132
|
+
actor: "agent",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const issues: any[] = [];
|
|
136
|
+
await checkEngineHealth(base, issues, []);
|
|
137
|
+
|
|
138
|
+
assert.equal(
|
|
139
|
+
issues.some((issue) => issue.code === "completed_milestone_reopened"),
|
|
140
|
+
false,
|
|
141
|
+
"explicit reopen should exempt reopened milestone even when completion dispatch timestamps are absent",
|
|
142
|
+
);
|
|
143
|
+
});
|
|
@@ -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"/);
|
|
@@ -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", () => {
|
|
@@ -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
|
});
|