@opengsd/gsd-pi 1.0.2-dev.e9a1b49 → 1.0.2-dev.fb7ddf1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -12
- package/dist/headless-answers.js +2 -1
- package/dist/headless-events.d.ts +1 -0
- package/dist/headless-events.js +8 -1
- package/dist/onboarding.js +22 -3
- package/dist/resource-loader.d.ts +7 -0
- package/dist/resource-loader.js +44 -9
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +34 -11
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +81 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +38 -1
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +65 -16
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -1
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +36 -55
- package/dist/resources/extensions/gsd/auto.js +40 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -27
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/bootstrap/tool-search-shim.js +4 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +1 -1
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +3 -0
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-git-checks.js +70 -5
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +7 -2
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/mcp-filter.js +57 -18
- package/dist/resources/extensions/gsd/mcp-project-config.js +15 -9
- package/dist/resources/extensions/gsd/migration-auto-check.js +5 -1
- package/dist/resources/extensions/gsd/milestone-actions.js +3 -0
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-merge.js +6 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/post-execution-checks.js +5 -4
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +3 -20
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repo-identity.js +36 -6
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +13 -6
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/gsd/worktree-post-create-hook.js +117 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +29 -0
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/extensions/subagent/index.js +8 -15
- package/dist/resources/shared/package-manager-detection.js +36 -0
- package/dist/resources/skills/agent-browser/SKILL.md +1 -1
- package/dist/resources/skills/api-design/SKILL.md +1 -1
- package/dist/resources/skills/code-optimizer/SKILL.md +6 -11
- package/dist/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/dist/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/dist/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/dist/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/dist/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/dist/resources/skills/forensics/SKILL.md +2 -2
- package/dist/resources/skills/grill-me/SKILL.md +1 -1
- package/dist/resources/skills/handoff/SKILL.md +1 -1
- package/dist/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/dist/resources/skills/observability/SKILL.md +1 -1
- package/dist/resources/skills/security-review/SKILL.md +1 -1
- package/dist/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/dist/resources/skills/tdd/SKILL.md +1 -1
- package/dist/resources/skills/write-docs/SKILL.md +1 -1
- package/dist/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +7 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/worktree-cli.d.ts +0 -2
- package/dist/worktree-cli.js +21 -9
- package/package.json +5 -2
- package/packages/cloud-mcp-gateway/bin/gsd-cloud-mcp-gateway.js +14 -0
- package/packages/cloud-mcp-gateway/package.json +4 -3
- package/packages/contracts/dist/rpc.test.js +5 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/dist/workflow.d.ts +15 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/dist/workflow.test.js +1 -0
- package/packages/contracts/dist/workflow.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode-class-constants.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +2 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/bin/gsd-mcp-server.js +14 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +7 -1
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +13 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +47 -8
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +16 -14
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/bin/pi-ai.js +14 -0
- package/packages/pi-ai/dist/models.generated.d.ts +48 -206
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +73 -226
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js +29 -1
- package/packages/pi-ai/dist/utils/tests/tool-search-shim.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts +4 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-search-shim.js +58 -10
- package/packages/pi-ai/dist/utils/tool-search-shim.js.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/tool-shims.js.map +1 -1
- package/packages/pi-ai/package.json +3 -2
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +5 -7
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +5 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +0 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/package.json +8 -8
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/scripts/install/deps.js +10 -0
- package/scripts/install/detect-existing.js +17 -3
- package/scripts/install/npm-global.js +103 -33
- package/scripts/install.js +1 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +36 -11
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +86 -19
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +96 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +47 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +101 -18
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +3 -1
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +47 -57
- package/src/resources/extensions/gsd/auto.ts +50 -2
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +124 -25
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/bootstrap/tool-search-shim.ts +4 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1 -1
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +2 -0
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +72 -5
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +7 -2
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/mcp-filter.ts +64 -17
- package/src/resources/extensions/gsd/mcp-project-config.ts +24 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +6 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -0
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-merge.ts +6 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/post-execution-checks.ts +7 -4
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +3 -20
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repo-identity.ts +35 -7
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +13 -6
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +1 -1
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-untracked-content.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/complete-slice-reopen-handoff.test.ts +40 -3
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +22 -3
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +19 -1
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +56 -1
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +127 -10
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +67 -1
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +141 -1
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/gsd/worktree-post-create-hook.ts +127 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +33 -0
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/extensions/subagent/index.ts +8 -15
- package/src/resources/shared/package-manager-detection.ts +39 -0
- package/src/resources/skills/agent-browser/SKILL.md +1 -1
- package/src/resources/skills/api-design/SKILL.md +1 -1
- package/src/resources/skills/code-optimizer/SKILL.md +6 -11
- package/src/resources/skills/create-gsd-extension/SKILL.md +1 -1
- package/src/resources/skills/create-mcp-server/SKILL.md +1 -1
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/src/resources/skills/create-skill/workflows/verify-skill.md +2 -10
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +1 -5
- package/src/resources/skills/decompose-into-slices/SKILL.md +3 -3
- package/src/resources/skills/dependency-upgrade/SKILL.md +1 -1
- package/src/resources/skills/forensics/SKILL.md +2 -2
- package/src/resources/skills/grill-me/SKILL.md +1 -1
- package/src/resources/skills/handoff/SKILL.md +1 -1
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +1 -1
- package/src/resources/skills/observability/SKILL.md +1 -1
- package/src/resources/skills/security-review/SKILL.md +1 -1
- package/src/resources/skills/spike-wrap-up/SKILL.md +1 -1
- package/src/resources/skills/tdd/SKILL.md +1 -1
- package/src/resources/skills/write-docs/SKILL.md +1 -1
- package/src/resources/skills/write-milestone-brief/SKILL.md +1 -1
- package/dist/tsconfig.extensions.tsbuildinfo +0 -1
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BEjZM0MLHLibeMFbjtMol → tH1tnDYt1E0hK9Ien73Z0}/_ssgManifest.js +0 -0
|
@@ -94,6 +94,7 @@ import { resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
|
94
94
|
import { probeGitConflictState } from "./git-conflict-state.js";
|
|
95
95
|
import { runTurnGitAction } from "./git-service.js";
|
|
96
96
|
import { parseUnitId } from "./unit-id.js";
|
|
97
|
+
import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
|
|
97
98
|
|
|
98
99
|
// ─── Types ────────────────────────────────────────────────────────────────
|
|
99
100
|
|
|
@@ -132,6 +133,15 @@ export interface DispatchContext {
|
|
|
132
133
|
sessionProvider?: string;
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
function resolveExistingExpectedArtifact(
|
|
137
|
+
unitType: string,
|
|
138
|
+
unitId: string,
|
|
139
|
+
basePath: string,
|
|
140
|
+
): string | null {
|
|
141
|
+
const artifactPath = resolveExpectedArtifactPath(unitType, unitId, basePath);
|
|
142
|
+
return artifactPath && existsSync(artifactPath) ? artifactPath : null;
|
|
143
|
+
}
|
|
144
|
+
|
|
135
145
|
type ReassessmentChecker = typeof checkNeedsReassessment;
|
|
136
146
|
type ResearchProjectPromptBuilder = typeof buildResearchProjectPrompt;
|
|
137
147
|
|
|
@@ -971,13 +981,17 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
971
981
|
if (await getMilestonePipelineVariant(mid) === "trivial") return null;
|
|
972
982
|
|
|
973
983
|
// Load roadmap to find all slices
|
|
974
|
-
const roadmapFile =
|
|
984
|
+
const roadmapFile =
|
|
985
|
+
resolveExistingExpectedArtifact("plan-milestone", mid, basePath) ??
|
|
986
|
+
resolveMilestoneFile(basePath, mid, "ROADMAP");
|
|
975
987
|
const roadmapContent = roadmapFile ? await loadFile(roadmapFile) : null;
|
|
976
988
|
if (!roadmapContent) return null;
|
|
977
989
|
const roadmap = parseRoadmap(roadmapContent);
|
|
978
990
|
|
|
979
991
|
// Find slices that need research (no RESEARCH file, dependencies done)
|
|
980
|
-
const milestoneResearchFile =
|
|
992
|
+
const milestoneResearchFile =
|
|
993
|
+
resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
|
|
994
|
+
resolveMilestoneFile(basePath, mid, "RESEARCH");
|
|
981
995
|
const researchReadySlices: Array<{ id: string; title: string }> = [];
|
|
982
996
|
|
|
983
997
|
for (const slice of roadmap.slices) {
|
|
@@ -985,10 +999,10 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
985
999
|
// Skip S01 when milestone research exists
|
|
986
1000
|
if (milestoneResearchFile && slice.id === "S01") continue;
|
|
987
1001
|
// Skip if already has research
|
|
988
|
-
if (
|
|
1002
|
+
if (resolveExistingExpectedArtifact("research-slice", `${mid}/${slice.id}`, basePath)) continue;
|
|
989
1003
|
// Skip if dependencies aren't done (check for SUMMARY files)
|
|
990
1004
|
const depsComplete = (slice.depends ?? []).every((depId) =>
|
|
991
|
-
!!
|
|
1005
|
+
!!resolveExistingExpectedArtifact("complete-slice", `${mid}/${depId}`, basePath),
|
|
992
1006
|
);
|
|
993
1007
|
if (!depsComplete) continue;
|
|
994
1008
|
|
|
@@ -1001,7 +1015,9 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1001
1015
|
// #4414: If a previous parallel-research attempt escalated to a blocker
|
|
1002
1016
|
// placeholder, skip this rule and fall through to per-slice research
|
|
1003
1017
|
// (or other rules) rather than re-dispatching the same failing unit.
|
|
1004
|
-
const parallelBlocker =
|
|
1018
|
+
const parallelBlocker =
|
|
1019
|
+
resolveExistingExpectedArtifact("research-slice", `${mid}/parallel-research`, basePath) ??
|
|
1020
|
+
resolveMilestoneFile(basePath, mid, "PARALLEL-BLOCKER");
|
|
1005
1021
|
if (parallelBlocker) return null;
|
|
1006
1022
|
|
|
1007
1023
|
return {
|
|
@@ -1030,15 +1046,19 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
1030
1046
|
if (!state.activeSlice) return missingSliceStop(mid, state.phase);
|
|
1031
1047
|
const sid = state.activeSlice!.id;
|
|
1032
1048
|
const sTitle = state.activeSlice!.title;
|
|
1033
|
-
const researchFile =
|
|
1049
|
+
const researchFile =
|
|
1050
|
+
resolveExistingExpectedArtifact("research-slice", `${mid}/${sid}`, basePath) ??
|
|
1051
|
+
resolveSliceFile(basePath, mid, sid, "RESEARCH");
|
|
1034
1052
|
if (researchFile) return null; // has research, fall through
|
|
1035
1053
|
// Skip slice research for S01 when milestone research already exists —
|
|
1036
1054
|
// the milestone research already covers the same ground for the first slice.
|
|
1037
|
-
const milestoneResearchFile =
|
|
1038
|
-
basePath
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1055
|
+
const milestoneResearchFile =
|
|
1056
|
+
resolveExistingExpectedArtifact("research-milestone", mid, basePath) ??
|
|
1057
|
+
resolveMilestoneFile(
|
|
1058
|
+
basePath,
|
|
1059
|
+
mid,
|
|
1060
|
+
"RESEARCH",
|
|
1061
|
+
);
|
|
1042
1062
|
if (milestoneResearchFile && sid === "S01") return null; // fall through to plan-slice
|
|
1043
1063
|
return {
|
|
1044
1064
|
action: "dispatch",
|
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
runMilestoneCloseoutGitHub,
|
|
69
69
|
} from "./milestone-closeout.js";
|
|
70
70
|
import type { AutoSession, SidecarItem } from "./auto/session.js";
|
|
71
|
-
import { getEvidence, clearEvidenceFromDisk } from "./safety/evidence-collector.js";
|
|
71
|
+
import { getEvidence, clearEvidenceFromDisk, isExecutionToolName } from "./safety/evidence-collector.js";
|
|
72
72
|
import { validateFileChanges } from "./safety/file-change-validator.js";
|
|
73
73
|
import { crossReferenceEvidence, type ClaimedEvidence } from "./safety/evidence-cross-ref.js";
|
|
74
74
|
import { validateContent } from "./safety/content-validator.js";
|
|
@@ -112,6 +112,27 @@ const MAX_VERIFICATION_RETRIES = 3;
|
|
|
112
112
|
const MAX_NOTIFICATION_DETAILS = 3;
|
|
113
113
|
const NOTIFICATION_BULLET = "•";
|
|
114
114
|
|
|
115
|
+
function isParallelResearchUnit(unitType: string, unitId: string): boolean {
|
|
116
|
+
return unitType === "research-slice" && unitId.endsWith("/parallel-research");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function maybeWriteParallelResearchCostSpikeBlocker(
|
|
120
|
+
unitType: string,
|
|
121
|
+
unitId: string,
|
|
122
|
+
basePath: string,
|
|
123
|
+
unitCostUsd: number,
|
|
124
|
+
rollingAvgUsd: number,
|
|
125
|
+
): string | null {
|
|
126
|
+
if (!isParallelResearchUnit(unitType, unitId)) return null;
|
|
127
|
+
return writeBlockerPlaceholder(
|
|
128
|
+
unitType,
|
|
129
|
+
unitId,
|
|
130
|
+
basePath,
|
|
131
|
+
`Parallel slice research cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}). ` +
|
|
132
|
+
"Skipping the aggregate sentinel so dispatch can fall back to per-slice research.",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
115
136
|
export function resolveCloseoutGitAction(
|
|
116
137
|
uokFlags: ReturnType<typeof resolveUokFlags>,
|
|
117
138
|
): TurnGitActionMode | null {
|
|
@@ -202,13 +223,45 @@ function completeSliceReopenReplanHandoffDetected(
|
|
|
202
223
|
agentEndMessagesIncludeToolCall(agentEndMessages, "gsd_task_reopen") ||
|
|
203
224
|
agentEndMessagesMentionTool(agentEndMessages, "gsd_task_reopen") ||
|
|
204
225
|
unitActivityMentionsTool(s.basePath, unitType, unitId, "gsd_task_reopen") ||
|
|
205
|
-
unitActivityMentionsTool(s.canonicalProjectRoot, unitType, unitId, "gsd_task_reopen")
|
|
226
|
+
unitActivityMentionsTool(s.canonicalProjectRoot, unitType, unitId, "gsd_task_reopen")
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function completeSliceReplanSignalDetected(
|
|
231
|
+
s: AutoSession,
|
|
232
|
+
agentEndMessages: unknown[] | undefined,
|
|
233
|
+
): boolean {
|
|
234
|
+
if (s.currentUnit?.type !== "complete-slice") return false;
|
|
235
|
+
return (
|
|
206
236
|
agentEndMessagesIncludeSuccessfulToolResult(agentEndMessages, "gsd_replan_slice") ||
|
|
207
237
|
agentEndMessagesIncludeToolCall(agentEndMessages, "gsd_replan_slice") ||
|
|
208
238
|
agentEndMessagesMentionTool(agentEndMessages, "gsd_replan_slice") ||
|
|
209
|
-
unitActivityMentionsTool(s.basePath,
|
|
210
|
-
unitActivityMentionsTool(s.canonicalProjectRoot,
|
|
239
|
+
unitActivityMentionsTool(s.basePath, s.currentUnit.type, s.currentUnit.id, "gsd_replan_slice") ||
|
|
240
|
+
unitActivityMentionsTool(s.canonicalProjectRoot, s.currentUnit.type, s.currentUnit.id, "gsd_replan_slice")
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function completeSliceValidReplanOutcomeDetected(
|
|
245
|
+
s: AutoSession,
|
|
246
|
+
agentEndMessages: unknown[] | undefined,
|
|
247
|
+
): boolean {
|
|
248
|
+
if (s.currentUnit?.type !== "complete-slice") return false;
|
|
249
|
+
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
250
|
+
if (!mid || !sid) return false;
|
|
251
|
+
|
|
252
|
+
if (!completeSliceReplanSignalDetected(s, agentEndMessages)) return false;
|
|
253
|
+
|
|
254
|
+
const replanPath = resolveSliceFile(s.basePath, mid, sid, "REPLAN");
|
|
255
|
+
const canonicalReplanPath = resolveSliceFile(s.canonicalProjectRoot, mid, sid, "REPLAN");
|
|
256
|
+
const hasReplanArtifact = (
|
|
257
|
+
Boolean(replanPath && existsSync(replanPath)) ||
|
|
258
|
+
Boolean(canonicalReplanPath && existsSync(canonicalReplanPath))
|
|
211
259
|
);
|
|
260
|
+
if (!hasReplanArtifact) return false;
|
|
261
|
+
|
|
262
|
+
if (!isDbAvailable()) return true;
|
|
263
|
+
const slice = getSlice(mid, sid);
|
|
264
|
+
return Boolean(slice && !isClosedStatus(slice.status));
|
|
212
265
|
}
|
|
213
266
|
|
|
214
267
|
function formatPreExecutionCheckDetail(check: PreExecutionCheckJSON): string {
|
|
@@ -469,12 +522,6 @@ export function _shouldDispatchQuickTaskForTest(
|
|
|
469
522
|
state.currentUnit.type !== "quick-task";
|
|
470
523
|
}
|
|
471
524
|
|
|
472
|
-
function isExecutionToolName(name: unknown): boolean {
|
|
473
|
-
if (typeof name !== "string") return false;
|
|
474
|
-
const normalized = name.trim().toLowerCase();
|
|
475
|
-
return normalized === "bash" || normalized === "gsd_exec";
|
|
476
|
-
}
|
|
477
|
-
|
|
478
525
|
export function _hasExecutionToolCallsInSessionForTest(entries: readonly unknown[]): boolean {
|
|
479
526
|
for (const entry of entries) {
|
|
480
527
|
const e = entry as any;
|
|
@@ -1449,11 +1496,11 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1449
1496
|
suppressedWarning: "evidence-empty-but-session-has-exec-calls",
|
|
1450
1497
|
});
|
|
1451
1498
|
} else {
|
|
1452
|
-
logWarning("safety", `evidence mismatch: ${missingCommandMismatches.length} claimed command(s) not found in
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1499
|
+
logWarning("safety", `evidence mismatch: ${missingCommandMismatches.length} claimed command(s) not found in recorded execution calls`);
|
|
1500
|
+
ctx.ui.notify(
|
|
1501
|
+
`Safety: task ${sTid} claimed ${missingCommandMismatches.length} command(s) not found in recorded execution calls`,
|
|
1502
|
+
"warning",
|
|
1503
|
+
);
|
|
1457
1504
|
}
|
|
1458
1505
|
}
|
|
1459
1506
|
|
|
@@ -1591,7 +1638,7 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1591
1638
|
if (!triggerArtifactVerified) {
|
|
1592
1639
|
try {
|
|
1593
1640
|
const { milestone: mid, slice: sid } = parseUnitId(s.currentUnit.id);
|
|
1594
|
-
if (mid && sid) {
|
|
1641
|
+
if (mid && sid && !isParallelResearchUnit(s.currentUnit.type, s.currentUnit.id)) {
|
|
1595
1642
|
// Phase C: write to the canonical project root (#5236 scope)
|
|
1596
1643
|
// so non-symlinked worktrees no longer maintain a separate
|
|
1597
1644
|
// local .gsd/ projection. copyPlanningArtifacts has been
|
|
@@ -1777,7 +1824,29 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1777
1824
|
"warning",
|
|
1778
1825
|
);
|
|
1779
1826
|
return "continue";
|
|
1780
|
-
} else if (
|
|
1827
|
+
} else if (
|
|
1828
|
+
!triggerArtifactVerified &&
|
|
1829
|
+
completeSliceValidReplanOutcomeDetected(s, opts?.agentEndMessages)
|
|
1830
|
+
) {
|
|
1831
|
+
const retryKey = `${s.currentUnit.type}:${s.currentUnit.id}`;
|
|
1832
|
+
s.pendingVerificationRetry = null;
|
|
1833
|
+
s.verificationRetryCount.delete(retryKey);
|
|
1834
|
+
s.verificationRetryFailureHashes.delete(retryKey);
|
|
1835
|
+
debugLog("postUnit", {
|
|
1836
|
+
phase: "artifact-verify-complete-slice-replan-outcome",
|
|
1837
|
+
unitType: s.currentUnit.type,
|
|
1838
|
+
unitId: s.currentUnit.id,
|
|
1839
|
+
});
|
|
1840
|
+
ctx.ui.notify(
|
|
1841
|
+
`complete-slice ${s.currentUnit.id} produced a valid replan outcome; continuing orchestration instead of retrying closeout.`,
|
|
1842
|
+
"warning",
|
|
1843
|
+
);
|
|
1844
|
+
return "continue";
|
|
1845
|
+
} else if (
|
|
1846
|
+
!triggerArtifactVerified &&
|
|
1847
|
+
!isDbAvailable() &&
|
|
1848
|
+
!completeSliceReplanSignalDetected(s, opts?.agentEndMessages)
|
|
1849
|
+
) {
|
|
1781
1850
|
debugLog("postUnit", { phase: "artifact-verify-skip-db-unavailable", unitType: s.currentUnit.type, unitId: s.currentUnit.id });
|
|
1782
1851
|
const dbSkipDiag = diagnoseExpectedArtifact(s.currentUnit.type, s.currentUnit.id, verificationBasePath);
|
|
1783
1852
|
ctx.ui.notify(
|
|
@@ -1860,8 +1929,17 @@ export async function postUnitPreVerification(pctx: PostUnitContext, opts?: PreV
|
|
|
1860
1929
|
);
|
|
1861
1930
|
return "continue";
|
|
1862
1931
|
}
|
|
1932
|
+
const parallelBlocker = maybeWriteParallelResearchCostSpikeBlocker(
|
|
1933
|
+
s.currentUnit.type,
|
|
1934
|
+
s.currentUnit.id,
|
|
1935
|
+
verificationBasePath,
|
|
1936
|
+
unitCostUsd,
|
|
1937
|
+
rollingAvgUsd,
|
|
1938
|
+
);
|
|
1863
1939
|
ctx.ui.notify(
|
|
1864
|
-
|
|
1940
|
+
parallelBlocker
|
|
1941
|
+
? `Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) — wrote parallel blocker and pausing auto-mode.`
|
|
1942
|
+
: `Unit ${s.currentUnit.id} cost spike detected (${unitCostUsd.toFixed(2)} vs avg ${rollingAvgUsd.toFixed(2)}) — pausing auto-mode.`,
|
|
1865
1943
|
"error",
|
|
1866
1944
|
);
|
|
1867
1945
|
await pauseAuto(ctx, pi);
|
|
@@ -2031,6 +2109,11 @@ export async function postUnitPostVerification(pctx: PostUnitContext): Promise<"
|
|
|
2031
2109
|
"info",
|
|
2032
2110
|
);
|
|
2033
2111
|
|
|
2112
|
+
await s.orchestration?.retryActiveUnit({
|
|
2113
|
+
unitType: trigger.unitType,
|
|
2114
|
+
unitId: trigger.unitId,
|
|
2115
|
+
});
|
|
2116
|
+
|
|
2034
2117
|
// ── State reset: undo the completion so deriveState re-derives the unit ──
|
|
2035
2118
|
try {
|
|
2036
2119
|
const { milestone: mid, slice: sid, task: tid } = parseUnitId(trigger.unitId);
|
|
@@ -19,12 +19,11 @@ import {
|
|
|
19
19
|
relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath,
|
|
20
20
|
resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
|
|
21
21
|
} from "./paths.js";
|
|
22
|
-
import {
|
|
22
|
+
import { resolveInlineLevel, loadEffectiveGSDPreferences } from "./preferences.js";
|
|
23
23
|
import { isContextModeEnabled } from "./preferences-types.js";
|
|
24
24
|
import { parseRoadmap } from "./parsers-legacy.js";
|
|
25
25
|
import type { GSDState, InlineLevel } from "./types.js";
|
|
26
26
|
import type { GSDPreferences } from "./preferences.js";
|
|
27
|
-
import { getLoadedSkills, type Skill } from "@gsd/pi-coding-agent";
|
|
28
27
|
import { join, basename } from "node:path";
|
|
29
28
|
import { existsSync } from "node:fs";
|
|
30
29
|
import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary, type MinimalModelRegistry } from "./context-budget.js";
|
|
@@ -42,10 +41,12 @@ import { readCompactionSnapshot } from "./compaction-snapshot.js";
|
|
|
42
41
|
import { logWarning } from "./workflow-logger.js";
|
|
43
42
|
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
44
43
|
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
45
|
-
import { resolveSkillManifest, warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
46
44
|
import { classifyProject, type ProjectClassification } from "./detection.js";
|
|
47
45
|
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
48
46
|
import { debugLog } from "./debug-logger.js";
|
|
47
|
+
import { buildSkillActivationBlock, buildSkillDiscoveryVars } from "./skill-activation.js";
|
|
48
|
+
|
|
49
|
+
export { buildSkillActivationBlock, buildSkillDiscoveryVars };
|
|
49
50
|
|
|
50
51
|
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
51
52
|
|
|
@@ -1172,287 +1173,6 @@ export async function inlineRoadmapExcerpt(
|
|
|
1172
1173
|
return `### Milestone Roadmap (excerpt)\nSource: \`${roadmapRel}\`\n\n${excerpt}`;
|
|
1173
1174
|
}
|
|
1174
1175
|
|
|
1175
|
-
// ─── Skill Activation & Discovery ─────────────────────────────────────────
|
|
1176
|
-
|
|
1177
|
-
function normalizeSkillReference(ref: string): string {
|
|
1178
|
-
const normalized = ref.replace(/\\/g, "/").trim();
|
|
1179
|
-
const base = basename(normalized).replace(/\.md$/i, "");
|
|
1180
|
-
const name = /^SKILL$/i.test(base)
|
|
1181
|
-
? basename(normalized.replace(/\/SKILL(?:\.md)?$/i, ""))
|
|
1182
|
-
: base;
|
|
1183
|
-
return name.trim().toLowerCase();
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
function tokenizeSkillContext(...parts: Array<string | null | undefined>): Set<string> {
|
|
1187
|
-
const tokens = new Set<string>();
|
|
1188
|
-
const addVariants = (raw: string) => {
|
|
1189
|
-
const value = raw.trim().toLowerCase();
|
|
1190
|
-
if (!value || value.length < 2) return;
|
|
1191
|
-
tokens.add(value);
|
|
1192
|
-
tokens.add(value.replace(/[-_]+/g, " "));
|
|
1193
|
-
tokens.add(value.replace(/\s+/g, "-"));
|
|
1194
|
-
tokens.add(value.replace(/\s+/g, ""));
|
|
1195
|
-
};
|
|
1196
|
-
|
|
1197
|
-
for (const part of parts) {
|
|
1198
|
-
if (!part) continue;
|
|
1199
|
-
const text = part.toLowerCase();
|
|
1200
|
-
const phraseMatches = text.match(/[a-z0-9][a-z0-9+.#/_-]{1,}/g) ?? [];
|
|
1201
|
-
for (const match of phraseMatches) {
|
|
1202
|
-
addVariants(match);
|
|
1203
|
-
for (const piece of match.split(/[^a-z0-9+.#]+/g)) {
|
|
1204
|
-
if (piece.length >= 3) addVariants(piece);
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
return tokens;
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
function skillMatchesContext(skill: Skill, contextTokens: Set<string>): boolean {
|
|
1213
|
-
const haystacks = [
|
|
1214
|
-
skill.name.toLowerCase(),
|
|
1215
|
-
skill.name.toLowerCase().replace(/[-_]+/g, " "),
|
|
1216
|
-
skill.description.toLowerCase(),
|
|
1217
|
-
];
|
|
1218
|
-
|
|
1219
|
-
return [...contextTokens].some(token =>
|
|
1220
|
-
token.length >= 3 && haystacks.some(haystack => haystack.includes(token)),
|
|
1221
|
-
);
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
|
-
function resolvePreferenceSkillNames(refs: string[], base: string): string[] {
|
|
1225
|
-
if (refs.length === 0) return [];
|
|
1226
|
-
const prefs: GSDPreferences = { always_use_skills: refs };
|
|
1227
|
-
const report = resolveAllSkillReferences(prefs, base);
|
|
1228
|
-
return refs.map(ref => {
|
|
1229
|
-
const resolution = report.resolutions.get(ref);
|
|
1230
|
-
return normalizeSkillReference(resolution?.resolvedPath ?? ref);
|
|
1231
|
-
}).filter(Boolean);
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
function ruleMatchesContext(when: string, contextTokens: Set<string>): boolean {
|
|
1235
|
-
const whenTokens = tokenizeSkillContext(when);
|
|
1236
|
-
return [...whenTokens].some(token =>
|
|
1237
|
-
contextTokens.has(token) || [...contextTokens].some(ctx => ctx.includes(token) || token.includes(ctx)),
|
|
1238
|
-
);
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
function resolveSkillRuleMatches(
|
|
1242
|
-
prefs: GSDPreferences | undefined,
|
|
1243
|
-
contextTokens: Set<string>,
|
|
1244
|
-
base: string,
|
|
1245
|
-
): { include: string[]; avoid: string[] } {
|
|
1246
|
-
if (!prefs?.skill_rules?.length) return { include: [], avoid: [] };
|
|
1247
|
-
|
|
1248
|
-
const include: string[] = [];
|
|
1249
|
-
const avoid: string[] = [];
|
|
1250
|
-
for (const rule of prefs.skill_rules) {
|
|
1251
|
-
if (!ruleMatchesContext(rule.when, contextTokens)) continue;
|
|
1252
|
-
include.push(...resolvePreferenceSkillNames([...(rule.use ?? []), ...(rule.prefer ?? [])], base));
|
|
1253
|
-
avoid.push(...resolvePreferenceSkillNames(rule.avoid ?? [], base));
|
|
1254
|
-
}
|
|
1255
|
-
return { include, avoid };
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
function resolvePreferredSkillNames(
|
|
1259
|
-
prefs: GSDPreferences | undefined,
|
|
1260
|
-
visibleSkills: Skill[],
|
|
1261
|
-
contextTokens: Set<string>,
|
|
1262
|
-
base: string,
|
|
1263
|
-
): string[] {
|
|
1264
|
-
if (!prefs?.prefer_skills?.length) return [];
|
|
1265
|
-
const preferred = new Set(resolvePreferenceSkillNames(prefs.prefer_skills, base));
|
|
1266
|
-
return visibleSkills
|
|
1267
|
-
.filter(skill => preferred.has(normalizeSkillReference(skill.name)) && skillMatchesContext(skill, contextTokens))
|
|
1268
|
-
.map(skill => normalizeSkillReference(skill.name));
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
/** Skill names must be lowercase alphanumeric with hyphens — reject anything else
|
|
1272
|
-
* to prevent prompt injection via crafted directory names. */
|
|
1273
|
-
const SAFE_SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
1274
|
-
|
|
1275
|
-
function formatSkillActivationBlock(skillNames: string[]): string {
|
|
1276
|
-
const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
|
|
1277
|
-
if (safe.length === 0) return "";
|
|
1278
|
-
// Use explicit parameter syntax so LLMs pass { skill: "..." } instead of { name: "..." }.
|
|
1279
|
-
// The function-call-like syntax `Skill('name')` led LLMs to infer a positional
|
|
1280
|
-
// parameter name, causing tool validation failures — see #2224.
|
|
1281
|
-
const calls = safe.map(name => `Call Skill({ skill: '${name}' })`).join('. ');
|
|
1282
|
-
return `<skill_activation>${calls}.</skill_activation>`;
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
/**
|
|
1286
|
-
* Manifest-driven recommendations block — informational only, does NOT
|
|
1287
|
-
* auto-invoke. Lists per-unit-type skills that are installed but not already
|
|
1288
|
-
* activated by explicit user intent (always_use_skills / prefer_skills /
|
|
1289
|
-
* skill_rules / task-plan skills_used). Surfaces relevant skills to the
|
|
1290
|
-
* model so they can be invoked when the model judges them useful.
|
|
1291
|
-
*
|
|
1292
|
-
* This is the additive complement to the existing activation directive:
|
|
1293
|
-
* activation force-invokes (explicit intent), recommendations remind
|
|
1294
|
-
* (manifest defaults). User intent is preserved as the stronger signal
|
|
1295
|
-
* (RFC #4779 design principle); this block only adds visibility.
|
|
1296
|
-
*/
|
|
1297
|
-
function formatSkillRecommendationsBlock(unitType: string | undefined, skillNames: string[]): string {
|
|
1298
|
-
if (!unitType) return "";
|
|
1299
|
-
const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
|
|
1300
|
-
if (safe.length === 0) return "";
|
|
1301
|
-
return `<skill_recommendations unit="${unitType}">For this unit type, also consider invoking: ${safe.join(", ")}. Use Skill({ skill: 'name' }) when relevant — these are recommendations, not requirements.</skill_recommendations>`;
|
|
1302
|
-
}
|
|
1303
|
-
|
|
1304
|
-
export function buildSkillActivationBlock(params: {
|
|
1305
|
-
base: string;
|
|
1306
|
-
milestoneId: string;
|
|
1307
|
-
milestoneTitle?: string;
|
|
1308
|
-
sliceId?: string;
|
|
1309
|
-
sliceTitle?: string;
|
|
1310
|
-
taskId?: string;
|
|
1311
|
-
taskTitle?: string;
|
|
1312
|
-
extraContext?: string[];
|
|
1313
|
-
taskPlanContent?: string | null;
|
|
1314
|
-
preferences?: GSDPreferences;
|
|
1315
|
-
/**
|
|
1316
|
-
* Unit type dispatching this prompt. When provided, skills are filtered
|
|
1317
|
-
* through the per-unit-type manifest (see `skill-manifest.ts`). Unknown
|
|
1318
|
-
* or omitted values retain the pre-manifest behavior (all skills eligible).
|
|
1319
|
-
*/
|
|
1320
|
-
unitType?: string;
|
|
1321
|
-
}): string {
|
|
1322
|
-
const prefs = params.preferences ?? loadEffectiveGSDPreferences(params.base)?.preferences;
|
|
1323
|
-
const contextTokens = tokenizeSkillContext(
|
|
1324
|
-
params.milestoneId,
|
|
1325
|
-
params.milestoneTitle,
|
|
1326
|
-
params.sliceId,
|
|
1327
|
-
params.sliceTitle,
|
|
1328
|
-
params.taskId,
|
|
1329
|
-
params.taskTitle,
|
|
1330
|
-
);
|
|
1331
|
-
|
|
1332
|
-
const loaded = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
|
|
1333
|
-
|
|
1334
|
-
// Skill activation here is driven entirely by explicit sources
|
|
1335
|
-
// (always_use_skills, prefer_skills, skill_rules, task-plan skills_used).
|
|
1336
|
-
// Every match is an explicit user/project intent and must not be dropped
|
|
1337
|
-
// by the unit-type manifest — user intent is stronger signal than
|
|
1338
|
-
// defaults. The manifest's real home is the skill catalog rendering
|
|
1339
|
-
// layer (pi-coding-agent `formatSkillsForPrompt`); that wiring is tracked
|
|
1340
|
-
// as the "load-time short-circuit" follow-up to RFC #4779.
|
|
1341
|
-
//
|
|
1342
|
-
// `unitType` stays plumbed so the strict-mode warning can surface
|
|
1343
|
-
// manifest entries that reference uninstalled skills, and so the
|
|
1344
|
-
// activation-block site is ready to opt in once PR B lands.
|
|
1345
|
-
const visibleSkills = loaded;
|
|
1346
|
-
const installedNames = new Set(visibleSkills.map(skill => normalizeSkillReference(skill.name)));
|
|
1347
|
-
warnIfManifestHasMissingSkills(params.unitType, installedNames);
|
|
1348
|
-
const avoided = new Set(resolvePreferenceSkillNames(prefs?.avoid_skills ?? [], params.base));
|
|
1349
|
-
const matched = new Set<string>();
|
|
1350
|
-
|
|
1351
|
-
for (const name of resolvePreferenceSkillNames(prefs?.always_use_skills ?? [], params.base)) {
|
|
1352
|
-
matched.add(name);
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
const ruleMatches = resolveSkillRuleMatches(prefs, contextTokens, params.base);
|
|
1356
|
-
for (const name of ruleMatches.include) matched.add(name);
|
|
1357
|
-
for (const name of ruleMatches.avoid) avoided.add(name);
|
|
1358
|
-
|
|
1359
|
-
for (const name of resolvePreferredSkillNames(prefs, visibleSkills, contextTokens, params.base)) {
|
|
1360
|
-
matched.add(name);
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
if (params.taskPlanContent) {
|
|
1364
|
-
try {
|
|
1365
|
-
const taskPlan = parseTaskPlanFile(params.taskPlanContent);
|
|
1366
|
-
for (const skillName of taskPlan.frontmatter.skills_used) {
|
|
1367
|
-
matched.add(normalizeSkillReference(skillName));
|
|
1368
|
-
}
|
|
1369
|
-
} catch (err) {
|
|
1370
|
-
logWarning("prompt", `parseTaskPlanFile failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
// Heuristic auto-match (gated on skill_discovery: "auto").
|
|
1375
|
-
// For each installed skill, check if its name or description appears in the
|
|
1376
|
-
// unit's context tokens (milestone/slice/task titles). Only consider skills
|
|
1377
|
-
// already on the unit-type manifest allowlist — this keeps the heuristic
|
|
1378
|
-
// narrow and avoids wildly off-topic activations.
|
|
1379
|
-
// Users who set `skill_discovery: "off"` or "suggest" do not get
|
|
1380
|
-
// auto-matched skills (the recommendations block still surfaces manifest
|
|
1381
|
-
// skills passively); only "auto" actually adds them to the activation
|
|
1382
|
-
// directive set. Default `skill_discovery` is "suggest", so this is opt-in.
|
|
1383
|
-
if ((prefs?.skill_discovery ?? "suggest") === "auto") {
|
|
1384
|
-
const manifestAllow = resolveSkillManifest(params.unitType);
|
|
1385
|
-
const allowSet = manifestAllow ? new Set(manifestAllow) : null;
|
|
1386
|
-
for (const skill of visibleSkills) {
|
|
1387
|
-
const normalized = normalizeSkillReference(skill.name);
|
|
1388
|
-
if (matched.has(normalized) || avoided.has(normalized)) continue;
|
|
1389
|
-
// Respect the manifest allowlist when present; wildcard (null) lets all
|
|
1390
|
-
// installed skills compete for keyword match.
|
|
1391
|
-
if (allowSet && !allowSet.has(normalized)) continue;
|
|
1392
|
-
if (skillMatchesContext(skill, contextTokens)) {
|
|
1393
|
-
matched.add(normalized);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
|
|
1398
|
-
const ordered = [...matched]
|
|
1399
|
-
.filter(name => installedNames.has(name) && !avoided.has(name))
|
|
1400
|
-
.sort();
|
|
1401
|
-
const activationBlock = formatSkillActivationBlock(ordered);
|
|
1402
|
-
|
|
1403
|
-
// Manifest-driven recommendations (additive, does not override explicit intent).
|
|
1404
|
-
// Only surface skills the manifest declares for this unit type that are
|
|
1405
|
-
// installed and not already in matched/avoided.
|
|
1406
|
-
const matchedSet = new Set(ordered);
|
|
1407
|
-
const manifestList = resolveSkillManifest(params.unitType);
|
|
1408
|
-
const recommendations = (manifestList ?? [])
|
|
1409
|
-
.filter(name => installedNames.has(name) && !avoided.has(name) && !matchedSet.has(name))
|
|
1410
|
-
.sort();
|
|
1411
|
-
const recommendationsBlock = formatSkillRecommendationsBlock(params.unitType, recommendations);
|
|
1412
|
-
|
|
1413
|
-
if (!activationBlock && !recommendationsBlock) return "";
|
|
1414
|
-
if (!activationBlock) return recommendationsBlock;
|
|
1415
|
-
if (!recommendationsBlock) return activationBlock;
|
|
1416
|
-
return `${activationBlock}\n${recommendationsBlock}`;
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
/**
|
|
1420
|
-
* Build the skill discovery template variables for research prompts.
|
|
1421
|
-
* Returns { skillDiscoveryMode, skillDiscoveryInstructions } for template substitution.
|
|
1422
|
-
*/
|
|
1423
|
-
export function buildSkillDiscoveryVars(): { skillDiscoveryMode: string; skillDiscoveryInstructions: string } {
|
|
1424
|
-
const mode = resolveSkillDiscoveryMode();
|
|
1425
|
-
|
|
1426
|
-
if (mode === "off") {
|
|
1427
|
-
return {
|
|
1428
|
-
skillDiscoveryMode: "off",
|
|
1429
|
-
skillDiscoveryInstructions: " Skill discovery is disabled. Skip this step.",
|
|
1430
|
-
};
|
|
1431
|
-
}
|
|
1432
|
-
|
|
1433
|
-
const autoInstall = mode === "auto";
|
|
1434
|
-
const instructions = `
|
|
1435
|
-
Identify the key technologies, frameworks, and services this work depends on (e.g. Stripe, Clerk, Supabase, JUCE, SwiftUI).
|
|
1436
|
-
For each, check if a professional agent skill already exists:
|
|
1437
|
-
- First check \`<available_skills>\` in your system prompt — a skill may already be installed.
|
|
1438
|
-
- For technologies without an installed skill, run: \`npx skills find "<technology>"\`
|
|
1439
|
-
- Only consider skills that are **directly relevant** to core technologies — not tangentially related.
|
|
1440
|
-
- Evaluate results by install count and relevance to the actual work.${autoInstall
|
|
1441
|
-
? `
|
|
1442
|
-
- Install relevant skills: \`npx skills add <owner/repo@skill> -g -y\`
|
|
1443
|
-
- Record installed skills in the "Skills Discovered" section of your research output.
|
|
1444
|
-
- Installed skills will automatically appear in subsequent units' system prompts — no manual steps needed.`
|
|
1445
|
-
: `
|
|
1446
|
-
- Note promising skills in your research output with their install commands, but do NOT install them.
|
|
1447
|
-
- The user will decide which to install.`
|
|
1448
|
-
}`;
|
|
1449
|
-
|
|
1450
|
-
return {
|
|
1451
|
-
skillDiscoveryMode: mode,
|
|
1452
|
-
skillDiscoveryInstructions: instructions,
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1176
|
// ─── Text Helpers ──────────────────────────────────────────────────────────
|
|
1457
1177
|
|
|
1458
1178
|
export function extractMarkdownSection(content: string, heading: string): string | null {
|
|
@@ -413,22 +413,25 @@ export function verifyExpectedArtifact(
|
|
|
413
413
|
return true;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
-
const roadmapFile =
|
|
416
|
+
const roadmapFile = resolveExpectedArtifactPath("plan-milestone", mid, base);
|
|
417
417
|
if (!roadmapFile || !existsSync(roadmapFile)) {
|
|
418
418
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: roadmap missing`);
|
|
419
419
|
return false;
|
|
420
420
|
}
|
|
421
421
|
try {
|
|
422
422
|
const roadmap = parseLegacyRoadmap(readFileSync(roadmapFile, "utf-8"));
|
|
423
|
-
const milestoneResearchFile =
|
|
423
|
+
const milestoneResearchFile = resolveExpectedArtifactPath("research-milestone", mid, base);
|
|
424
|
+
const hasMilestoneResearch = !!milestoneResearchFile && existsSync(milestoneResearchFile);
|
|
424
425
|
for (const slice of roadmap.slices) {
|
|
425
426
|
if (slice.done) continue;
|
|
426
|
-
if (
|
|
427
|
-
const depsComplete = (slice.depends ?? []).every((depId) =>
|
|
428
|
-
|
|
429
|
-
|
|
427
|
+
if (hasMilestoneResearch && slice.id === "S01") continue;
|
|
428
|
+
const depsComplete = (slice.depends ?? []).every((depId) => {
|
|
429
|
+
const summaryPath = resolveExpectedArtifactPath("complete-slice", `${mid}/${depId}`, base);
|
|
430
|
+
return !!summaryPath && existsSync(summaryPath);
|
|
431
|
+
});
|
|
430
432
|
if (!depsComplete) continue;
|
|
431
|
-
|
|
433
|
+
const researchPath = resolveExpectedArtifactPath("research-slice", `${mid}/${slice.id}`, base);
|
|
434
|
+
if (!researchPath || !existsSync(researchPath)) {
|
|
432
435
|
logWarning("recovery", `verify-fail ${unitType} ${unitId}: slice ${slice.id} missing RESEARCH`);
|
|
433
436
|
return false;
|
|
434
437
|
}
|