@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.cce3612
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/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 +18 -2
- 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/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/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/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 +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/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/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- 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.js +1 -1
- 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 +37 -2
- 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/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/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-recovery.test.ts +41 -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/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/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 → orfEoZqDIo6Be_Z9ZFipD}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → orfEoZqDIo6Be_Z9ZFipD}/_ssgManifest.js +0 -0
|
@@ -108,6 +108,34 @@ test("executeSummarySave persists artifact and returns computed path", async ()
|
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
+
test("executeSummarySave mirrors milestone artifacts into the active worktree projection", async () => {
|
|
112
|
+
const base = makeTmpBase();
|
|
113
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
114
|
+
try {
|
|
115
|
+
mkdirSync(join(worktree, ".gsd"), { recursive: true });
|
|
116
|
+
writeFileSync(join(worktree, ".git"), "gitdir: ../../../.git/worktrees/M001\n");
|
|
117
|
+
openTestDb(base);
|
|
118
|
+
|
|
119
|
+
const result = await inProjectDir(worktree, () => executeSummarySave({
|
|
120
|
+
milestone_id: "M001",
|
|
121
|
+
slice_id: "S02",
|
|
122
|
+
artifact_type: "RESEARCH",
|
|
123
|
+
content: "# S02 Research\n\ncanonical and worktree",
|
|
124
|
+
}, worktree));
|
|
125
|
+
|
|
126
|
+
assert.equal(result.details.operation, "save_summary");
|
|
127
|
+
const relPath = "milestones/M001/slices/S02/S02-RESEARCH.md";
|
|
128
|
+
const projectPath = join(base, ".gsd", relPath);
|
|
129
|
+
const worktreePath = join(worktree, ".gsd", relPath);
|
|
130
|
+
assert.equal(existsSync(projectPath), true, "canonical artifact should be written");
|
|
131
|
+
assert.equal(existsSync(worktreePath), true, "active worktree projection should be mirrored");
|
|
132
|
+
assert.match(readFileSync(worktreePath, "utf-8"), /S02 Research/);
|
|
133
|
+
} finally {
|
|
134
|
+
closeDatabase();
|
|
135
|
+
cleanup(base);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
111
139
|
test("executeTaskComplete coerces string verificationEvidence entries", async () => {
|
|
112
140
|
const base = makeTmpBase();
|
|
113
141
|
try {
|
|
@@ -148,6 +176,60 @@ test("executeTaskComplete coerces string verificationEvidence entries", async ()
|
|
|
148
176
|
}
|
|
149
177
|
});
|
|
150
178
|
|
|
179
|
+
test("executeTaskComplete derives missing verification from evidence", async () => {
|
|
180
|
+
const base = makeTmpBase();
|
|
181
|
+
try {
|
|
182
|
+
openTestDb(base);
|
|
183
|
+
const planDir = join(base, ".gsd", "milestones", "M001", "slices", "S01");
|
|
184
|
+
mkdirSync(planDir, { recursive: true });
|
|
185
|
+
writeFileSync(join(planDir, "S01-PLAN.md"), "# S01\n\n- [ ] **T01: Demo** `est:5m`\n");
|
|
186
|
+
|
|
187
|
+
const result = await inProjectDir(base, () => executeTaskComplete({
|
|
188
|
+
milestoneId: "M001",
|
|
189
|
+
sliceId: "S01",
|
|
190
|
+
taskId: "T01",
|
|
191
|
+
oneLiner: "Completed task",
|
|
192
|
+
narrative: "Did the work",
|
|
193
|
+
verificationEvidence: [
|
|
194
|
+
{ command: "npm test", exitCode: 0, verdict: "pass", durationMs: 1234 },
|
|
195
|
+
],
|
|
196
|
+
}, base));
|
|
197
|
+
|
|
198
|
+
assert.equal(result.details.operation, "complete_task");
|
|
199
|
+
const db = _getAdapter();
|
|
200
|
+
assert.ok(db, "DB should be open");
|
|
201
|
+
const row = db!.prepare(
|
|
202
|
+
"SELECT verification_result FROM tasks WHERE milestone_id = ? AND slice_id = ? AND id = ?",
|
|
203
|
+
).get("M001", "S01", "T01") as Record<string, unknown> | undefined;
|
|
204
|
+
|
|
205
|
+
assert.match(String(row?.verification_result), /Verification evidence recorded/);
|
|
206
|
+
assert.match(String(row?.verification_result), /`npm test` exited 0 \(pass\)/);
|
|
207
|
+
} finally {
|
|
208
|
+
closeDatabase();
|
|
209
|
+
cleanup(base);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("executeTaskComplete returns a tool error when verification cannot be derived", async () => {
|
|
214
|
+
const base = makeTmpBase();
|
|
215
|
+
try {
|
|
216
|
+
openTestDb(base);
|
|
217
|
+
const result = await inProjectDir(base, () => executeTaskComplete({
|
|
218
|
+
milestoneId: "M001",
|
|
219
|
+
sliceId: "S01",
|
|
220
|
+
taskId: "T01",
|
|
221
|
+
oneLiner: "Completed task",
|
|
222
|
+
narrative: "Did the work",
|
|
223
|
+
}, base));
|
|
224
|
+
|
|
225
|
+
assert.equal(result.isError, true);
|
|
226
|
+
assert.match(String(result.content[0]?.text), /verification is required/);
|
|
227
|
+
} finally {
|
|
228
|
+
closeDatabase();
|
|
229
|
+
cleanup(base);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
|
|
151
233
|
test("executeSliceComplete preserves omitted optional requirement arrays", async () => {
|
|
152
234
|
const base = makeTmpBase();
|
|
153
235
|
try {
|
|
@@ -9,7 +9,7 @@ import { join } from "node:path";
|
|
|
9
9
|
import { probeGitConflictState } from "../git-conflict-state.js";
|
|
10
10
|
import { ensureWorkspaceGitReadyForPath } from "../workspace-git-preflight.js";
|
|
11
11
|
import { isWorkspaceGitAllowedCommand } from "../workspace-git-guard.js";
|
|
12
|
-
import { cleanup, git, makeTempRepo } from "./test-utils.ts";
|
|
12
|
+
import { cleanup, git, makeTempDir, makeTempRepo } from "./test-utils.ts";
|
|
13
13
|
|
|
14
14
|
function seedGsdConflict(base: string): void {
|
|
15
15
|
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
@@ -60,6 +60,21 @@ test("probeGitConflictState reports clean repo", () => {
|
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
test("ensureWorkspaceGitReadyForPath allows fresh non-git project setup folders", async () => {
|
|
64
|
+
const base = makeTempDir("gsd-ws-git-non-repo-");
|
|
65
|
+
try {
|
|
66
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
67
|
+
|
|
68
|
+
const probe = probeGitConflictState(base);
|
|
69
|
+
assert.equal(probe.status, "clean");
|
|
70
|
+
|
|
71
|
+
const ready = await ensureWorkspaceGitReadyForPath(base);
|
|
72
|
+
assert.equal(ready.ok, true);
|
|
73
|
+
} finally {
|
|
74
|
+
cleanup(base);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
63
78
|
test("ensureWorkspaceGitReadyForPath auto-resolves .gsd/ conflicts", async () => {
|
|
64
79
|
const base = makeTempRepo("gsd-ws-git-heal-");
|
|
65
80
|
try {
|
|
@@ -212,6 +212,34 @@ test("enterMilestone returns ok:true mode:none when isolation disabled", () => {
|
|
|
212
212
|
assert.equal(s.basePath, "/project");
|
|
213
213
|
});
|
|
214
214
|
|
|
215
|
+
test("adoptStrandedMilestone forces branch recovery even when normal preferences differ", (t) => {
|
|
216
|
+
const previousCwd = process.cwd();
|
|
217
|
+
const base = makeGitRepoBase({ isolation: "worktree" });
|
|
218
|
+
t.after(() => cleanupRepoBase(base, previousCwd));
|
|
219
|
+
|
|
220
|
+
const s = makeSession({ basePath: base, originalBasePath: base });
|
|
221
|
+
const deps = makeDeps();
|
|
222
|
+
const ctx = makeCtx();
|
|
223
|
+
const lifecycle = new WorktreeLifecycle(s, deps);
|
|
224
|
+
|
|
225
|
+
const result = lifecycle.adoptStrandedMilestone("M001", base, ctx, {
|
|
226
|
+
mode: "branch",
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
assert.equal(result.ok, true, `expected ok:true, got: ${JSON.stringify(result)}`);
|
|
230
|
+
if (result.ok) {
|
|
231
|
+
assert.equal(result.mode, "branch");
|
|
232
|
+
assert.equal(result.path, base);
|
|
233
|
+
}
|
|
234
|
+
assert.equal(s.basePath, base);
|
|
235
|
+
assert.equal(s.strandedRecoveryIsolationMode, "branch");
|
|
236
|
+
const currentBranch = execFileSync("git", ["branch", "--show-current"], {
|
|
237
|
+
cwd: base,
|
|
238
|
+
encoding: "utf-8",
|
|
239
|
+
}).trim();
|
|
240
|
+
assert.equal(currentBranch, "milestone/M001");
|
|
241
|
+
});
|
|
242
|
+
|
|
215
243
|
test("enterMilestone returns ok:false reason:isolation-degraded when session degraded", () => {
|
|
216
244
|
const s = makeSession({ isolationDegraded: true });
|
|
217
245
|
const deps = makeDeps({ getIsolationMode: () => "branch" });
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { test } from "node:test";
|
|
16
16
|
import assert from "node:assert/strict";
|
|
17
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
17
|
+
import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { tmpdir } from "node:os";
|
|
20
20
|
|
|
@@ -79,3 +79,47 @@ test("#2942: injected existsFn — milestones/ alone is enough", () => {
|
|
|
79
79
|
p === "/proj/.gsd" || p === "/proj/.gsd/milestones";
|
|
80
80
|
assert.equal(hasGsdBootstrapArtifacts("/proj/.gsd", existsFn), true);
|
|
81
81
|
});
|
|
82
|
+
|
|
83
|
+
test("bare /gsd routes zombie .gsd folders to project init before closeout/db checks", async (t) => {
|
|
84
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-zombie-bare-command-"));
|
|
85
|
+
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
86
|
+
mkdirSync(join(base, ".gsd", "runtime"), { recursive: true });
|
|
87
|
+
|
|
88
|
+
const previousCwd = process.cwd();
|
|
89
|
+
const previousGsdHome = process.env.GSD_HOME;
|
|
90
|
+
const previousProjectRoot = process.env.GSD_PROJECT_ROOT;
|
|
91
|
+
try {
|
|
92
|
+
process.chdir(base);
|
|
93
|
+
process.env.GSD_HOME = join(base, ".test-gsd-home");
|
|
94
|
+
delete process.env.GSD_PROJECT_ROOT;
|
|
95
|
+
|
|
96
|
+
const notifications: string[] = [];
|
|
97
|
+
const ctx = {
|
|
98
|
+
hasUI: false,
|
|
99
|
+
ui: {
|
|
100
|
+
notify: (content: unknown) => notifications.push(String(content)),
|
|
101
|
+
setStatus: () => {},
|
|
102
|
+
setWidget: () => {},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
const { handleAutoCommand } = await import("../commands/handlers/auto.ts");
|
|
106
|
+
|
|
107
|
+
await handleAutoCommand("", ctx as any, {} as any);
|
|
108
|
+
|
|
109
|
+
assert.ok(
|
|
110
|
+
notifications.some((message) => message.includes("/gsd init did not start")),
|
|
111
|
+
"bare /gsd should route unbootstrapped zombie folders to the init wizard",
|
|
112
|
+
);
|
|
113
|
+
assert.equal(
|
|
114
|
+
existsSync(join(base, ".gsd", "gsd.db")),
|
|
115
|
+
false,
|
|
116
|
+
"bare /gsd should not create the project DB before init has bootstrapped .gsd/",
|
|
117
|
+
);
|
|
118
|
+
} finally {
|
|
119
|
+
process.chdir(previousCwd);
|
|
120
|
+
if (previousGsdHome === undefined) delete process.env.GSD_HOME;
|
|
121
|
+
else process.env.GSD_HOME = previousGsdHome;
|
|
122
|
+
if (previousProjectRoot === undefined) delete process.env.GSD_PROJECT_ROOT;
|
|
123
|
+
else process.env.GSD_PROJECT_ROOT = previousProjectRoot;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
@@ -173,6 +173,15 @@ export async function handleCompleteTask(
|
|
|
173
173
|
if (!params.milestoneId || typeof params.milestoneId !== "string" || params.milestoneId.trim() === "") {
|
|
174
174
|
return { error: "milestoneId is required and must be a non-empty string" };
|
|
175
175
|
}
|
|
176
|
+
if (!params.oneLiner || typeof params.oneLiner !== "string" || params.oneLiner.trim() === "") {
|
|
177
|
+
return { error: "oneLiner is required and must be a non-empty string" };
|
|
178
|
+
}
|
|
179
|
+
if (!params.narrative || typeof params.narrative !== "string" || params.narrative.trim() === "") {
|
|
180
|
+
return { error: "narrative is required and must be a non-empty string" };
|
|
181
|
+
}
|
|
182
|
+
if (!params.verification || typeof params.verification !== "string" || params.verification.trim() === "") {
|
|
183
|
+
return { error: "verification is required and must be a non-empty string" };
|
|
184
|
+
}
|
|
176
185
|
|
|
177
186
|
const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, params.milestoneId);
|
|
178
187
|
|
|
@@ -15,8 +15,10 @@ import {
|
|
|
15
15
|
} from "../gsd-db.js";
|
|
16
16
|
import { GATE_REGISTRY } from "../gate-registry.js";
|
|
17
17
|
import { generateRequirementsMd, saveArtifactToDb } from "../db-writer.js";
|
|
18
|
-
import { resolveMilestoneFile, resolveSliceFile } from "../paths.js";
|
|
18
|
+
import { clearPathCache, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
|
|
19
|
+
import { saveFile, clearParseCache } from "../files.js";
|
|
19
20
|
import { unlinkSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
20
22
|
import type { CompleteMilestoneParams } from "./complete-milestone.js";
|
|
21
23
|
import { handleCompleteMilestone } from "./complete-milestone.js";
|
|
22
24
|
import { handleCompleteTask } from "./complete-task.js";
|
|
@@ -96,6 +98,28 @@ function registerProjectMilestoneSequence(content: string): string[] {
|
|
|
96
98
|
return registered;
|
|
97
99
|
}
|
|
98
100
|
|
|
101
|
+
async function mirrorArtifactToActiveWorktreeProjection(
|
|
102
|
+
basePath: string,
|
|
103
|
+
relativePath: string,
|
|
104
|
+
content: string,
|
|
105
|
+
): Promise<void> {
|
|
106
|
+
const contract = resolveGsdPathContract(basePath);
|
|
107
|
+
if (!contract.worktreeGsd) return;
|
|
108
|
+
if (contract.worktreeGsd === contract.projectGsd) return;
|
|
109
|
+
|
|
110
|
+
const fullPath = join(contract.worktreeGsd, relativePath);
|
|
111
|
+
try {
|
|
112
|
+
await saveFile(fullPath, content);
|
|
113
|
+
clearPathCache();
|
|
114
|
+
clearParseCache();
|
|
115
|
+
invalidateStateCache();
|
|
116
|
+
} catch (err) {
|
|
117
|
+
logWarning("tool", `gsd_summary_save worktree projection mirror failed: ${(err as Error).message}`, {
|
|
118
|
+
path: relativePath,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
99
123
|
export async function executeSummarySave(
|
|
100
124
|
params: SummarySaveParams,
|
|
101
125
|
basePath: string = process.cwd(),
|
|
@@ -197,6 +221,7 @@ export async function executeSummarySave(
|
|
|
197
221
|
},
|
|
198
222
|
basePath,
|
|
199
223
|
);
|
|
224
|
+
await mirrorArtifactToActiveWorktreeProjection(basePath, relativePath, contentToSave);
|
|
200
225
|
|
|
201
226
|
let registeredMilestones: string[] = [];
|
|
202
227
|
if (params.artifact_type === "PROJECT") {
|
|
@@ -306,7 +331,7 @@ export interface TaskCompleteParams {
|
|
|
306
331
|
milestoneId: string;
|
|
307
332
|
oneLiner: string;
|
|
308
333
|
narrative: string;
|
|
309
|
-
verification
|
|
334
|
+
verification?: string;
|
|
310
335
|
deviations?: string;
|
|
311
336
|
knownIssues?: string;
|
|
312
337
|
keyFiles?: string[];
|
|
@@ -315,6 +340,40 @@ export interface TaskCompleteParams {
|
|
|
315
340
|
verificationEvidence?: VerificationEvidenceInput[];
|
|
316
341
|
}
|
|
317
342
|
|
|
343
|
+
type NormalizedVerificationEvidence = {
|
|
344
|
+
command: string;
|
|
345
|
+
exitCode: number;
|
|
346
|
+
verdict: string;
|
|
347
|
+
durationMs: number;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
function normalizeVerificationEvidence(
|
|
351
|
+
evidence: VerificationEvidenceInput[] | undefined,
|
|
352
|
+
): NormalizedVerificationEvidence[] {
|
|
353
|
+
return (evidence ?? []).map((entry) =>
|
|
354
|
+
typeof entry === "string"
|
|
355
|
+
? { command: entry, exitCode: -1, verdict: "unknown (coerced from string)", durationMs: 0 }
|
|
356
|
+
: entry,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function deriveVerificationSummary(
|
|
361
|
+
evidence: NormalizedVerificationEvidence[],
|
|
362
|
+
): string | null {
|
|
363
|
+
if (evidence.length === 0) return null;
|
|
364
|
+
|
|
365
|
+
const rendered = evidence.slice(0, 3).map((entry) => {
|
|
366
|
+
const command = entry.command.trim() || "(unspecified command)";
|
|
367
|
+
const verdict = entry.verdict.trim() || "recorded";
|
|
368
|
+
return `\`${command}\` exited ${entry.exitCode} (${verdict})`;
|
|
369
|
+
});
|
|
370
|
+
const suffix = evidence.length > rendered.length
|
|
371
|
+
? `; ${evidence.length - rendered.length} more check(s) recorded`
|
|
372
|
+
: "";
|
|
373
|
+
|
|
374
|
+
return `Verification evidence recorded: ${rendered.join("; ")}${suffix}.`;
|
|
375
|
+
}
|
|
376
|
+
|
|
318
377
|
export type CompleteMilestoneExecutorParams = Partial<CompleteMilestoneParams> & Record<string, unknown>;
|
|
319
378
|
export type SliceCompleteExecutorParams = CompleteSliceParams;
|
|
320
379
|
export type PlanMilestoneExecutorParams = PlanMilestoneParams;
|
|
@@ -350,9 +409,27 @@ export async function executeTaskComplete(
|
|
|
350
409
|
}
|
|
351
410
|
try {
|
|
352
411
|
const coerced = { ...params };
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
412
|
+
const verificationEvidence = normalizeVerificationEvidence(params.verificationEvidence);
|
|
413
|
+
coerced.verificationEvidence = verificationEvidence;
|
|
414
|
+
|
|
415
|
+
const verification = typeof params.verification === "string" ? params.verification.trim() : "";
|
|
416
|
+
if (verification.length === 0) {
|
|
417
|
+
const derived = deriveVerificationSummary(verificationEvidence);
|
|
418
|
+
if (derived) {
|
|
419
|
+
coerced.verification = derived;
|
|
420
|
+
} else if (params.blockerDiscovered === true) {
|
|
421
|
+
coerced.verification = "Not run: blocker discovered before verification.";
|
|
422
|
+
} else {
|
|
423
|
+
return {
|
|
424
|
+
content: [{
|
|
425
|
+
type: "text",
|
|
426
|
+
text: "Error completing task: verification is required unless verificationEvidence is provided or blockerDiscovered is true.",
|
|
427
|
+
}],
|
|
428
|
+
details: { operation: "complete_task", error: "verification_required" },
|
|
429
|
+
isError: true,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
}
|
|
356
433
|
|
|
357
434
|
const result = await handleCompleteTask(coerced as any, basePath);
|
|
358
435
|
if ("error" in result) {
|
|
@@ -151,3 +151,85 @@ export function renderFrame(
|
|
|
151
151
|
lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
|
|
152
152
|
return lines.map((line) => safeLine(line, width, ""));
|
|
153
153
|
}
|
|
154
|
+
|
|
155
|
+
export interface DialogFrameOptions {
|
|
156
|
+
borderColor?: string;
|
|
157
|
+
paddingX?: number;
|
|
158
|
+
footer?: string | string[];
|
|
159
|
+
scroll?: {
|
|
160
|
+
offset: number;
|
|
161
|
+
visibleRows: number;
|
|
162
|
+
totalRows: number;
|
|
163
|
+
trackOffset?: number;
|
|
164
|
+
trackRows?: number;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function renderTitledTopBorder(
|
|
169
|
+
theme: ThemeLike,
|
|
170
|
+
title: string,
|
|
171
|
+
width: number,
|
|
172
|
+
border: (text: string) => string,
|
|
173
|
+
): string {
|
|
174
|
+
const trimmedTitle = title.trim();
|
|
175
|
+
if (!trimmedTitle || width < 10) {
|
|
176
|
+
return border("╭" + "─".repeat(width - 2) + "╮");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const maxTitleWidth = Math.max(0, width - 7);
|
|
180
|
+
const safeTitle = safeLine(trimmedTitle, maxTitleWidth);
|
|
181
|
+
const fill = Math.max(0, width - visibleWidth(safeTitle) - 5);
|
|
182
|
+
return border("╭─ ") + theme.bold(theme.fg("accent", safeTitle)) + border(" " + "─".repeat(fill) + "╮");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function renderDialogFrame(
|
|
186
|
+
theme: ThemeLike,
|
|
187
|
+
title: string,
|
|
188
|
+
inner: string[],
|
|
189
|
+
width: number,
|
|
190
|
+
options: DialogFrameOptions = {},
|
|
191
|
+
): string[] {
|
|
192
|
+
if (width < 4) return inner.map((line) => safeLine(line, width));
|
|
193
|
+
|
|
194
|
+
const borderColor = options.borderColor ?? "borderAccent";
|
|
195
|
+
const paddingX = Math.max(0, options.paddingX ?? 1);
|
|
196
|
+
const contentWidth = Math.max(0, width - 2 - paddingX * 2);
|
|
197
|
+
const border = (text: string) => theme.fg(borderColor, text);
|
|
198
|
+
const pad = " ".repeat(paddingX);
|
|
199
|
+
const lines = [renderTitledTopBorder(theme, title, width, border)];
|
|
200
|
+
|
|
201
|
+
const scroll = options.scroll;
|
|
202
|
+
const bodyRows = inner.length;
|
|
203
|
+
const trackOffset = Math.max(0, Math.min(scroll?.trackOffset ?? 0, bodyRows));
|
|
204
|
+
const trackRows = Math.max(0, Math.min(scroll?.trackRows ?? bodyRows, bodyRows - trackOffset));
|
|
205
|
+
const scrollable = !!scroll && scroll.totalRows > scroll.visibleRows && trackRows > 0;
|
|
206
|
+
const thumbLen = scrollable
|
|
207
|
+
? Math.max(1, Math.round((scroll.visibleRows / scroll.totalRows) * trackRows))
|
|
208
|
+
: 0;
|
|
209
|
+
const maxThumbStart = Math.max(0, trackRows - thumbLen);
|
|
210
|
+
const maxScrollOffset = scrollable ? Math.max(1, scroll.totalRows - scroll.visibleRows) : 1;
|
|
211
|
+
const thumbStart = scrollable
|
|
212
|
+
? trackOffset + Math.min(maxThumbStart, Math.round((scroll.offset / maxScrollOffset) * maxThumbStart))
|
|
213
|
+
: -1;
|
|
214
|
+
|
|
215
|
+
for (let i = 0; i < inner.length; i++) {
|
|
216
|
+
const line = inner[i] ?? "";
|
|
217
|
+
const rightBorder = scrollable && i >= thumbStart && i < thumbStart + thumbLen ? "┃" : "│";
|
|
218
|
+
lines.push(border("│") + pad + padRightVisible(line, contentWidth) + pad + border(rightBorder));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const footer = Array.isArray(options.footer)
|
|
222
|
+
? options.footer
|
|
223
|
+
: options.footer
|
|
224
|
+
? [options.footer]
|
|
225
|
+
: [];
|
|
226
|
+
if (footer.length > 0) {
|
|
227
|
+
lines.push(border("├" + "─".repeat(width - 2) + "┤"));
|
|
228
|
+
for (const line of footer) {
|
|
229
|
+
lines.push(border("│") + pad + padRightVisible(line, contentWidth) + pad + border("│"));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
lines.push(border("╰" + "─".repeat(width - 2) + "╯"));
|
|
234
|
+
return lines.map((line) => safeLine(line, width, ""));
|
|
235
|
+
}
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
//
|
|
14
14
|
// Phased rollout tracking:
|
|
15
15
|
// - Phase 1 (this PR): schema + manifests + coverage test.
|
|
16
|
+
// - Phase 1b (skill token savings): skills policy wired via skill-scope.ts
|
|
17
|
+
// and setVisibleSkills(); allowlists derived from skill-manifest.ts.
|
|
16
18
|
// - Phase 2: add composeSystemPromptForUnit(); migrate one low-risk
|
|
17
19
|
// unit type (e.g. reassess-roadmap) as the pilot.
|
|
18
20
|
// - Phase 3: migrate remaining unit types, tighten manifests per
|
|
@@ -277,11 +279,20 @@ export interface UnitContextManifest {
|
|
|
277
279
|
|
|
278
280
|
// ─── Manifests ────────────────────────────────────────────────────────────
|
|
279
281
|
|
|
280
|
-
// Phase 1 policy:
|
|
281
|
-
//
|
|
282
|
-
//
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
// Phase 1 policy: skills policy is derived from skill-manifest.ts allowlists
|
|
283
|
+
// via `skillPolicyForUnit()`; units without an allowlist keep mode "all".
|
|
284
|
+
// Explicit mode "none" remains for lightweight config units.
|
|
285
|
+
|
|
286
|
+
import { resolveSkillManifest } from "./skill-manifest.js";
|
|
287
|
+
|
|
288
|
+
/** Derive skills policy from skill-manifest allowlists; default to full catalog. */
|
|
289
|
+
function skillPolicyForUnit(unitType: string): SkillsPolicy {
|
|
290
|
+
const allowlist = resolveSkillManifest(unitType);
|
|
291
|
+
if (allowlist) {
|
|
292
|
+
return { mode: "allowlist", skills: allowlist };
|
|
293
|
+
}
|
|
294
|
+
return { mode: "all" };
|
|
295
|
+
}
|
|
285
296
|
|
|
286
297
|
const COMMON_BUDGET_LARGE = 1_500_000; // ~400K tokens
|
|
287
298
|
const COMMON_BUDGET_MEDIUM = 750_000; // ~200K tokens
|
|
@@ -360,7 +371,7 @@ export type UnitType = typeof KNOWN_UNIT_TYPES[number];
|
|
|
360
371
|
export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
361
372
|
// ─── Milestone-scoped ────────────────────────────────────────────────
|
|
362
373
|
"research-milestone": {
|
|
363
|
-
skills:
|
|
374
|
+
skills: skillPolicyForUnit("research-milestone"),
|
|
364
375
|
knowledge: "full",
|
|
365
376
|
memory: "prompt-relevant",
|
|
366
377
|
codebaseMap: true,
|
|
@@ -377,7 +388,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
377
388
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
378
389
|
},
|
|
379
390
|
"plan-milestone": {
|
|
380
|
-
skills:
|
|
391
|
+
skills: skillPolicyForUnit("plan-milestone"),
|
|
381
392
|
knowledge: "full",
|
|
382
393
|
memory: "prompt-relevant",
|
|
383
394
|
codebaseMap: true,
|
|
@@ -392,7 +403,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
392
403
|
maxSystemPromptChars: COMMON_BUDGET_LARGE,
|
|
393
404
|
},
|
|
394
405
|
"discuss-milestone": {
|
|
395
|
-
skills:
|
|
406
|
+
skills: skillPolicyForUnit("discuss-milestone"),
|
|
396
407
|
knowledge: "full",
|
|
397
408
|
memory: "prompt-relevant",
|
|
398
409
|
codebaseMap: true,
|
|
@@ -407,7 +418,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
407
418
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
408
419
|
},
|
|
409
420
|
"validate-milestone": {
|
|
410
|
-
skills:
|
|
421
|
+
skills: skillPolicyForUnit("validate-milestone"),
|
|
411
422
|
knowledge: "scoped",
|
|
412
423
|
memory: "prompt-relevant",
|
|
413
424
|
codebaseMap: false,
|
|
@@ -424,7 +435,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
424
435
|
maxSystemPromptChars: COMMON_BUDGET_LARGE,
|
|
425
436
|
},
|
|
426
437
|
"complete-milestone": {
|
|
427
|
-
skills:
|
|
438
|
+
skills: skillPolicyForUnit("complete-milestone"),
|
|
428
439
|
knowledge: "scoped",
|
|
429
440
|
memory: "prompt-relevant",
|
|
430
441
|
codebaseMap: false,
|
|
@@ -446,7 +457,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
446
457
|
|
|
447
458
|
// ─── Slice-scoped ────────────────────────────────────────────────────
|
|
448
459
|
"research-slice": {
|
|
449
|
-
skills:
|
|
460
|
+
skills: skillPolicyForUnit("research-slice"),
|
|
450
461
|
knowledge: "full",
|
|
451
462
|
memory: "prompt-relevant",
|
|
452
463
|
codebaseMap: true,
|
|
@@ -463,7 +474,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
463
474
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
464
475
|
},
|
|
465
476
|
"plan-slice": {
|
|
466
|
-
skills:
|
|
477
|
+
skills: skillPolicyForUnit("plan-slice"),
|
|
467
478
|
knowledge: "full",
|
|
468
479
|
memory: "prompt-relevant",
|
|
469
480
|
codebaseMap: true,
|
|
@@ -481,7 +492,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
481
492
|
maxSystemPromptChars: COMMON_BUDGET_LARGE,
|
|
482
493
|
},
|
|
483
494
|
"refine-slice": {
|
|
484
|
-
skills:
|
|
495
|
+
skills: skillPolicyForUnit("refine-slice"),
|
|
485
496
|
knowledge: "scoped",
|
|
486
497
|
memory: "prompt-relevant",
|
|
487
498
|
codebaseMap: true,
|
|
@@ -499,7 +510,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
499
510
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
500
511
|
},
|
|
501
512
|
"replan-slice": {
|
|
502
|
-
skills:
|
|
513
|
+
skills: skillPolicyForUnit("replan-slice"),
|
|
503
514
|
knowledge: "scoped",
|
|
504
515
|
memory: "prompt-relevant",
|
|
505
516
|
codebaseMap: true,
|
|
@@ -514,7 +525,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
514
525
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
515
526
|
},
|
|
516
527
|
"complete-slice": {
|
|
517
|
-
skills:
|
|
528
|
+
skills: skillPolicyForUnit("complete-slice"),
|
|
518
529
|
knowledge: "scoped",
|
|
519
530
|
memory: "prompt-relevant",
|
|
520
531
|
codebaseMap: false,
|
|
@@ -535,7 +546,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
535
546
|
maxSystemPromptChars: COMMON_BUDGET_LARGE,
|
|
536
547
|
},
|
|
537
548
|
"reassess-roadmap": {
|
|
538
|
-
skills:
|
|
549
|
+
skills: skillPolicyForUnit("reassess-roadmap"),
|
|
539
550
|
knowledge: "scoped",
|
|
540
551
|
memory: "critical-only",
|
|
541
552
|
codebaseMap: false,
|
|
@@ -552,7 +563,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
552
563
|
|
|
553
564
|
// ─── Task-scoped ─────────────────────────────────────────────────────
|
|
554
565
|
"execute-task": {
|
|
555
|
-
skills:
|
|
566
|
+
skills: skillPolicyForUnit("execute-task"),
|
|
556
567
|
knowledge: "scoped",
|
|
557
568
|
memory: "prompt-relevant",
|
|
558
569
|
codebaseMap: true,
|
|
@@ -567,7 +578,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
567
578
|
maxSystemPromptChars: COMMON_BUDGET_LARGE,
|
|
568
579
|
},
|
|
569
580
|
"reactive-execute": {
|
|
570
|
-
skills:
|
|
581
|
+
skills: skillPolicyForUnit("reactive-execute"),
|
|
571
582
|
knowledge: "scoped",
|
|
572
583
|
memory: "prompt-relevant",
|
|
573
584
|
codebaseMap: true,
|
|
@@ -584,7 +595,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
584
595
|
|
|
585
596
|
// ─── Ancillary units ─────────────────────────────────────────────────
|
|
586
597
|
"run-uat": {
|
|
587
|
-
skills:
|
|
598
|
+
skills: skillPolicyForUnit("run-uat"),
|
|
588
599
|
knowledge: "critical-only",
|
|
589
600
|
memory: "critical-only",
|
|
590
601
|
codebaseMap: false,
|
|
@@ -599,7 +610,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
599
610
|
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
|
600
611
|
},
|
|
601
612
|
"gate-evaluate": {
|
|
602
|
-
skills:
|
|
613
|
+
skills: skillPolicyForUnit("gate-evaluate"),
|
|
603
614
|
knowledge: "critical-only",
|
|
604
615
|
memory: "critical-only",
|
|
605
616
|
codebaseMap: false,
|
|
@@ -616,7 +627,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
616
627
|
maxSystemPromptChars: COMMON_BUDGET_SMALL,
|
|
617
628
|
},
|
|
618
629
|
"rewrite-docs": {
|
|
619
|
-
skills:
|
|
630
|
+
skills: skillPolicyForUnit("rewrite-docs"),
|
|
620
631
|
knowledge: "scoped",
|
|
621
632
|
memory: "prompt-relevant",
|
|
622
633
|
codebaseMap: true,
|
|
@@ -631,7 +642,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
631
642
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
632
643
|
},
|
|
633
644
|
"triage-captures": {
|
|
634
|
-
skills:
|
|
645
|
+
skills: skillPolicyForUnit("triage-captures"),
|
|
635
646
|
knowledge: "scoped",
|
|
636
647
|
memory: "prompt-relevant",
|
|
637
648
|
codebaseMap: false,
|
|
@@ -646,7 +657,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
646
657
|
maxSystemPromptChars: COMMON_BUDGET_MEDIUM,
|
|
647
658
|
},
|
|
648
659
|
"quick-task": {
|
|
649
|
-
skills:
|
|
660
|
+
skills: skillPolicyForUnit("quick-task"),
|
|
650
661
|
knowledge: "full",
|
|
651
662
|
memory: "prompt-relevant",
|
|
652
663
|
codebaseMap: true,
|
|
@@ -684,7 +695,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
684
695
|
// discussion runs before any milestone exists, so milestone artifacts are
|
|
685
696
|
// not loaded. Keeps templates available for PROJECT.md scaffolding.
|
|
686
697
|
"discuss-project": {
|
|
687
|
-
skills:
|
|
698
|
+
skills: skillPolicyForUnit("discuss-project"),
|
|
688
699
|
knowledge: "scoped",
|
|
689
700
|
memory: "prompt-relevant",
|
|
690
701
|
codebaseMap: true,
|
|
@@ -701,7 +712,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
701
712
|
// discuss-requirements: REQUIREMENTS.md interview. PROJECT.md is the
|
|
702
713
|
// primary context input; templates carry the requirements format.
|
|
703
714
|
"discuss-requirements": {
|
|
704
|
-
skills:
|
|
715
|
+
skills: skillPolicyForUnit("discuss-requirements"),
|
|
705
716
|
knowledge: "scoped",
|
|
706
717
|
memory: "prompt-relevant",
|
|
707
718
|
codebaseMap: true,
|
|
@@ -737,7 +748,7 @@ export const UNIT_MANIFESTS: Record<UnitType, UnitContextManifest> = {
|
|
|
737
748
|
// planning-dispatch policy to dispatch them. PROJECT.md + REQUIREMENTS.md
|
|
738
749
|
// give the orchestrator the framing context.
|
|
739
750
|
"research-project": {
|
|
740
|
-
skills:
|
|
751
|
+
skills: skillPolicyForUnit("research-project"),
|
|
741
752
|
knowledge: "scoped",
|
|
742
753
|
memory: "prompt-relevant",
|
|
743
754
|
codebaseMap: true,
|