@opengsd/gsd-pi 1.0.0
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/LICENSE +21 -0
- package/README.md +96 -0
- package/package.json +171 -0
- package/packages/contracts/dist/index.d.ts +3 -0
- package/packages/contracts/dist/index.d.ts.map +1 -0
- package/packages/contracts/dist/index.js +5 -0
- package/packages/contracts/dist/index.js.map +1 -0
- package/packages/contracts/dist/rpc.d.ts +549 -0
- package/packages/contracts/dist/rpc.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.js +53 -0
- package/packages/contracts/dist/rpc.js.map +1 -0
- package/packages/contracts/dist/rpc.test.d.ts +2 -0
- package/packages/contracts/dist/rpc.test.d.ts.map +1 -0
- package/packages/contracts/dist/rpc.test.js +54 -0
- package/packages/contracts/dist/rpc.test.js.map +1 -0
- package/packages/contracts/dist/workflow.d.ts +201 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -0
- package/packages/contracts/dist/workflow.js +225 -0
- package/packages/contracts/dist/workflow.js.map +1 -0
- package/packages/contracts/package.json +39 -0
- package/packages/contracts/src/index.ts +5 -0
- package/packages/contracts/src/rpc.test.ts +80 -0
- package/packages/contracts/src/rpc.ts +286 -0
- package/packages/contracts/src/workflow.ts +237 -0
- package/packages/contracts/tsconfig.json +25 -0
- package/packages/daemon/package.json +49 -0
- package/packages/daemon/src/channel-manager.ts +223 -0
- package/packages/daemon/src/cli.ts +96 -0
- package/packages/daemon/src/commands.ts +110 -0
- package/packages/daemon/src/config.ts +137 -0
- package/packages/daemon/src/daemon.test.ts +763 -0
- package/packages/daemon/src/daemon.ts +199 -0
- package/packages/daemon/src/discord-bot.test.ts +792 -0
- package/packages/daemon/src/discord-bot.ts +491 -0
- package/packages/daemon/src/event-bridge.test.ts +620 -0
- package/packages/daemon/src/event-bridge.ts +494 -0
- package/packages/daemon/src/event-formatter.test.ts +401 -0
- package/packages/daemon/src/event-formatter.ts +413 -0
- package/packages/daemon/src/index.ts +55 -0
- package/packages/daemon/src/launchd.test.ts +356 -0
- package/packages/daemon/src/launchd.ts +242 -0
- package/packages/daemon/src/logger.ts +89 -0
- package/packages/daemon/src/message-batcher.test.ts +308 -0
- package/packages/daemon/src/message-batcher.ts +216 -0
- package/packages/daemon/src/orchestrator.test.ts +584 -0
- package/packages/daemon/src/orchestrator.ts +469 -0
- package/packages/daemon/src/project-scanner.test.ts +235 -0
- package/packages/daemon/src/project-scanner.ts +99 -0
- package/packages/daemon/src/session-manager.test.ts +822 -0
- package/packages/daemon/src/session-manager.ts +400 -0
- package/packages/daemon/src/types.ts +184 -0
- package/packages/daemon/src/verbosity.test.ts +171 -0
- package/packages/daemon/src/verbosity.ts +101 -0
- package/packages/daemon/tsconfig.json +24 -0
- package/packages/mcp-server/README.md +275 -0
- package/packages/mcp-server/package.json +53 -0
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/cli.ts +70 -0
- package/packages/mcp-server/src/env-writer.test.ts +433 -0
- package/packages/mcp-server/src/env-writer.ts +292 -0
- package/packages/mcp-server/src/import-candidates.test.ts +53 -0
- package/packages/mcp-server/src/index.ts +43 -0
- package/packages/mcp-server/src/mcp-server.test.ts +1395 -0
- package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
- package/packages/mcp-server/src/readers/captures.ts +119 -0
- package/packages/mcp-server/src/readers/doctor-lite.ts +225 -0
- package/packages/mcp-server/src/readers/graph.test.ts +679 -0
- package/packages/mcp-server/src/readers/graph.ts +863 -0
- package/packages/mcp-server/src/readers/index.ts +28 -0
- package/packages/mcp-server/src/readers/knowledge.ts +111 -0
- package/packages/mcp-server/src/readers/metrics.ts +118 -0
- package/packages/mcp-server/src/readers/paths.test.ts +67 -0
- package/packages/mcp-server/src/readers/paths.ts +334 -0
- package/packages/mcp-server/src/readers/readers.test.ts +513 -0
- package/packages/mcp-server/src/readers/roadmap.ts +263 -0
- package/packages/mcp-server/src/readers/state.ts +223 -0
- package/packages/mcp-server/src/remote-questions.test.ts +397 -0
- package/packages/mcp-server/src/remote-questions.ts +967 -0
- package/packages/mcp-server/src/secure-env-collect.test.ts +260 -0
- package/packages/mcp-server/src/server.ts +1342 -0
- package/packages/mcp-server/src/session-manager.ts +404 -0
- package/packages/mcp-server/src/tool-credentials.test.ts +95 -0
- package/packages/mcp-server/src/tool-credentials.ts +97 -0
- package/packages/mcp-server/src/types.ts +96 -0
- package/packages/mcp-server/src/workflow-tools-parity.test.ts +257 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +2350 -0
- package/packages/mcp-server/src/workflow-tools.ts +2257 -0
- package/packages/mcp-server/tsconfig.json +25 -0
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/native/dist/ast/index.d.ts +4 -0
- package/packages/native/dist/ast/index.js +11 -0
- package/packages/native/dist/ast/types.d.ts +69 -0
- package/packages/native/dist/ast/types.js +2 -0
- package/packages/native/dist/clipboard/index.d.ts +28 -0
- package/packages/native/dist/clipboard/index.js +38 -0
- package/packages/native/dist/clipboard/types.d.ts +7 -0
- package/packages/native/dist/clipboard/types.js +2 -0
- package/packages/native/dist/diff/index.d.ts +33 -0
- package/packages/native/dist/diff/index.js +43 -0
- package/packages/native/dist/diff/types.d.ts +23 -0
- package/packages/native/dist/diff/types.js +2 -0
- package/packages/native/dist/fd/index.d.ts +26 -0
- package/packages/native/dist/fd/index.js +30 -0
- package/packages/native/dist/fd/types.d.ts +29 -0
- package/packages/native/dist/fd/types.js +2 -0
- package/packages/native/dist/glob/index.d.ts +28 -0
- package/packages/native/dist/glob/index.js +35 -0
- package/packages/native/dist/glob/types.d.ts +50 -0
- package/packages/native/dist/glob/types.js +2 -0
- package/packages/native/dist/grep/index.d.ts +21 -0
- package/packages/native/dist/grep/index.js +28 -0
- package/packages/native/dist/grep/types.d.ts +99 -0
- package/packages/native/dist/grep/types.js +2 -0
- package/packages/native/dist/gsd-parser/index.d.ts +45 -0
- package/packages/native/dist/gsd-parser/index.js +61 -0
- package/packages/native/dist/gsd-parser/types.d.ts +55 -0
- package/packages/native/dist/gsd-parser/types.js +8 -0
- package/packages/native/dist/highlight/index.d.ts +28 -0
- package/packages/native/dist/highlight/index.js +38 -0
- package/packages/native/dist/highlight/types.d.ts +25 -0
- package/packages/native/dist/highlight/types.js +2 -0
- package/packages/native/dist/html/index.d.ts +15 -0
- package/packages/native/dist/html/index.js +19 -0
- package/packages/native/dist/html/types.d.ts +7 -0
- package/packages/native/dist/html/types.js +2 -0
- package/packages/native/dist/image/index.d.ts +15 -0
- package/packages/native/dist/image/index.js +23 -0
- package/packages/native/dist/image/types.d.ts +35 -0
- package/packages/native/dist/image/types.js +29 -0
- package/packages/native/dist/index.d.ts +46 -0
- package/packages/native/dist/index.js +85 -0
- package/packages/native/dist/json-parse/index.d.ts +23 -0
- package/packages/native/dist/json-parse/index.js +78 -0
- package/packages/native/dist/native.d.ts +57 -0
- package/packages/native/dist/native.js +113 -0
- package/packages/native/dist/ps/index.d.ts +38 -0
- package/packages/native/dist/ps/index.js +53 -0
- package/packages/native/dist/stream-process/index.d.ts +35 -0
- package/packages/native/dist/stream-process/index.js +254 -0
- package/packages/native/dist/text/index.d.ts +55 -0
- package/packages/native/dist/text/index.js +76 -0
- package/packages/native/dist/text/types.d.ts +27 -0
- package/packages/native/dist/text/types.js +13 -0
- package/packages/native/dist/truncate/index.d.ts +29 -0
- package/packages/native/dist/truncate/index.js +30 -0
- package/packages/native/dist/ttsr/index.d.ts +27 -0
- package/packages/native/dist/ttsr/index.js +37 -0
- package/packages/native/dist/ttsr/types.d.ts +9 -0
- package/packages/native/dist/ttsr/types.js +2 -0
- package/packages/native/dist/xxhash/index.d.ts +22 -0
- package/packages/native/dist/xxhash/index.js +89 -0
- package/packages/native/package.json +97 -0
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/clipboard.test.mjs +126 -0
- package/packages/native/src/__tests__/diff.test.mjs +189 -0
- package/packages/native/src/__tests__/fd.test.mjs +199 -0
- package/packages/native/src/__tests__/glob.test.mjs +237 -0
- package/packages/native/src/__tests__/grep.test.mjs +179 -0
- package/packages/native/src/__tests__/highlight.test.mjs +156 -0
- package/packages/native/src/__tests__/html.test.mjs +98 -0
- package/packages/native/src/__tests__/image.test.mjs +137 -0
- package/packages/native/src/__tests__/json-parse.test.mjs +158 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +123 -0
- package/packages/native/src/__tests__/ps.test.mjs +115 -0
- package/packages/native/src/__tests__/stream-process.test.mjs +108 -0
- package/packages/native/src/__tests__/text.test.mjs +295 -0
- package/packages/native/src/__tests__/truncate.test.mjs +160 -0
- package/packages/native/src/__tests__/ttsr.test.mjs +135 -0
- package/packages/native/src/__tests__/xxhash.test.mjs +122 -0
- package/packages/native/src/ast/index.ts +12 -0
- package/packages/native/src/ast/types.ts +75 -0
- package/packages/native/src/clipboard/index.ts +40 -0
- package/packages/native/src/clipboard/types.ts +7 -0
- package/packages/native/src/diff/index.ts +61 -0
- package/packages/native/src/diff/types.ts +24 -0
- package/packages/native/src/fd/index.ts +36 -0
- package/packages/native/src/fd/types.ts +31 -0
- package/packages/native/src/glob/index.ts +44 -0
- package/packages/native/src/glob/types.ts +53 -0
- package/packages/native/src/grep/index.ts +49 -0
- package/packages/native/src/grep/types.ts +105 -0
- package/packages/native/src/gsd-parser/index.ts +98 -0
- package/packages/native/src/gsd-parser/types.ts +62 -0
- package/packages/native/src/highlight/index.ts +44 -0
- package/packages/native/src/highlight/types.ts +25 -0
- package/packages/native/src/html/index.ts +24 -0
- package/packages/native/src/html/types.ts +7 -0
- package/packages/native/src/image/index.ts +28 -0
- package/packages/native/src/image/types.ts +41 -0
- package/packages/native/src/index.ts +128 -0
- package/packages/native/src/json-parse/index.ts +76 -0
- package/packages/native/src/native.ts +154 -0
- package/packages/native/src/ps/index.ts +52 -0
- package/packages/native/src/stream-process/index.ts +313 -0
- package/packages/native/src/text/index.ts +125 -0
- package/packages/native/src/text/types.ts +29 -0
- package/packages/native/src/truncate/index.ts +50 -0
- package/packages/native/src/ttsr/index.ts +39 -0
- package/packages/native/src/ttsr/types.ts +10 -0
- package/packages/native/src/xxhash/index.ts +98 -0
- package/packages/native/tsconfig.json +9 -0
- package/packages/native/tsconfig.tsbuildinfo +1 -0
- package/packages/pi-agent-core/package.json +23 -0
- package/packages/pi-agent-core/src/agent-loop.test.ts +733 -0
- package/packages/pi-agent-core/src/agent-loop.ts +851 -0
- package/packages/pi-agent-core/src/agent.test.ts +129 -0
- package/packages/pi-agent-core/src/agent.ts +668 -0
- package/packages/pi-agent-core/src/index.ts +10 -0
- package/packages/pi-agent-core/src/proxy.ts +334 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +358 -0
- package/packages/pi-agent-core/tsconfig.json +28 -0
- package/packages/pi-ai/bedrock-provider.d.ts +1 -0
- package/packages/pi-ai/bedrock-provider.js +1 -0
- package/packages/pi-ai/package.json +48 -0
- package/packages/pi-ai/scripts/generate-models.ts +1671 -0
- package/packages/pi-ai/src/api-registry.ts +86 -0
- package/packages/pi-ai/src/bedrock-provider.ts +6 -0
- package/packages/pi-ai/src/cli.ts +133 -0
- package/packages/pi-ai/src/env-api-keys.ts +148 -0
- package/packages/pi-ai/src/index.ts +36 -0
- package/packages/pi-ai/src/models/capability-patches.ts +51 -0
- package/packages/pi-ai/src/models/custom.ts +337 -0
- package/packages/pi-ai/src/models/fake-model.ts +30 -0
- package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1554 -0
- package/packages/pi-ai/src/models/generated/anthropic.ts +398 -0
- package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
- package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
- package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
- package/packages/pi-ai/src/models/generated/google-antigravity.ts +177 -0
- package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
- package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
- package/packages/pi-ai/src/models/generated/google.ts +466 -0
- package/packages/pi-ai/src/models/generated/groq.ts +160 -0
- package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
- package/packages/pi-ai/src/models/generated/index.ts +52 -0
- package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
- package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
- package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
- package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
- package/packages/pi-ai/src/models/generated/openai-codex.ts +177 -0
- package/packages/pi-ai/src/models/generated/openai.ts +721 -0
- package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
- package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
- package/packages/pi-ai/src/models/generated/openrouter.ts +4291 -0
- package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
- package/packages/pi-ai/src/models/generated/xai.ts +415 -0
- package/packages/pi-ai/src/models/generated/zai.ts +241 -0
- package/packages/pi-ai/src/models/index.ts +115 -0
- package/packages/pi-ai/src/models.generated.test.ts +362 -0
- package/packages/pi-ai/src/models.test.ts +404 -0
- package/packages/pi-ai/src/models.ts +3 -0
- package/packages/pi-ai/src/oauth.ts +1 -0
- package/packages/pi-ai/src/providers/amazon-bedrock.test.ts +164 -0
- package/packages/pi-ai/src/providers/amazon-bedrock.ts +797 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +92 -0
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +36 -0
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +134 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +899 -0
- package/packages/pi-ai/src/providers/anthropic-vertex.ts +130 -0
- package/packages/pi-ai/src/providers/anthropic.ts +240 -0
- package/packages/pi-ai/src/providers/api-family.test.ts +129 -0
- package/packages/pi-ai/src/providers/api-family.ts +57 -0
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +248 -0
- package/packages/pi-ai/src/providers/fake.ts +376 -0
- package/packages/pi-ai/src/providers/github-copilot-headers.ts +37 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +90 -0
- package/packages/pi-ai/src/providers/google-gemini-cli.ts +982 -0
- package/packages/pi-ai/src/providers/google-shared.test.ts +137 -0
- package/packages/pi-ai/src/providers/google-shared.ts +364 -0
- package/packages/pi-ai/src/providers/google-vertex.ts +500 -0
- package/packages/pi-ai/src/providers/google.ts +467 -0
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +118 -0
- package/packages/pi-ai/src/providers/mistral.ts +597 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
- package/packages/pi-ai/src/providers/openai-codex-responses.ts +1007 -0
- package/packages/pi-ai/src/providers/openai-completions.test.ts +75 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +830 -0
- package/packages/pi-ai/src/providers/openai-responses-shared.ts +496 -0
- package/packages/pi-ai/src/providers/openai-responses.ts +205 -0
- package/packages/pi-ai/src/providers/openai-shared.ts +193 -0
- package/packages/pi-ai/src/providers/provider-capabilities.test.ts +174 -0
- package/packages/pi-ai/src/providers/provider-capabilities.ts +215 -0
- package/packages/pi-ai/src/providers/register-builtins.ts +216 -0
- package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
- package/packages/pi-ai/src/providers/simple-options.ts +61 -0
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/src/providers/transform-messages-report.test.ts +189 -0
- package/packages/pi-ai/src/providers/transform-messages.ts +289 -0
- package/packages/pi-ai/src/stream.ts +59 -0
- package/packages/pi-ai/src/types.ts +413 -0
- package/packages/pi-ai/src/utils/event-stream.ts +87 -0
- package/packages/pi-ai/src/utils/hash.ts +13 -0
- package/packages/pi-ai/src/utils/json-parse.ts +51 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +282 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +470 -0
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +80 -0
- package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +323 -0
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +80 -0
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +468 -0
- package/packages/pi-ai/src/utils/oauth/google-oauth-utils.ts +201 -0
- package/packages/pi-ai/src/utils/oauth/index.ts +134 -0
- package/packages/pi-ai/src/utils/oauth/openai-codex.ts +472 -0
- package/packages/pi-ai/src/utils/oauth/pkce.ts +34 -0
- package/packages/pi-ai/src/utils/oauth/types.ts +49 -0
- package/packages/pi-ai/src/utils/overflow.ts +129 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +241 -0
- package/packages/pi-ai/src/utils/sanitize-unicode.ts +25 -0
- package/packages/pi-ai/src/utils/tests/json-parse.test.ts +17 -0
- package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +240 -0
- package/packages/pi-ai/src/utils/typebox-helpers.ts +24 -0
- package/packages/pi-ai/src/utils/validation.ts +69 -0
- package/packages/pi-ai/src/web-runtime-env-api-keys.ts +86 -0
- package/packages/pi-ai/src/web-runtime-oauth.ts +9 -0
- package/packages/pi-ai/tsconfig.json +28 -0
- package/packages/pi-coding-agent/package.json +52 -0
- package/packages/pi-coding-agent/scripts/copy-assets.cjs +55 -0
- package/packages/pi-coding-agent/src/cli/abort-signal-timeout.test.ts +73 -0
- package/packages/pi-coding-agent/src/cli/abort-signal-timeout.ts +18 -0
- package/packages/pi-coding-agent/src/cli/args.test.ts +44 -0
- package/packages/pi-coding-agent/src/cli/args.ts +357 -0
- package/packages/pi-coding-agent/src/cli/config-selector.ts +52 -0
- package/packages/pi-coding-agent/src/cli/file-processor.ts +96 -0
- package/packages/pi-coding-agent/src/cli/list-models.ts +164 -0
- package/packages/pi-coding-agent/src/cli/session-picker.ts +51 -0
- package/packages/pi-coding-agent/src/cli.ts +20 -0
- package/packages/pi-coding-agent/src/config.ts +245 -0
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +491 -0
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +93 -0
- package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
- package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +172 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +3150 -0
- package/packages/pi-coding-agent/src/core/artifact-manager.ts +125 -0
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +654 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +925 -0
- package/packages/pi-coding-agent/src/core/bash-executor.ts +316 -0
- package/packages/pi-coding-agent/src/core/blob-store.ts +154 -0
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +1571 -0
- package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +307 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +598 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +986 -0
- package/packages/pi-coding-agent/src/core/compaction/index.ts +7 -0
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +368 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +440 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +117 -0
- package/packages/pi-coding-agent/src/core/constants.ts +59 -0
- package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
- package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/defaults.ts +3 -0
- package/packages/pi-coding-agent/src/core/diagnostics.ts +15 -0
- package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +163 -0
- package/packages/pi-coding-agent/src/core/discovery-cache.ts +104 -0
- package/packages/pi-coding-agent/src/core/event-bus.ts +33 -0
- package/packages/pi-coding-agent/src/core/exec.ts +106 -0
- package/packages/pi-coding-agent/src/core/export-html/ansi-to-html.ts +258 -0
- package/packages/pi-coding-agent/src/core/export-html/index.ts +306 -0
- package/packages/pi-coding-agent/src/core/export-html/template.css +971 -0
- package/packages/pi-coding-agent/src/core/export-html/template.html +54 -0
- package/packages/pi-coding-agent/src/core/export-html/template.js +1583 -0
- package/packages/pi-coding-agent/src/core/export-html/tool-renderer.ts +114 -0
- package/packages/pi-coding-agent/src/core/export-html/vendor/highlight.min.js +1213 -0
- package/packages/pi-coding-agent/src/core/export-html/vendor/marked.min.js +6 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +186 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +275 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +1139 -0
- package/packages/pi-coding-agent/src/core/extensions/project-trust.ts +51 -0
- package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +282 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +1241 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +1872 -0
- package/packages/pi-coding-agent/src/core/extensions/wrapper.ts +127 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +242 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.ts +164 -0
- package/packages/pi-coding-agent/src/core/footer-data-provider.ts +144 -0
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +54 -0
- package/packages/pi-coding-agent/src/core/fs-utils.ts +12 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +271 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +80 -0
- package/packages/pi-coding-agent/src/core/keybindings.ts +211 -0
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +280 -0
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/lock-utils.ts +113 -0
- package/packages/pi-coding-agent/src/core/lsp/client.ts +968 -0
- package/packages/pi-coding-agent/src/core/lsp/config.ts +356 -0
- package/packages/pi-coding-agent/src/core/lsp/defaults.json +456 -0
- package/packages/pi-coding-agent/src/core/lsp/edits.ts +109 -0
- package/packages/pi-coding-agent/src/core/lsp/helpers.ts +54 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +1065 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +451 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +70 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp.md +39 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +190 -0
- package/packages/pi-coding-agent/src/core/lsp/types.ts +445 -0
- package/packages/pi-coding-agent/src/core/lsp/utils.ts +706 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +226 -0
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +144 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +318 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +730 -0
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +210 -0
- package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +1053 -0
- package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
- package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +511 -0
- package/packages/pi-coding-agent/src/core/models-json-writer.test.ts +145 -0
- package/packages/pi-coding-agent/src/core/models-json-writer.ts +188 -0
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +262 -0
- package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
- package/packages/pi-coding-agent/src/core/package-manager.ts +1845 -0
- package/packages/pi-coding-agent/src/core/prompt-templates.ts +299 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +295 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.ts +118 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +107 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +929 -0
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +518 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +576 -0
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.test.ts +113 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +688 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +129 -0
- package/packages/pi-coding-agent/src/core/session-manager.ts +1646 -0
- package/packages/pi-coding-agent/src/core/settings-manager-security.test.ts +102 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +1247 -0
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +117 -0
- package/packages/pi-coding-agent/src/core/skills.ts +490 -0
- package/packages/pi-coding-agent/src/core/slash-commands.ts +43 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +296 -0
- package/packages/pi-coding-agent/src/core/timings.ts +25 -0
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/core/tools/bash-background.test.ts +91 -0
- package/packages/pi-coding-agent/src/core/tools/bash-interceptor.test.ts +198 -0
- package/packages/pi-coding-agent/src/core/tools/bash-interceptor.ts +115 -0
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/tools/bash.ts +478 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +85 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +402 -0
- package/packages/pi-coding-agent/src/core/tools/edit.ts +242 -0
- package/packages/pi-coding-agent/src/core/tools/find.ts +209 -0
- package/packages/pi-coding-agent/src/core/tools/grep.ts +356 -0
- package/packages/pi-coding-agent/src/core/tools/hashline-edit.ts +318 -0
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +207 -0
- package/packages/pi-coding-agent/src/core/tools/hashline.test.ts +456 -0
- package/packages/pi-coding-agent/src/core/tools/hashline.ts +525 -0
- package/packages/pi-coding-agent/src/core/tools/index.ts +226 -0
- package/packages/pi-coding-agent/src/core/tools/ls.ts +178 -0
- package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +67 -0
- package/packages/pi-coding-agent/src/core/tools/path-utils.ts +106 -0
- package/packages/pi-coding-agent/src/core/tools/read.ts +235 -0
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +31 -0
- package/packages/pi-coding-agent/src/core/tools/tool-compatibility-registry.ts +83 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
- package/packages/pi-coding-agent/src/core/tools/truncate.ts +267 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +133 -0
- package/packages/pi-coding-agent/src/index.ts +422 -0
- package/packages/pi-coding-agent/src/main.ts +649 -0
- package/packages/pi-coding-agent/src/migrations.ts +295 -0
- package/packages/pi-coding-agent/src/modes/index.ts +16 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +128 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +93 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/collapsible-message.test.ts +111 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +28 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +41 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +512 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +139 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +66 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +161 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/animated-component.test.ts +115 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/animated-component.ts +107 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/armin.ts +360 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +200 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.test.ts +35 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +287 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/bordered-loader.ts +66 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/branch-summary-message.ts +54 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/collapsible-message.ts +45 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +73 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/config-selector.ts +599 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/countdown-timer.ts +43 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/custom-editor.ts +97 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/custom-message.ts +89 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/daxnuts.test.ts +68 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/daxnuts.ts +159 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +153 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +99 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +97 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +150 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +92 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/extension-selector.ts +152 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +266 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/index.ts +33 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/interactive-key-handling.test.ts +122 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/keybinding-hints.ts +84 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +256 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +693 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/oauth-selector.ts +127 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +231 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/render-cache.ts +22 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/scoped-models-selector.ts +342 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/selector-footers.test.ts +63 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/session-selector-search.ts +194 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/session-selector.ts +1015 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +466 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/show-images-selector.ts +47 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +61 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/theme-selector.test.ts +27 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/theme-selector.ts +67 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +66 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +49 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +303 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1457 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +345 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tree-render-utils.ts +84 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tree-selector.ts +1125 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message-selector.test.ts +28 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message-selector.ts +154 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +76 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/visual-truncate.ts +50 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +230 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +1066 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +68 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +373 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +157 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +76 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-lifecycle.test.ts +63 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +73 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +40 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4418 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
- package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +695 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +96 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +1130 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +388 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +68 -0
- package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
- package/packages/pi-coding-agent/src/modes/interactive/utils/shorten-path.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/utils/tool-call-summary.test.ts +39 -0
- package/packages/pi-coding-agent/src/modes/interactive/utils/tool-call-summary.ts +56 -0
- package/packages/pi-coding-agent/src/modes/print-mode.ts +106 -0
- package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +64 -0
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +109 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +574 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +891 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-protocol-v2.test.ts +971 -0
- package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +4 -0
- package/packages/pi-coding-agent/src/modes/shared/command-context-actions.ts +53 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/index.ts +270 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/pipeline.ts +567 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +31 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +98 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +479 -0
- package/packages/pi-coding-agent/src/tests/path-display.test.ts +85 -0
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
- package/packages/pi-coding-agent/src/utils/changelog.ts +99 -0
- package/packages/pi-coding-agent/src/utils/clipboard-image.ts +227 -0
- package/packages/pi-coding-agent/src/utils/clipboard-native.ts +11 -0
- package/packages/pi-coding-agent/src/utils/clipboard.ts +14 -0
- package/packages/pi-coding-agent/src/utils/error.ts +6 -0
- package/packages/pi-coding-agent/src/utils/frontmatter.ts +39 -0
- package/packages/pi-coding-agent/src/utils/git.ts +192 -0
- package/packages/pi-coding-agent/src/utils/image-convert.ts +28 -0
- package/packages/pi-coding-agent/src/utils/image-resize.ts +225 -0
- package/packages/pi-coding-agent/src/utils/mime.ts +30 -0
- package/packages/pi-coding-agent/src/utils/path-display.ts +36 -0
- package/packages/pi-coding-agent/src/utils/photon.ts +2 -0
- package/packages/pi-coding-agent/src/utils/shell.ts +212 -0
- package/packages/pi-coding-agent/src/utils/sleep.ts +18 -0
- package/packages/pi-coding-agent/src/utils/tools-manager.ts +286 -0
- package/packages/pi-coding-agent/tsconfig.json +28 -0
- package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +206 -0
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/fuzzy.test.js +100 -0
- package/packages/pi-tui/dist/__tests__/fuzzy.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/keys.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/keys.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/keys.test.js +18 -0
- package/packages/pi-tui/dist/__tests__/keys.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/loader.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js +24 -0
- package/packages/pi-tui/dist/__tests__/loader.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +227 -0
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +80 -0
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/style.test.js +129 -0
- package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
- package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/tui.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js +315 -0
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -0
- package/packages/pi-tui/dist/__tests__/utils.test.d.ts +2 -0
- package/packages/pi-tui/dist/__tests__/utils.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/__tests__/utils.test.js +17 -0
- package/packages/pi-tui/dist/__tests__/utils.test.js.map +1 -0
- package/packages/pi-tui/dist/autocomplete.d.ts +55 -0
- package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -0
- package/packages/pi-tui/dist/autocomplete.js +540 -0
- package/packages/pi-tui/dist/autocomplete.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/box.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/box.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/box.test.js +20 -0
- package/packages/pi-tui/dist/components/__tests__/box.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.js +38 -0
- package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.js +89 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js +81 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/loader.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/loader.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +81 -0
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-list.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-list.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-list.test.js +36 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-list.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +70 -0
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/select-list.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/select-list.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/select-list.test.js +42 -0
- package/packages/pi-tui/dist/components/__tests__/select-list.test.js.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/truncated-text.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/truncated-text.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/truncated-text.test.js +14 -0
- package/packages/pi-tui/dist/components/__tests__/truncated-text.test.js.map +1 -0
- package/packages/pi-tui/dist/components/box.d.ts +23 -0
- package/packages/pi-tui/dist/components/box.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/box.js +111 -0
- package/packages/pi-tui/dist/components/box.js.map +1 -0
- package/packages/pi-tui/dist/components/cancellable-loader.d.ts +22 -0
- package/packages/pi-tui/dist/components/cancellable-loader.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/cancellable-loader.js +38 -0
- package/packages/pi-tui/dist/components/cancellable-loader.js.map +1 -0
- package/packages/pi-tui/dist/components/editor.d.ts +245 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/editor.js +1825 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -0
- package/packages/pi-tui/dist/components/image.d.ts +37 -0
- package/packages/pi-tui/dist/components/image.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/image.js +84 -0
- package/packages/pi-tui/dist/components/image.js.map +1 -0
- package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
- package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/image.test.js +33 -0
- package/packages/pi-tui/dist/components/image.test.js.map +1 -0
- package/packages/pi-tui/dist/components/input.d.ts +42 -0
- package/packages/pi-tui/dist/components/input.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/input.js +479 -0
- package/packages/pi-tui/dist/components/input.js.map +1 -0
- package/packages/pi-tui/dist/components/loader.d.ts +24 -0
- package/packages/pi-tui/dist/components/loader.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/loader.js +74 -0
- package/packages/pi-tui/dist/components/loader.js.map +1 -0
- package/packages/pi-tui/dist/components/markdown.d.ts +106 -0
- package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/markdown.js +668 -0
- package/packages/pi-tui/dist/components/markdown.js.map +1 -0
- package/packages/pi-tui/dist/components/select-list.d.ts +32 -0
- package/packages/pi-tui/dist/components/select-list.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/select-list.js +155 -0
- package/packages/pi-tui/dist/components/select-list.js.map +1 -0
- package/packages/pi-tui/dist/components/settings-list.d.ts +50 -0
- package/packages/pi-tui/dist/components/settings-list.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/settings-list.js +179 -0
- package/packages/pi-tui/dist/components/settings-list.js.map +1 -0
- package/packages/pi-tui/dist/components/spacer.d.ts +12 -0
- package/packages/pi-tui/dist/components/spacer.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/spacer.js +22 -0
- package/packages/pi-tui/dist/components/spacer.js.map +1 -0
- package/packages/pi-tui/dist/components/text.d.ts +19 -0
- package/packages/pi-tui/dist/components/text.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/text.js +83 -0
- package/packages/pi-tui/dist/components/text.js.map +1 -0
- package/packages/pi-tui/dist/components/truncated-text.d.ts +13 -0
- package/packages/pi-tui/dist/components/truncated-text.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/truncated-text.js +54 -0
- package/packages/pi-tui/dist/components/truncated-text.js.map +1 -0
- package/packages/pi-tui/dist/editor-component.d.ts +41 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -0
- package/packages/pi-tui/dist/editor-component.js +2 -0
- package/packages/pi-tui/dist/editor-component.js.map +1 -0
- package/packages/pi-tui/dist/fuzzy.d.ts +16 -0
- package/packages/pi-tui/dist/fuzzy.d.ts.map +1 -0
- package/packages/pi-tui/dist/fuzzy.js +111 -0
- package/packages/pi-tui/dist/fuzzy.js.map +1 -0
- package/packages/pi-tui/dist/index.d.ts +24 -0
- package/packages/pi-tui/dist/index.d.ts.map +1 -0
- package/packages/pi-tui/dist/index.js +35 -0
- package/packages/pi-tui/dist/index.js.map +1 -0
- package/packages/pi-tui/dist/keybindings.d.ts +39 -0
- package/packages/pi-tui/dist/keybindings.d.ts.map +1 -0
- package/packages/pi-tui/dist/keybindings.js +116 -0
- package/packages/pi-tui/dist/keybindings.js.map +1 -0
- package/packages/pi-tui/dist/keys.d.ts +142 -0
- package/packages/pi-tui/dist/keys.d.ts.map +1 -0
- package/packages/pi-tui/dist/keys.js +994 -0
- package/packages/pi-tui/dist/keys.js.map +1 -0
- package/packages/pi-tui/dist/kill-ring.d.ts +28 -0
- package/packages/pi-tui/dist/kill-ring.d.ts.map +1 -0
- package/packages/pi-tui/dist/kill-ring.js +46 -0
- package/packages/pi-tui/dist/kill-ring.js.map +1 -0
- package/packages/pi-tui/dist/overlay-layout.d.ts +55 -0
- package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -0
- package/packages/pi-tui/dist/overlay-layout.js +314 -0
- package/packages/pi-tui/dist/overlay-layout.js.map +1 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts +55 -0
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -0
- package/packages/pi-tui/dist/stdin-buffer.js +342 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -0
- package/packages/pi-tui/dist/style.d.ts +52 -0
- package/packages/pi-tui/dist/style.d.ts.map +1 -0
- package/packages/pi-tui/dist/style.js +219 -0
- package/packages/pi-tui/dist/style.js.map +1 -0
- package/packages/pi-tui/dist/terminal-image.d.ts +68 -0
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -0
- package/packages/pi-tui/dist/terminal-image.js +181 -0
- package/packages/pi-tui/dist/terminal-image.js.map +1 -0
- package/packages/pi-tui/dist/terminal.d.ts +89 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -0
- package/packages/pi-tui/dist/terminal.js +295 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -0
- package/packages/pi-tui/dist/tui.d.ts +213 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -0
- package/packages/pi-tui/dist/tui.js +978 -0
- package/packages/pi-tui/dist/tui.js.map +1 -0
- package/packages/pi-tui/dist/undo-stack.d.ts +17 -0
- package/packages/pi-tui/dist/undo-stack.d.ts.map +1 -0
- package/packages/pi-tui/dist/undo-stack.js +27 -0
- package/packages/pi-tui/dist/undo-stack.js.map +1 -0
- package/packages/pi-tui/dist/utils.d.ts +72 -0
- package/packages/pi-tui/dist/utils.d.ts.map +1 -0
- package/packages/pi-tui/dist/utils.js +120 -0
- package/packages/pi-tui/dist/utils.js.map +1 -0
- package/packages/pi-tui/package.json +35 -0
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +264 -0
- package/packages/pi-tui/src/__tests__/fuzzy.test.ts +120 -0
- package/packages/pi-tui/src/__tests__/keys.test.ts +21 -0
- package/packages/pi-tui/src/__tests__/loader.test.ts +30 -0
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +266 -0
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +99 -0
- package/packages/pi-tui/src/__tests__/style.test.ts +156 -0
- package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
- package/packages/pi-tui/src/__tests__/tui.test.ts +377 -0
- package/packages/pi-tui/src/__tests__/utils.test.ts +22 -0
- package/packages/pi-tui/src/autocomplete.ts +675 -0
- package/packages/pi-tui/src/components/__tests__/box.test.ts +25 -0
- package/packages/pi-tui/src/components/__tests__/cancellable-loader.test.ts +45 -0
- package/packages/pi-tui/src/components/__tests__/editor.test.ts +119 -0
- package/packages/pi-tui/src/components/__tests__/input.test.ts +111 -0
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +122 -0
- package/packages/pi-tui/src/components/__tests__/markdown-list.test.ts +40 -0
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +82 -0
- package/packages/pi-tui/src/components/__tests__/select-list.test.ts +70 -0
- package/packages/pi-tui/src/components/__tests__/truncated-text.test.ts +17 -0
- package/packages/pi-tui/src/components/box.ts +150 -0
- package/packages/pi-tui/src/components/cancellable-loader.ts +42 -0
- package/packages/pi-tui/src/components/editor.ts +2196 -0
- package/packages/pi-tui/src/components/image.test.ts +41 -0
- package/packages/pi-tui/src/components/image.ts +131 -0
- package/packages/pi-tui/src/components/input.ts +558 -0
- package/packages/pi-tui/src/components/loader.ts +83 -0
- package/packages/pi-tui/src/components/markdown.ts +842 -0
- package/packages/pi-tui/src/components/select-list.ts +194 -0
- package/packages/pi-tui/src/components/settings-list.ts +251 -0
- package/packages/pi-tui/src/components/spacer.ts +28 -0
- package/packages/pi-tui/src/components/text.ts +107 -0
- package/packages/pi-tui/src/components/truncated-text.ts +72 -0
- package/packages/pi-tui/src/editor-component.ts +77 -0
- package/packages/pi-tui/src/fuzzy.ts +138 -0
- package/packages/pi-tui/src/index.ts +98 -0
- package/packages/pi-tui/src/keybindings.ts +189 -0
- package/packages/pi-tui/src/keys.ts +1196 -0
- package/packages/pi-tui/src/kill-ring.ts +46 -0
- package/packages/pi-tui/src/overlay-layout.ts +408 -0
- package/packages/pi-tui/src/stdin-buffer.ts +419 -0
- package/packages/pi-tui/src/style.ts +295 -0
- package/packages/pi-tui/src/terminal-image.ts +260 -0
- package/packages/pi-tui/src/terminal.ts +377 -0
- package/packages/pi-tui/src/tui.ts +1182 -0
- package/packages/pi-tui/src/undo-stack.ts +28 -0
- package/packages/pi-tui/src/utils.ts +154 -0
- package/packages/pi-tui/tsconfig.json +28 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
- package/packages/rpc-client/README.md +132 -0
- package/packages/rpc-client/examples/basic-usage.ts +13 -0
- package/packages/rpc-client/package.json +42 -0
- package/packages/rpc-client/src/index.ts +10 -0
- package/packages/rpc-client/src/jsonl.ts +64 -0
- package/packages/rpc-client/src/rpc-client.test.ts +625 -0
- package/packages/rpc-client/src/rpc-client.ts +663 -0
- package/packages/rpc-client/src/rpc-types.ts +4 -0
- package/packages/rpc-client/tsconfig.examples.json +17 -0
- package/packages/rpc-client/tsconfig.json +25 -0
- package/pkg/dist/core/export-html/template.css +971 -0
- package/pkg/dist/core/export-html/template.html +54 -0
- package/pkg/dist/core/export-html/template.js +1583 -0
- package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
- package/pkg/package.json +8 -0
- package/scripts/ensure-workspace-builds.cjs +123 -0
- package/scripts/install.js +526 -0
- package/scripts/lib/workspace-manifest.cjs +86 -0
- package/scripts/link-workspace-packages.cjs +82 -0
- package/scripts/postinstall.js +11 -0
- package/src/resources/GSD-WORKFLOW.md +664 -0
- package/src/resources/agents/debugger.md +58 -0
- package/src/resources/agents/doc-writer.md +43 -0
- package/src/resources/agents/git-ops.md +56 -0
- package/src/resources/agents/javascript-pro.md +55 -0
- package/src/resources/agents/planner.md +55 -0
- package/src/resources/agents/refactorer.md +47 -0
- package/src/resources/agents/researcher.md +29 -0
- package/src/resources/agents/reviewer.md +48 -0
- package/src/resources/agents/scout.md +56 -0
- package/src/resources/agents/security.md +59 -0
- package/src/resources/agents/tester.md +50 -0
- package/src/resources/agents/typescript-pro.md +61 -0
- package/src/resources/agents/worker.md +31 -0
- package/src/resources/extensions/ask-user-questions.ts +478 -0
- package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
- package/src/resources/extensions/async-jobs/async-bash-tool.ts +263 -0
- package/src/resources/extensions/async-jobs/await-tool.test.ts +200 -0
- package/src/resources/extensions/async-jobs/await-tool.ts +136 -0
- package/src/resources/extensions/async-jobs/cancel-job-tool.ts +35 -0
- package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
- package/src/resources/extensions/async-jobs/index.ts +153 -0
- package/src/resources/extensions/async-jobs/job-manager.ts +242 -0
- package/src/resources/extensions/aws-auth/index.ts +144 -0
- package/src/resources/extensions/bg-shell/bg-shell-command.ts +219 -0
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +413 -0
- package/src/resources/extensions/bg-shell/bg-shell-tool.ts +985 -0
- package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
- package/src/resources/extensions/bg-shell/index.ts +54 -0
- package/src/resources/extensions/bg-shell/interaction.ts +200 -0
- package/src/resources/extensions/bg-shell/output-formatter.ts +262 -0
- package/src/resources/extensions/bg-shell/overlay.ts +441 -0
- package/src/resources/extensions/bg-shell/process-manager.ts +469 -0
- package/src/resources/extensions/bg-shell/readiness-detector.ts +126 -0
- package/src/resources/extensions/bg-shell/types.ts +291 -0
- package/src/resources/extensions/bg-shell/utilities.ts +93 -0
- package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
- package/src/resources/extensions/browser-tools/capture.ts +229 -0
- package/src/resources/extensions/browser-tools/core.ts +1196 -0
- package/src/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
- package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
- package/src/resources/extensions/browser-tools/index.ts +163 -0
- package/src/resources/extensions/browser-tools/lifecycle.ts +270 -0
- package/src/resources/extensions/browser-tools/package.json +24 -0
- package/src/resources/extensions/browser-tools/refs.ts +264 -0
- package/src/resources/extensions/browser-tools/settle.ts +197 -0
- package/src/resources/extensions/browser-tools/state.ts +408 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
- package/src/resources/extensions/browser-tools/tools/action-cache.ts +216 -0
- package/src/resources/extensions/browser-tools/tools/assertions.ts +342 -0
- package/src/resources/extensions/browser-tools/tools/codegen.ts +274 -0
- package/src/resources/extensions/browser-tools/tools/device.ts +183 -0
- package/src/resources/extensions/browser-tools/tools/extract.ts +229 -0
- package/src/resources/extensions/browser-tools/tools/forms.ts +805 -0
- package/src/resources/extensions/browser-tools/tools/injection-detect.ts +221 -0
- package/src/resources/extensions/browser-tools/tools/inspection.ts +492 -0
- package/src/resources/extensions/browser-tools/tools/intent.ts +629 -0
- package/src/resources/extensions/browser-tools/tools/interaction.ts +865 -0
- package/src/resources/extensions/browser-tools/tools/navigation.ts +232 -0
- package/src/resources/extensions/browser-tools/tools/network-mock.ts +244 -0
- package/src/resources/extensions/browser-tools/tools/pages.ts +303 -0
- package/src/resources/extensions/browser-tools/tools/pdf.ts +92 -0
- package/src/resources/extensions/browser-tools/tools/refs.ts +541 -0
- package/src/resources/extensions/browser-tools/tools/screenshot.ts +102 -0
- package/src/resources/extensions/browser-tools/tools/session.ts +400 -0
- package/src/resources/extensions/browser-tools/tools/state-persistence.ts +202 -0
- package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
- package/src/resources/extensions/browser-tools/tools/visual-diff.ts +209 -0
- package/src/resources/extensions/browser-tools/tools/wait.ts +247 -0
- package/src/resources/extensions/browser-tools/tools/zoom.ts +105 -0
- package/src/resources/extensions/browser-tools/utils.ts +660 -0
- package/src/resources/extensions/claude-code-cli/index.ts +28 -0
- package/src/resources/extensions/claude-code-cli/models.ts +51 -0
- package/src/resources/extensions/claude-code-cli/package.json +11 -0
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +305 -0
- package/src/resources/extensions/claude-code-cli/readiness.ts +242 -0
- package/src/resources/extensions/claude-code-cli/sdk-types.ts +149 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1981 -0
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +256 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2380 -0
- package/src/resources/extensions/cmux/index.ts +479 -0
- package/src/resources/extensions/cmux/package.json +7 -0
- package/src/resources/extensions/context7/extension-manifest.json +12 -0
- package/src/resources/extensions/context7/index.ts +435 -0
- package/src/resources/extensions/context7/package.json +11 -0
- package/src/resources/extensions/get-secrets-from-user.ts +608 -0
- package/src/resources/extensions/github-sync/cli.ts +367 -0
- package/src/resources/extensions/github-sync/index.ts +93 -0
- package/src/resources/extensions/github-sync/mapping.ts +81 -0
- package/src/resources/extensions/github-sync/sync.ts +594 -0
- package/src/resources/extensions/github-sync/templates.ts +339 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +89 -0
- package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +43 -0
- package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
- package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
- package/src/resources/extensions/github-sync/tests/sync-source.test.ts +14 -0
- package/src/resources/extensions/github-sync/tests/templates.test.ts +209 -0
- package/src/resources/extensions/github-sync/types.ts +47 -0
- package/src/resources/extensions/google-search/extension-manifest.json +13 -0
- package/src/resources/extensions/google-search/index.ts +6 -0
- package/src/resources/extensions/google-search/package.json +9 -0
- package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
- package/src/resources/extensions/gsd/activity-log.ts +184 -0
- package/src/resources/extensions/gsd/atomic-write.ts +185 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +159 -0
- package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +72 -0
- package/src/resources/extensions/gsd/auto/detect-stuck.ts +138 -0
- package/src/resources/extensions/gsd/auto/finalize-timeout.ts +49 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +92 -0
- package/src/resources/extensions/gsd/auto/lease-conflict-notice.ts +62 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +302 -0
- package/src/resources/extensions/gsd/auto/loop.ts +1448 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +417 -0
- package/src/resources/extensions/gsd/auto/phases.ts +3014 -0
- package/src/resources/extensions/gsd/auto/resolve.ts +176 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +306 -0
- package/src/resources/extensions/gsd/auto/session.ts +427 -0
- package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
- package/src/resources/extensions/gsd/auto/types.ts +130 -0
- package/src/resources/extensions/gsd/auto/unit-runner-events.ts +19 -0
- package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.ts +28 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-iteration.ts +52 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.ts +58 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.ts +71 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-retry.ts +90 -0
- package/src/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.ts +50 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +179 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-ledger.ts +45 -0
- package/src/resources/extensions/gsd/auto/workflow-iteration-completion.ts +26 -0
- package/src/resources/extensions/gsd/auto/workflow-journal-reporter.ts +33 -0
- package/src/resources/extensions/gsd/auto/workflow-kernel.ts +542 -0
- package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +71 -0
- package/src/resources/extensions/gsd/auto/workflow-phase-reporter.ts +22 -0
- package/src/resources/extensions/gsd/auto/workflow-session-lock.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-iteration.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-sidecar-queue.ts +46 -0
- package/src/resources/extensions/gsd/auto/workflow-turn-reporter.ts +68 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +89 -0
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +51 -0
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +218 -0
- package/src/resources/extensions/gsd/auto-budget.ts +57 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +1239 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +311 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +1827 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +755 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +2375 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +4108 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +1217 -0
- package/src/resources/extensions/gsd/auto-runtime-state.ts +63 -0
- package/src/resources/extensions/gsd/auto-start.ts +1561 -0
- package/src/resources/extensions/gsd/auto-status-message.ts +45 -0
- package/src/resources/extensions/gsd/auto-supervisor.ts +86 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +308 -0
- package/src/resources/extensions/gsd/auto-timers.ts +366 -0
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +156 -0
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +138 -0
- package/src/resources/extensions/gsd/auto-utils.ts +25 -0
- package/src/resources/extensions/gsd/auto-verification.ts +955 -0
- package/src/resources/extensions/gsd/auto-worktree-repair.ts +194 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +2570 -0
- package/src/resources/extensions/gsd/auto.ts +3167 -0
- package/src/resources/extensions/gsd/blocked-models.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +685 -0
- package/src/resources/extensions/gsd/bootstrap/crash-log.ts +32 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1408 -0
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +144 -0
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +123 -0
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +67 -0
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +166 -0
- package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +61 -0
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +68 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +154 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +1203 -0
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +101 -0
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +61 -0
- package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +32 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +770 -0
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
- package/src/resources/extensions/gsd/bootstrap/tests/write-gate-shouldblock-basepath.test.ts +97 -0
- package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +103 -0
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1059 -0
- package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
- package/src/resources/extensions/gsd/browser-evidence.ts +29 -0
- package/src/resources/extensions/gsd/cache.ts +40 -0
- package/src/resources/extensions/gsd/captures.ts +571 -0
- package/src/resources/extensions/gsd/changelog.ts +213 -0
- package/src/resources/extensions/gsd/claude-import.ts +705 -0
- package/src/resources/extensions/gsd/clean-root-preflight.ts +564 -0
- package/src/resources/extensions/gsd/closeout-recovery.ts +290 -0
- package/src/resources/extensions/gsd/codebase-generator.ts +616 -0
- package/src/resources/extensions/gsd/collision-diagnostics.ts +332 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +577 -0
- package/src/resources/extensions/gsd/commands/context.ts +159 -0
- package/src/resources/extensions/gsd/commands/dispatcher.ts +101 -0
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +179 -0
- package/src/resources/extensions/gsd/commands/handlers/core.ts +597 -0
- package/src/resources/extensions/gsd/commands/handlers/escalate.ts +216 -0
- package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +144 -0
- package/src/resources/extensions/gsd/commands/handlers/onboarding.ts +196 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +359 -0
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +147 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +691 -0
- package/src/resources/extensions/gsd/commands/index.ts +20 -0
- package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
- package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
- package/src/resources/extensions/gsd/commands-bootstrap.ts +280 -0
- package/src/resources/extensions/gsd/commands-closeout.ts +109 -0
- package/src/resources/extensions/gsd/commands-cmux.ts +182 -0
- package/src/resources/extensions/gsd/commands-codebase.ts +198 -0
- package/src/resources/extensions/gsd/commands-config.ts +119 -0
- package/src/resources/extensions/gsd/commands-debug.ts +510 -0
- package/src/resources/extensions/gsd/commands-do.ts +110 -0
- package/src/resources/extensions/gsd/commands-eval-review.ts +716 -0
- package/src/resources/extensions/gsd/commands-extensions.ts +1088 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +493 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +510 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +99 -0
- package/src/resources/extensions/gsd/commands-logs.ts +537 -0
- package/src/resources/extensions/gsd/commands-maintenance.ts +544 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +402 -0
- package/src/resources/extensions/gsd/commands-memory.ts +551 -0
- package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1848 -0
- package/src/resources/extensions/gsd/commands-rate.ts +55 -0
- package/src/resources/extensions/gsd/commands-scan.ts +126 -0
- package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
- package/src/resources/extensions/gsd/commands-ship.ts +292 -0
- package/src/resources/extensions/gsd/commands-verdict.ts +229 -0
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +684 -0
- package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
- package/src/resources/extensions/gsd/commands.ts +17 -0
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +331 -0
- package/src/resources/extensions/gsd/component-loader.ts +592 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/config-overlay.ts +331 -0
- package/src/resources/extensions/gsd/constants.ts +69 -0
- package/src/resources/extensions/gsd/context-budget.ts +309 -0
- package/src/resources/extensions/gsd/context-injector.ts +100 -0
- package/src/resources/extensions/gsd/context-masker.ts +74 -0
- package/src/resources/extensions/gsd/context-store.ts +497 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +427 -0
- package/src/resources/extensions/gsd/custom-execution-policy.ts +74 -0
- package/src/resources/extensions/gsd/custom-verification.ts +183 -0
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +274 -0
- package/src/resources/extensions/gsd/dashboard-overlay.ts +684 -0
- package/src/resources/extensions/gsd/db/auto-workers.ts +310 -0
- package/src/resources/extensions/gsd/db/command-queue.ts +149 -0
- package/src/resources/extensions/gsd/db/milestone-leases.ts +300 -0
- package/src/resources/extensions/gsd/db/runtime-kv.ts +127 -0
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +554 -0
- package/src/resources/extensions/gsd/db-adapter.ts +75 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +387 -0
- package/src/resources/extensions/gsd/db-connection-cache.ts +45 -0
- package/src/resources/extensions/gsd/db-coordination-schema.ts +109 -0
- package/src/resources/extensions/gsd/db-decision-requirement-rows.ts +77 -0
- package/src/resources/extensions/gsd/db-gate-rows.ts +19 -0
- package/src/resources/extensions/gsd/db-lightweight-query-rows.ts +50 -0
- package/src/resources/extensions/gsd/db-memory-fts-schema.ts +66 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +34 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +464 -0
- package/src/resources/extensions/gsd/db-milestone-artifact-rows.ts +70 -0
- package/src/resources/extensions/gsd/db-open-state.ts +47 -0
- package/src/resources/extensions/gsd/db-provider.ts +148 -0
- package/src/resources/extensions/gsd/db-runtime-kv-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +33 -0
- package/src/resources/extensions/gsd/db-task-slice-rows.ts +150 -0
- package/src/resources/extensions/gsd/db-transaction.ts +76 -0
- package/src/resources/extensions/gsd/db-verification-evidence-rows.ts +14 -0
- package/src/resources/extensions/gsd/db-verification-evidence-schema.ts +22 -0
- package/src/resources/extensions/gsd/db-writer.ts +966 -0
- package/src/resources/extensions/gsd/debug-logger.ts +178 -0
- package/src/resources/extensions/gsd/debug-session-store.ts +377 -0
- package/src/resources/extensions/gsd/deep-project-setup-policy.ts +257 -0
- package/src/resources/extensions/gsd/definition-io.ts +18 -0
- package/src/resources/extensions/gsd/definition-loader.ts +469 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
- package/src/resources/extensions/gsd/detection.ts +1339 -0
- package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
- package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
- package/src/resources/extensions/gsd/diff-context.ts +214 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +211 -0
- package/src/resources/extensions/gsd/docs/COORDINATION.md +42 -0
- package/src/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +755 -0
- package/src/resources/extensions/gsd/doctor-checks.ts +5 -0
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +196 -0
- package/src/resources/extensions/gsd/doctor-environment.ts +643 -0
- package/src/resources/extensions/gsd/doctor-format.ts +99 -0
- package/src/resources/extensions/gsd/doctor-git-checks.ts +622 -0
- package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
- package/src/resources/extensions/gsd/doctor-proactive.ts +488 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +523 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +793 -0
- package/src/resources/extensions/gsd/doctor-types.ts +134 -0
- package/src/resources/extensions/gsd/doctor.ts +802 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +233 -0
- package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
- package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
- package/src/resources/extensions/gsd/engine-types.ts +71 -0
- package/src/resources/extensions/gsd/env-utils.ts +31 -0
- package/src/resources/extensions/gsd/error-classifier.ts +188 -0
- package/src/resources/extensions/gsd/error-utils.ts +6 -0
- package/src/resources/extensions/gsd/errors.ts +29 -0
- package/src/resources/extensions/gsd/escalation.ts +369 -0
- package/src/resources/extensions/gsd/eval-review-schema.ts +243 -0
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +333 -0
- package/src/resources/extensions/gsd/execution-policy.ts +43 -0
- package/src/resources/extensions/gsd/exit-command.ts +30 -0
- package/src/resources/extensions/gsd/export-html.ts +1008 -0
- package/src/resources/extensions/gsd/export.ts +318 -0
- package/src/resources/extensions/gsd/extension-manifest.json +33 -0
- package/src/resources/extensions/gsd/file-lock.ts +132 -0
- package/src/resources/extensions/gsd/files.ts +1009 -0
- package/src/resources/extensions/gsd/forensics.ts +1342 -0
- package/src/resources/extensions/gsd/fresh-run-ui.ts +43 -0
- package/src/resources/extensions/gsd/gate-registry.ts +251 -0
- package/src/resources/extensions/gsd/git-conflict-state.ts +23 -0
- package/src/resources/extensions/gsd/git-constants.ts +41 -0
- package/src/resources/extensions/gsd/git-self-heal.ts +158 -0
- package/src/resources/extensions/gsd/git-service.ts +1412 -0
- package/src/resources/extensions/gsd/gitignore.ts +336 -0
- package/src/resources/extensions/gsd/graph-context.ts +212 -0
- package/src/resources/extensions/gsd/graph.ts +349 -0
- package/src/resources/extensions/gsd/gsd-command-home.ts +209 -0
- package/src/resources/extensions/gsd/gsd-db.ts +3190 -0
- package/src/resources/extensions/gsd/gsd-home.ts +30 -0
- package/src/resources/extensions/gsd/guided-flow-queue.ts +443 -0
- package/src/resources/extensions/gsd/guided-flow.ts +2887 -0
- package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
- package/src/resources/extensions/gsd/health-widget-core.ts +140 -0
- package/src/resources/extensions/gsd/health-widget.ts +148 -0
- package/src/resources/extensions/gsd/history.ts +144 -0
- package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
- package/src/resources/extensions/gsd/index.ts +37 -0
- package/src/resources/extensions/gsd/init-wizard.ts +704 -0
- package/src/resources/extensions/gsd/interrupted-session.ts +269 -0
- package/src/resources/extensions/gsd/journal.ts +218 -0
- package/src/resources/extensions/gsd/json-persistence.ts +78 -0
- package/src/resources/extensions/gsd/jsonl-utils.ts +21 -0
- package/src/resources/extensions/gsd/key-manager.ts +1018 -0
- package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
- package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
- package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
- package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
- package/src/resources/extensions/gsd/legacy-telemetry.ts +99 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +982 -0
- package/src/resources/extensions/gsd/marketplace-discovery.ts +508 -0
- package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
- package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
- package/src/resources/extensions/gsd/md-importer.ts +748 -0
- package/src/resources/extensions/gsd/memory-backfill.ts +212 -0
- package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
- package/src/resources/extensions/gsd/memory-embeddings.ts +235 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +434 -0
- package/src/resources/extensions/gsd/memory-ingest.ts +286 -0
- package/src/resources/extensions/gsd/memory-relations.ts +240 -0
- package/src/resources/extensions/gsd/memory-source-store.ts +138 -0
- package/src/resources/extensions/gsd/memory-store.ts +909 -0
- package/src/resources/extensions/gsd/metrics.ts +1040 -0
- package/src/resources/extensions/gsd/migrate/audit.ts +219 -0
- package/src/resources/extensions/gsd/migrate/command.ts +341 -0
- package/src/resources/extensions/gsd/migrate/index.ts +44 -0
- package/src/resources/extensions/gsd/migrate/parser.ts +323 -0
- package/src/resources/extensions/gsd/migrate/parsers.ts +676 -0
- package/src/resources/extensions/gsd/migrate/preview.ts +58 -0
- package/src/resources/extensions/gsd/migrate/safety.ts +149 -0
- package/src/resources/extensions/gsd/migrate/transformer.ts +411 -0
- package/src/resources/extensions/gsd/migrate/types.ts +370 -0
- package/src/resources/extensions/gsd/migrate/validator.ts +55 -0
- package/src/resources/extensions/gsd/migrate/writer.ts +592 -0
- package/src/resources/extensions/gsd/migrate-external.ts +215 -0
- package/src/resources/extensions/gsd/migration-auto-check.ts +121 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +193 -0
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/milestone-id-utils.ts +32 -0
- package/src/resources/extensions/gsd/milestone-ids.ts +136 -0
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +373 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +53 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +89 -0
- package/src/resources/extensions/gsd/model-router.ts +844 -0
- package/src/resources/extensions/gsd/namespaced-registry.ts +467 -0
- package/src/resources/extensions/gsd/namespaced-resolver.ts +307 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +1447 -0
- package/src/resources/extensions/gsd/native-parser-bridge.ts +267 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +322 -0
- package/src/resources/extensions/gsd/notification-store.ts +342 -0
- package/src/resources/extensions/gsd/notification-widget.ts +69 -0
- package/src/resources/extensions/gsd/notifications.ts +153 -0
- package/src/resources/extensions/gsd/observability-validator.ts +456 -0
- package/src/resources/extensions/gsd/onboarding-state.ts +146 -0
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/package.json +11 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +248 -0
- package/src/resources/extensions/gsd/parallel-merge.ts +270 -0
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +507 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +1077 -0
- package/src/resources/extensions/gsd/parsers-legacy.ts +292 -0
- package/src/resources/extensions/gsd/paths.ts +722 -0
- package/src/resources/extensions/gsd/pending-auto-start.ts +81 -0
- package/src/resources/extensions/gsd/phase-anchor.ts +71 -0
- package/src/resources/extensions/gsd/planning-depth.ts +137 -0
- package/src/resources/extensions/gsd/planning-path-scope.ts +45 -0
- package/src/resources/extensions/gsd/plugin-importer.ts +411 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +665 -0
- package/src/resources/extensions/gsd/post-unit-hooks.ts +86 -0
- package/src/resources/extensions/gsd/pr-evidence.ts +182 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +890 -0
- package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
- package/src/resources/extensions/gsd/preferences-models.ts +572 -0
- package/src/resources/extensions/gsd/preferences-skills.ts +147 -0
- package/src/resources/extensions/gsd/preferences-types.ts +579 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +1453 -0
- package/src/resources/extensions/gsd/preferences.ts +697 -0
- package/src/resources/extensions/gsd/preparation.ts +1419 -0
- package/src/resources/extensions/gsd/process-task-path.ts +81 -0
- package/src/resources/extensions/gsd/progress-score.ts +161 -0
- package/src/resources/extensions/gsd/project-research-policy.ts +259 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +217 -0
- package/src/resources/extensions/gsd/prompt-loader.ts +248 -0
- package/src/resources/extensions/gsd/prompt-ordering.ts +200 -0
- package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
- package/src/resources/extensions/gsd/prompts/add-tests.md +36 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +91 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +49 -0
- package/src/resources/extensions/gsd/prompts/debug-diagnose.md +27 -0
- package/src/resources/extensions/gsd/prompts/debug-session-manager.md +80 -0
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +252 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +368 -0
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +31 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +73 -0
- package/src/resources/extensions/gsd/prompts/forensics.md +155 -0
- package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +116 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +113 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +99 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +74 -0
- package/src/resources/extensions/gsd/prompts/guided-research-decision.md +70 -0
- package/src/resources/extensions/gsd/prompts/guided-research-project.md +102 -0
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +15 -0
- package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
- package/src/resources/extensions/gsd/prompts/guided-workflow-preferences.md +68 -0
- package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +28 -0
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +114 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +55 -0
- package/src/resources/extensions/gsd/prompts/queue.md +128 -0
- package/src/resources/extensions/gsd/prompts/quick-task.md +40 -0
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +68 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +79 -0
- package/src/resources/extensions/gsd/prompts/replan-slice.md +39 -0
- package/src/resources/extensions/gsd/prompts/research-milestone.md +47 -0
- package/src/resources/extensions/gsd/prompts/research-slice.md +58 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +95 -0
- package/src/resources/extensions/gsd/prompts/review-migration.md +66 -0
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +33 -0
- package/src/resources/extensions/gsd/prompts/run-uat.md +89 -0
- package/src/resources/extensions/gsd/prompts/scan.md +79 -0
- package/src/resources/extensions/gsd/prompts/system.md +180 -0
- package/src/resources/extensions/gsd/prompts/triage-captures.md +68 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +88 -0
- package/src/resources/extensions/gsd/prompts/workflow-oneshot.md +26 -0
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/prompts/worktree-merge.md +125 -0
- package/src/resources/extensions/gsd/provider-error-pause.ts +49 -0
- package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
- package/src/resources/extensions/gsd/python-resolver.ts +76 -0
- package/src/resources/extensions/gsd/queue-order.ts +235 -0
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +295 -0
- package/src/resources/extensions/gsd/quick.ts +297 -0
- package/src/resources/extensions/gsd/reactive-graph.ts +337 -0
- package/src/resources/extensions/gsd/recovery-classification.ts +139 -0
- package/src/resources/extensions/gsd/repo-identity.ts +683 -0
- package/src/resources/extensions/gsd/reports.ts +505 -0
- package/src/resources/extensions/gsd/repository-registry.ts +108 -0
- package/src/resources/extensions/gsd/rethink.ts +164 -0
- package/src/resources/extensions/gsd/roadmap-mutations.ts +134 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +294 -0
- package/src/resources/extensions/gsd/root-write-leak-guard.ts +101 -0
- package/src/resources/extensions/gsd/routing-history.ts +286 -0
- package/src/resources/extensions/gsd/rule-registry.ts +599 -0
- package/src/resources/extensions/gsd/rule-types.ts +68 -0
- package/src/resources/extensions/gsd/run-manager.ts +214 -0
- package/src/resources/extensions/gsd/safe-fs.ts +48 -0
- package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +265 -0
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +155 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +124 -0
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +130 -0
- package/src/resources/extensions/gsd/safety/safety-harness.ts +114 -0
- package/src/resources/extensions/gsd/schemas/__fixtures__/valid-project.md +26 -0
- package/src/resources/extensions/gsd/schemas/__fixtures__/valid-requirements.md +57 -0
- package/src/resources/extensions/gsd/schemas/__fixtures__/valid-roadmap.md +19 -0
- package/src/resources/extensions/gsd/schemas/parsers.ts +346 -0
- package/src/resources/extensions/gsd/schemas/validate.ts +452 -0
- package/src/resources/extensions/gsd/service-tier.ts +199 -0
- package/src/resources/extensions/gsd/session-forensics.ts +580 -0
- package/src/resources/extensions/gsd/session-lock.ts +732 -0
- package/src/resources/extensions/gsd/session-model-override.ts +36 -0
- package/src/resources/extensions/gsd/session-status-io.ts +179 -0
- package/src/resources/extensions/gsd/setup-catalog.ts +105 -0
- package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +1088 -0
- package/src/resources/extensions/gsd/skill-discovery.ts +157 -0
- package/src/resources/extensions/gsd/skill-health.ts +422 -0
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +141 -0
- package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +242 -0
- package/src/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +83 -0
- package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +64 -0
- package/src/resources/extensions/gsd/skills/gsd-headless/references/multi-session.md +176 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +411 -0
- package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
- package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +913 -0
- package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +417 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +66 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +101 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
- package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
- package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +65 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
- package/src/resources/extensions/gsd/state-reconciliation.ts +25 -0
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +1730 -0
- package/src/resources/extensions/gsd/status-guards.ts +41 -0
- package/src/resources/extensions/gsd/structured-data-formatter.ts +146 -0
- package/src/resources/extensions/gsd/sync-lock.ts +152 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +101 -0
- package/src/resources/extensions/gsd/templates/context.md +108 -0
- package/src/resources/extensions/gsd/templates/decisions.md +8 -0
- package/src/resources/extensions/gsd/templates/knowledge.md +19 -0
- package/src/resources/extensions/gsd/templates/milestone-summary.md +81 -0
- package/src/resources/extensions/gsd/templates/milestone-validation.md +74 -0
- package/src/resources/extensions/gsd/templates/plan.md +152 -0
- package/src/resources/extensions/gsd/templates/project.md +41 -0
- package/src/resources/extensions/gsd/templates/reassessment.md +29 -0
- package/src/resources/extensions/gsd/templates/requirements.md +81 -0
- package/src/resources/extensions/gsd/templates/research.md +79 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +131 -0
- package/src/resources/extensions/gsd/templates/runtime.md +21 -0
- package/src/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
- package/src/resources/extensions/gsd/templates/slice-context.md +58 -0
- package/src/resources/extensions/gsd/templates/slice-summary.md +108 -0
- package/src/resources/extensions/gsd/templates/state.md +17 -0
- package/src/resources/extensions/gsd/templates/task-plan.md +95 -0
- package/src/resources/extensions/gsd/templates/task-summary.md +66 -0
- package/src/resources/extensions/gsd/templates/uat.md +54 -0
- package/src/resources/extensions/gsd/tests/active-milestone-id-guard.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/activity-log.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +296 -0
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/artifact-validators.test.ts +524 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/ask-user-questions-dedup.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/atomic-write.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +807 -0
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +457 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/auto-loop-symlink-worktree.test.ts +190 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +5503 -0
- package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +479 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +1300 -0
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +759 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +390 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +218 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/auto-prompts-fallback.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1773 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/auto-start-validation-block.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/auto-status-message.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +70 -0
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/auto-workers.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +143 -0
- package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +290 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/capability-router.test.ts +371 -0
- package/src/resources/extensions/gsd/tests/captures.test.ts +524 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/claude-import-marketplace-discovery.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +350 -0
- package/src/resources/extensions/gsd/tests/claude-skill-dirs.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +509 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/cmux.test.ts +333 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +669 -0
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +506 -0
- package/src/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/command-queue.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +188 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/commands-do.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +612 -0
- package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +663 -0
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
- package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/commands-scan.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/commands-ship-eval-warn.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +439 -0
- package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +311 -0
- package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +366 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +743 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
- package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +247 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +556 -0
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +513 -0
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +582 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +389 -0
- package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +715 -0
- package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +185 -0
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +294 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +331 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +709 -0
- package/src/resources/extensions/gsd/tests/current-directory-root-homedir-fallback.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +902 -0
- package/src/resources/extensions/gsd/tests/custom-verification.test.ts +415 -0
- package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +483 -0
- package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +360 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/db-adapter.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/db-base-schema.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/db-connection-cache.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/db-coordination-schema.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/db-decision-requirement-rows.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/db-gate-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-lightweight-query-rows.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
- package/src/resources/extensions/gsd/tests/db-migration-steps.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-milestone-artifact-rows.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/db-open-state.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/db-provider.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/db-runtime-kv-schema.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/db-verification-evidence-schema.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +980 -0
- package/src/resources/extensions/gsd/tests/debug-command-handler.test.ts +942 -0
- package/src/resources/extensions/gsd/tests/debug-command-lifecycle.integration.test.ts +1229 -0
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/debug-session-store.test.ts +565 -0
- package/src/resources/extensions/gsd/tests/decision-scope-cascade.test.ts +370 -0
- package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
- package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/deep-mode-integration.test.ts +406 -0
- package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +923 -0
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +1705 -0
- package/src/resources/extensions/gsd/tests/deep-project-setup-policy.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +762 -0
- package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +514 -0
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +1388 -0
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +641 -0
- package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +558 -0
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +1049 -0
- package/src/resources/extensions/gsd/tests/detect-stuck-respects-retry.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/detection.test.ts +1367 -0
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +314 -0
- package/src/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-cold-start-db-open.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/discuss-command-targeting-5471.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/discuss-headless-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +276 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +446 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +279 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +358 -0
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
- package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +828 -0
- package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +149 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
- package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +531 -0
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +530 -0
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/escalation.test.ts +819 -0
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/eval-review-schema.test.ts +282 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +407 -0
- package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/export-html-all.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +387 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/file-lock.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +215 -0
- package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +298 -0
- package/src/resources/extensions/gsd/tests/fresh-run-ui.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
- package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
- package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +216 -0
- package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
- package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1210 -0
- package/src/resources/extensions/gsd/tests/gsd-home.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
- package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +149 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +445 -0
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +43 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-requirements-prompt-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +350 -0
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/headless-query.test.ts +184 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +251 -0
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +189 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +239 -0
- package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/integration/atomic-task-closeout.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/integration/auto-preflight.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +966 -0
- package/src/resources/extensions/gsd/tests/integration/auto-secrets-gate.test.ts +194 -0
- package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +964 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +430 -0
- package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +256 -0
- package/src/resources/extensions/gsd/tests/integration/continue-here.test.ts +281 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-completion-deferral.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-delimiter-fix.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-enhancements.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment-worktree.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment.test.ts +403 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +954 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +431 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-roadmap-summary-atomicity.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +549 -0
- package/src/resources/extensions/gsd/tests/integration/doctor.test.ts +612 -0
- package/src/resources/extensions/gsd/tests/integration/e2e-workflow-pipeline-integration.test.ts +476 -0
- package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +415 -0
- package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/integration/git-self-heal.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +2040 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/integration/headless-command.ts +534 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +474 -0
- package/src/resources/extensions/gsd/tests/integration/inherited-repo-home-dir.test.ts +191 -0
- package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +274 -0
- package/src/resources/extensions/gsd/tests/integration/integration-mixed-milestones.test.ts +539 -0
- package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +634 -0
- package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
- package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +669 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-workers-multi-milestone-e2e.test.ts +337 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/integration/plugin-importer-live.test.ts +481 -0
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/integration/queue-reorder-e2e.test.ts +335 -0
- package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +253 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +689 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1356 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +980 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +832 -0
- package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +369 -0
- package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +248 -0
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +223 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +241 -0
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +1473 -0
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/journal.test.ts +373 -0
- package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +501 -0
- package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
- package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +434 -0
- package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/lease-conflict-notice.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/legacy-component-format-telemetry.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/legacy-telemetry.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/manifest-status.test.ts +274 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1292 -0
- package/src/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
- package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +416 -0
- package/src/resources/extensions/gsd/tests/measurement.test.ts +531 -0
- package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/memory-embeddings.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/memory-ingest.test.ts +153 -0
- package/src/resources/extensions/gsd/tests/memory-leak-guards.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/memory-relations.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +460 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +327 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
- package/src/resources/extensions/gsd/tests/metrics-milestone-scope.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
- package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
- package/src/resources/extensions/gsd/tests/metrics.test.ts +519 -0
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +782 -0
- package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +651 -0
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +448 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +347 -0
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +361 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +364 -0
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +990 -0
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +278 -0
- package/src/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
- package/src/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/native-has-changes-cache.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/next-milestone-id.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +200 -0
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/notification-store.test.ts +325 -0
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/onboarding-state.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +374 -0
- package/src/resources/extensions/gsd/tests/overrides.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +330 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +273 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/parallel-milestone-isolation.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +736 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +332 -0
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +308 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +199 -0
- package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +253 -0
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +420 -0
- package/src/resources/extensions/gsd/tests/parsers.test.ts +1892 -0
- package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +404 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-boundary-map-preservation.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-rendering.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +349 -0
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +474 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +306 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +712 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/planning-depth-setter.test.ts +172 -0
- package/src/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +536 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +1065 -0
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +300 -0
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +567 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pr-evidence.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +149 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +2246 -0
- package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +708 -0
- package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +1314 -0
- package/src/resources/extensions/gsd/tests/preflight-context-draft-filter.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +222 -0
- package/src/resources/extensions/gsd/tests/process-task-path.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +620 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +277 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +677 -0
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +574 -0
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +387 -0
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/prompts-no-gitignored-test-refs.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +744 -0
- package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/python-resolver.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/quality-gates.test.ts +344 -0
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +166 -0
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/queue-prompt-rendering.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/rate-limit-model-fallback.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +511 -0
- package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +363 -0
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +728 -0
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +252 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +774 -0
- package/src/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +609 -0
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
- package/src/resources/extensions/gsd/tests/requirements.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
- package/src/resources/extensions/gsd/tests/resolve-ts.mjs +9 -0
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
- package/src/resources/extensions/gsd/tests/retry-diagnostic-reasoning.test.ts +161 -0
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/rewrite-count-persist.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
- package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +213 -0
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +399 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +464 -0
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +294 -0
- package/src/resources/extensions/gsd/tests/routing-history.test.ts +229 -0
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/runtime-kv.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +268 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +364 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/session-forensics-readonly-classification.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +166 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +379 -0
- package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +224 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +387 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +304 -0
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +239 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +182 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +130 -0
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +244 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +352 -0
- package/src/resources/extensions/gsd/tests/skill-catalog.test.ts +193 -0
- package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +144 -0
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +348 -0
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/stale-milestone-id-reservation.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +334 -0
- package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +442 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +424 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1645 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +1137 -0
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +216 -0
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +285 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +232 -0
- package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +153 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +214 -0
- package/src/resources/extensions/gsd/tests/test-utils.ts +165 -0
- package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +382 -0
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +306 -0
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +211 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +383 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +612 -0
- package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +330 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +153 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unborn-branch.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/undo.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +203 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +529 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +462 -0
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +326 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +335 -0
- package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +245 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/uok-flags.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +241 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +163 -0
- package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/update-command.test.ts +86 -0
- package/src/resources/extensions/gsd/tests/vacuous-truth-slices.test.ts +115 -0
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-directory.test.ts +269 -0
- package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +300 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +371 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +766 -0
- package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/validation.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +601 -0
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +1265 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +204 -0
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +359 -0
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +716 -0
- package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-dispatch-outcome.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-iteration.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile-outcome.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-retry.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/workflow-custom-engine-verify-outcome.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/workflow-dispatch-ledger.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/workflow-install.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/workflow-iteration-completion.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/workflow-journal-reporter.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +630 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +411 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +336 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +771 -0
- package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/workflow-phase-reporter.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/workflow-plugins.test.ts +310 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +91 -0
- package/src/resources/extensions/gsd/tests/workflow-session-lock.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-iteration.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/workflow-sidecar-queue.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +198 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1397 -0
- package/src/resources/extensions/gsd/tests/workflow-turn-reporter.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/workflow-unit-dispatch.test.ts +160 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/workspace-index.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/workspace.test.ts +196 -0
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +440 -0
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +207 -0
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +109 -0
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +181 -0
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +216 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +397 -0
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +992 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +290 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +180 -0
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/worktree-root-resolution.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/worktree-root.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +417 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +228 -0
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +85 -0
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +283 -0
- package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +206 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +304 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +476 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +188 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +726 -0
- package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +81 -0
- package/src/resources/extensions/gsd/token-counter.ts +83 -0
- package/src/resources/extensions/gsd/tool-contract.ts +82 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +273 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +568 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +473 -0
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +286 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +427 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +370 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +443 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +161 -0
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +289 -0
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +152 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +146 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +242 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/tools/skip-slice.ts +133 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +301 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +991 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +578 -0
- package/src/resources/extensions/gsd/triage-ui.ts +196 -0
- package/src/resources/extensions/gsd/tui/render-kit.ts +153 -0
- package/src/resources/extensions/gsd/types.ts +721 -0
- package/src/resources/extensions/gsd/undo.ts +465 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +285 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +796 -0
- package/src/resources/extensions/gsd/unit-id.ts +14 -0
- package/src/resources/extensions/gsd/unit-ownership.ts +275 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +267 -0
- package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +150 -0
- package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
- package/src/resources/extensions/gsd/uok/audit.ts +85 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +306 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +60 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +263 -0
- package/src/resources/extensions/gsd/uok/flags.ts +45 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +206 -0
- package/src/resources/extensions/gsd/uok/gitops.ts +80 -0
- package/src/resources/extensions/gsd/uok/kernel.ts +124 -0
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +212 -0
- package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +209 -0
- package/src/resources/extensions/gsd/uok/timeline.ts +158 -0
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/user-input-boundary.ts +166 -0
- package/src/resources/extensions/gsd/validate-directory.ts +186 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +83 -0
- package/src/resources/extensions/gsd/validation.ts +45 -0
- package/src/resources/extensions/gsd/verdict-parser.ts +110 -0
- package/src/resources/extensions/gsd/verification-evidence.ts +270 -0
- package/src/resources/extensions/gsd/verification-gate.ts +848 -0
- package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +953 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +570 -0
- package/src/resources/extensions/gsd/visualizer-views.ts +1229 -0
- package/src/resources/extensions/gsd/watch/header-renderer.ts +331 -0
- package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
- package/src/resources/extensions/gsd/workflow-dispatch.ts +106 -0
- package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
- package/src/resources/extensions/gsd/workflow-events.ts +166 -0
- package/src/resources/extensions/gsd/workflow-install.ts +422 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +381 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +260 -0
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +60 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +459 -0
- package/src/resources/extensions/gsd/workflow-migration.ts +340 -0
- package/src/resources/extensions/gsd/workflow-plugins.ts +402 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +567 -0
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +681 -0
- package/src/resources/extensions/gsd/workflow-templates/accessibility-audit.md +88 -0
- package/src/resources/extensions/gsd/workflow-templates/api-breaking-change.md +117 -0
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +88 -0
- package/src/resources/extensions/gsd/workflow-templates/changelog-gen.md +82 -0
- package/src/resources/extensions/gsd/workflow-templates/ci-bootstrap.md +144 -0
- package/src/resources/extensions/gsd/workflow-templates/dead-code.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +75 -0
- package/src/resources/extensions/gsd/workflow-templates/docs-sync.yaml +76 -0
- package/src/resources/extensions/gsd/workflow-templates/env-audit.yaml +88 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +42 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +46 -0
- package/src/resources/extensions/gsd/workflow-templates/issue-triage.md +84 -0
- package/src/resources/extensions/gsd/workflow-templates/observability-setup.md +133 -0
- package/src/resources/extensions/gsd/workflow-templates/onboarding-check.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/performance-audit.md +125 -0
- package/src/resources/extensions/gsd/workflow-templates/pr-review.md +67 -0
- package/src/resources/extensions/gsd/workflow-templates/pr-triage.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +84 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +269 -0
- package/src/resources/extensions/gsd/workflow-templates/release.md +118 -0
- package/src/resources/extensions/gsd/workflow-templates/rename-symbol.yaml +99 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +82 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +76 -0
- package/src/resources/extensions/gsd/workflow-templates/test-backfill.yaml +73 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +278 -0
- package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
- package/src/resources/extensions/gsd/workspace-index.ts +277 -0
- package/src/resources/extensions/gsd/workspace.ts +95 -0
- package/src/resources/extensions/gsd/worktree-command-bootstrap.ts +46 -0
- package/src/resources/extensions/gsd/worktree-command.ts +834 -0
- package/src/resources/extensions/gsd/worktree-health.ts +178 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +1989 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +909 -0
- package/src/resources/extensions/gsd/worktree-root.ts +182 -0
- package/src/resources/extensions/gsd/worktree-safety.ts +329 -0
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/gsd/worktree-state-projection.ts +447 -0
- package/src/resources/extensions/gsd/worktree-telemetry.ts +366 -0
- package/src/resources/extensions/gsd/worktree.ts +235 -0
- package/src/resources/extensions/gsd/write-intercept.ts +99 -0
- package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
- package/src/resources/extensions/mac-tools/index.ts +852 -0
- package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
- package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
- package/src/resources/extensions/mcp-client/auth.ts +160 -0
- package/src/resources/extensions/mcp-client/index.ts +526 -0
- package/src/resources/extensions/mcp-client/manager.ts +516 -0
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/mcp-client/tests/manager.test.ts +165 -0
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +89 -0
- package/src/resources/extensions/ollama/index.ts +158 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +186 -0
- package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +128 -0
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
- package/src/resources/extensions/ollama/ollama-client.ts +262 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +134 -0
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +215 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +287 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +258 -0
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
- package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +55 -0
- package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
- package/src/resources/extensions/ollama/types.ts +153 -0
- package/src/resources/extensions/package.json +3 -0
- package/src/resources/extensions/remote-questions/commands.ts +480 -0
- package/src/resources/extensions/remote-questions/config.ts +126 -0
- package/src/resources/extensions/remote-questions/discord-adapter.ts +148 -0
- package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
- package/src/resources/extensions/remote-questions/format.ts +315 -0
- package/src/resources/extensions/remote-questions/http-client.ts +76 -0
- package/src/resources/extensions/remote-questions/manager.ts +270 -0
- package/src/resources/extensions/remote-questions/mod.ts +16 -0
- package/src/resources/extensions/remote-questions/notify.ts +90 -0
- package/src/resources/extensions/remote-questions/remote-command.ts +437 -0
- package/src/resources/extensions/remote-questions/slack-adapter.ts +141 -0
- package/src/resources/extensions/remote-questions/status.ts +31 -0
- package/src/resources/extensions/remote-questions/store.ts +81 -0
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +231 -0
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +256 -0
- package/src/resources/extensions/remote-questions/tests/remote-answer-normalization.test.ts +92 -0
- package/src/resources/extensions/remote-questions/tests/telegram-commands.test.ts +267 -0
- package/src/resources/extensions/remote-questions/types.ts +102 -0
- package/src/resources/extensions/search-the-web/cache.ts +78 -0
- package/src/resources/extensions/search-the-web/command-search-provider.ts +105 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
- package/src/resources/extensions/search-the-web/format.ts +258 -0
- package/src/resources/extensions/search-the-web/http.ts +238 -0
- package/src/resources/extensions/search-the-web/index.ts +64 -0
- package/src/resources/extensions/search-the-web/native-search.ts +276 -0
- package/src/resources/extensions/search-the-web/provider.ts +150 -0
- package/src/resources/extensions/search-the-web/tavily.ts +116 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +589 -0
- package/src/resources/extensions/search-the-web/tool-llm-context.ts +608 -0
- package/src/resources/extensions/search-the-web/tool-search.ts +677 -0
- package/src/resources/extensions/search-the-web/url-utils.ts +144 -0
- package/src/resources/extensions/shared/cmux-events.ts +59 -0
- package/src/resources/extensions/shared/confirm-ui.ts +126 -0
- package/src/resources/extensions/shared/format-utils.ts +99 -0
- package/src/resources/extensions/shared/frontmatter.ts +117 -0
- package/src/resources/extensions/shared/gsd-phase-state.ts +95 -0
- package/src/resources/extensions/shared/html-shell.ts +412 -0
- package/src/resources/extensions/shared/interview-ui.ts +848 -0
- package/src/resources/extensions/shared/layout-utils.ts +75 -0
- package/src/resources/extensions/shared/mod.ts +31 -0
- package/src/resources/extensions/shared/next-action-ui.ts +226 -0
- package/src/resources/extensions/shared/path-display.ts +19 -0
- package/src/resources/extensions/shared/rtk-session-stats.ts +248 -0
- package/src/resources/extensions/shared/rtk-shared.ts +58 -0
- package/src/resources/extensions/shared/rtk.ts +98 -0
- package/src/resources/extensions/shared/sanitize.ts +55 -0
- package/src/resources/extensions/shared/terminal.ts +28 -0
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +161 -0
- package/src/resources/extensions/shared/tests/format-utils.test.ts +155 -0
- package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +90 -0
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +198 -0
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +185 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +144 -0
- package/src/resources/extensions/shared/tests/preview-layout.test.ts +120 -0
- package/src/resources/extensions/shared/tui.ts +11 -0
- package/src/resources/extensions/shared/ui.ts +401 -0
- package/src/resources/extensions/slash-commands/audit.ts +89 -0
- package/src/resources/extensions/slash-commands/clear.ts +10 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +311 -0
- package/src/resources/extensions/slash-commands/create-slash-command.ts +234 -0
- package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
- package/src/resources/extensions/slash-commands/index.ts +12 -0
- package/src/resources/extensions/subagent/agents.ts +166 -0
- package/src/resources/extensions/subagent/extension-manifest.json +13 -0
- package/src/resources/extensions/subagent/index.ts +1938 -0
- package/src/resources/extensions/subagent/isolation.ts +504 -0
- package/src/resources/extensions/subagent/launch.ts +131 -0
- package/src/resources/extensions/subagent/run-store.ts +218 -0
- package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
- package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
- package/src/resources/extensions/subagent/tests/model-override.test.ts +55 -0
- package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
- package/src/resources/extensions/subagent/worker-registry.ts +100 -0
- package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
- package/src/resources/extensions/ttsr/index.ts +168 -0
- package/src/resources/extensions/ttsr/rule-loader.ts +75 -0
- package/src/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
- package/src/resources/extensions/ttsr/ttsr-manager.ts +465 -0
- package/src/resources/extensions/universal-config/discovery.ts +104 -0
- package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
- package/src/resources/extensions/universal-config/format.ts +191 -0
- package/src/resources/extensions/universal-config/index.ts +120 -0
- package/src/resources/extensions/universal-config/package.json +11 -0
- package/src/resources/extensions/universal-config/scanners.ts +642 -0
- package/src/resources/extensions/universal-config/tests/discovery.test.ts +119 -0
- package/src/resources/extensions/universal-config/tests/format.test.ts +127 -0
- package/src/resources/extensions/universal-config/tests/scanners.test.ts +456 -0
- package/src/resources/extensions/universal-config/tools.ts +60 -0
- package/src/resources/extensions/universal-config/types.ts +135 -0
- package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
- package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
- package/src/resources/extensions/visual-brief/index.ts +8 -0
- package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
- package/src/resources/extensions/visual-brief/prompts.ts +183 -0
- package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
- package/src/resources/extensions/voice/extension-manifest.json +12 -0
- package/src/resources/extensions/voice/index.ts +264 -0
- package/src/resources/extensions/voice/linux-ready.ts +86 -0
- package/src/resources/extensions/voice/speech-recognizer.py +504 -0
- package/src/resources/extensions/voice/speech-recognizer.swift +154 -0
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +140 -0
- package/src/resources/skills/accessibility/SKILL.md +522 -0
- package/src/resources/skills/accessibility/references/WCAG.md +162 -0
- package/src/resources/skills/agent-browser/SKILL.md +517 -0
- package/src/resources/skills/agent-browser/references/authentication.md +202 -0
- package/src/resources/skills/agent-browser/references/commands.md +263 -0
- package/src/resources/skills/agent-browser/references/profiling.md +120 -0
- package/src/resources/skills/agent-browser/references/proxy-support.md +194 -0
- package/src/resources/skills/agent-browser/references/session-management.md +193 -0
- package/src/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
- package/src/resources/skills/agent-browser/references/video-recording.md +173 -0
- package/src/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
- package/src/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/src/resources/skills/agent-browser/templates/form-automation.sh +62 -0
- package/src/resources/skills/api-design/SKILL.md +190 -0
- package/src/resources/skills/best-practices/SKILL.md +583 -0
- package/src/resources/skills/btw/SKILL.md +42 -0
- package/src/resources/skills/code-optimizer/SKILL.md +160 -0
- package/src/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
- package/src/resources/skills/code-optimizer/references/build-compilation.md +90 -0
- package/src/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
- package/src/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
- package/src/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
- package/src/resources/skills/code-optimizer/references/config-infra.md +71 -0
- package/src/resources/skills/code-optimizer/references/data-structures.md +80 -0
- package/src/resources/skills/code-optimizer/references/database-queries.md +76 -0
- package/src/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
- package/src/resources/skills/code-optimizer/references/error-resilience.md +80 -0
- package/src/resources/skills/code-optimizer/references/io-network.md +89 -0
- package/src/resources/skills/code-optimizer/references/logging-observability.md +64 -0
- package/src/resources/skills/code-optimizer/references/memory-resources.md +66 -0
- package/src/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
- package/src/resources/skills/code-optimizer/references/security-performance.md +68 -0
- package/src/resources/skills/core-web-vitals/SKILL.md +441 -0
- package/src/resources/skills/core-web-vitals/references/LCP.md +208 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +93 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +37 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +104 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +176 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +76 -0
- package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/src/resources/skills/create-skill/SKILL.md +186 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/src/resources/skills/create-workflow/SKILL.md +130 -0
- package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
- package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
- package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
- package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
- package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
- package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
- package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
- package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
- package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
- package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
- package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
- package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
- package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
- package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
- package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/src/resources/skills/design-an-interface/SKILL.md +102 -0
- package/src/resources/skills/forensics/SKILL.md +153 -0
- package/src/resources/skills/frontend-design/SKILL.md +45 -0
- package/src/resources/skills/github-workflows/SKILL.md +90 -0
- package/src/resources/skills/github-workflows/references/gh/SKILL.md +276 -0
- package/src/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
- package/src/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
- package/src/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
- package/src/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
- package/src/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
- package/src/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
- package/src/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/src/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
- package/src/resources/skills/grill-me/SKILL.md +93 -0
- package/src/resources/skills/handoff/SKILL.md +121 -0
- package/src/resources/skills/lint/SKILL.md +145 -0
- package/src/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
- package/src/resources/skills/make-interfaces-feel-better/animations.md +379 -0
- package/src/resources/skills/make-interfaces-feel-better/performance.md +88 -0
- package/src/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
- package/src/resources/skills/make-interfaces-feel-better/typography.md +123 -0
- package/src/resources/skills/observability/SKILL.md +174 -0
- package/src/resources/skills/react-best-practices/README.md +123 -0
- package/src/resources/skills/react-best-practices/SKILL.md +136 -0
- package/src/resources/skills/react-best-practices/metadata.json +15 -0
- package/src/resources/skills/react-best-practices/rules/_sections.md +46 -0
- package/src/resources/skills/react-best-practices/rules/_template.md +28 -0
- package/src/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/src/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/src/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/src/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/src/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/src/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
- package/src/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/src/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/src/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/src/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/src/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/src/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/src/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/src/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/src/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/src/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/src/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/src/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/src/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/src/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/src/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/src/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/src/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/src/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/src/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/src/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/src/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/src/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/src/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/src/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/src/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/src/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/src/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/src/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/src/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/src/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/src/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/src/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/src/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/src/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/src/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/src/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/src/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/src/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/src/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/src/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/src/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/src/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/src/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/src/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/src/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/src/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/src/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/src/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/src/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/src/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/src/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/src/resources/skills/review/SKILL.md +218 -0
- package/src/resources/skills/security-review/SKILL.md +181 -0
- package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/src/resources/skills/tdd/SKILL.md +112 -0
- package/src/resources/skills/test/SKILL.md +204 -0
- package/src/resources/skills/userinterface-wiki/SKILL.md +253 -0
- package/src/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
- package/src/resources/skills/userinterface-wiki/rules/_template.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
- package/src/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
- package/src/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
- package/src/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
- package/src/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
- package/src/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
- package/src/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
- package/src/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
- package/src/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
- package/src/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
- package/src/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
- package/src/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
- package/src/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
- package/src/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
- package/src/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
- package/src/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
- package/src/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
- package/src/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
- package/src/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
- package/src/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
- package/src/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
- package/src/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
- package/src/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
- package/src/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
- package/src/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
- package/src/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
- package/src/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
- package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
- package/src/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
- package/src/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
- package/src/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
- package/src/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
- package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/src/resources/skills/web-design-guidelines/SKILL.md +39 -0
- package/src/resources/skills/web-quality-audit/SKILL.md +168 -0
- package/src/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
- package/src/resources/skills/write-docs/SKILL.md +82 -0
- package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
|
@@ -0,0 +1,4108 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Builds GSD auto-mode unit prompts and pre-dispatch checks.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Auto-mode Prompt Builders — construct dispatch prompts for each unit type.
|
|
6
|
+
*
|
|
7
|
+
* Pure async functions that load templates and inline file content. No module-level
|
|
8
|
+
* state, no globals — every dependency is passed as a parameter or imported as a
|
|
9
|
+
* utility.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { loadFile, parseContinue, parseSummary, loadActiveOverrides, formatOverridesSection, parseTaskPlanFile } from "./files.js";
|
|
13
|
+
import type { Override, UatType } from "./files.js";
|
|
14
|
+
import { hasVerdict, getUatType, extractVerdict } from "./verdict-parser.js";
|
|
15
|
+
import { loadPrompt, inlineTemplate } from "./prompt-loader.js";
|
|
16
|
+
import {
|
|
17
|
+
resolveMilestoneFile, resolveSliceFile, resolveSlicePath,
|
|
18
|
+
resolveTasksDir, resolveTaskFiles, resolveTaskFile,
|
|
19
|
+
relMilestoneFile, relSliceFile, relSlicePath, relMilestonePath,
|
|
20
|
+
resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
|
|
21
|
+
} from "./paths.js";
|
|
22
|
+
import { resolveSkillDiscoveryMode, resolveInlineLevel, loadEffectiveGSDPreferences, resolveAllSkillReferences } from "./preferences.js";
|
|
23
|
+
import { isContextModeEnabled } from "./preferences-types.js";
|
|
24
|
+
import { parseRoadmap } from "./parsers-legacy.js";
|
|
25
|
+
import type { GSDState, InlineLevel } from "./types.js";
|
|
26
|
+
import type { GSDPreferences } from "./preferences.js";
|
|
27
|
+
import { getLoadedSkills, type Skill } from "@gsd/pi-coding-agent";
|
|
28
|
+
import { join, basename } from "node:path";
|
|
29
|
+
import { existsSync } from "node:fs";
|
|
30
|
+
import { computeBudgets, resolveExecutorContextWindow, truncateAtSectionBoundary, type MinimalModelRegistry } from "./context-budget.js";
|
|
31
|
+
import { getPendingGates, getPendingGatesForTurn } from "./gsd-db.js";
|
|
32
|
+
import {
|
|
33
|
+
GATE_REGISTRY,
|
|
34
|
+
assertGateCoverage,
|
|
35
|
+
getGatesForTurn,
|
|
36
|
+
type GateDefinition,
|
|
37
|
+
} from "./gate-registry.js";
|
|
38
|
+
import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
|
|
39
|
+
import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
|
|
40
|
+
import { composeContextModeInstructions, composeInlinedContext, composeUnitContext, type ArtifactResolver, type ContextModeRenderMode, type ExcerptResolver } from "./unit-context-composer.js";
|
|
41
|
+
import { readCompactionSnapshot } from "./compaction-snapshot.js";
|
|
42
|
+
import { logWarning } from "./workflow-logger.js";
|
|
43
|
+
import { inlineGraphSubgraph } from "./graph-context.js";
|
|
44
|
+
import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
|
|
45
|
+
import { resolveSkillManifest, warnIfManifestHasMissingSkills } from "./skill-manifest.js";
|
|
46
|
+
import { classifyProject, type ProjectClassification } from "./detection.js";
|
|
47
|
+
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
48
|
+
import { debugLog } from "./debug-logger.js";
|
|
49
|
+
|
|
50
|
+
// ─── Preamble Cap ─────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Static ceiling for the preamble cap. Kept as an upper bound even
|
|
54
|
+
* after context-window-aware sizing so large-window users don't suddenly see
|
|
55
|
+
* 10× looser caps than needed. Small-window users get a tighter cap derived
|
|
56
|
+
* from their configured executor window.
|
|
57
|
+
*/
|
|
58
|
+
const MAX_PREAMBLE_CHARS = 20_000;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolve prompt budgets from the configured executor context window.
|
|
62
|
+
*
|
|
63
|
+
* The prompt builders here don't have access to the runtime model registry
|
|
64
|
+
* (they're called from many non-ctx sites), so `resolveExecutorContextWindow`
|
|
65
|
+
* is fed the user-configurable `context_window_override` preference as the
|
|
66
|
+
* `sessionContextWindow` fallback. That preference exists specifically to
|
|
67
|
+
* cover small-window local models (e.g. 32K lemonade/llama.cpp servers) whose
|
|
68
|
+
* n_ctx is not discoverable through the model registry. Issue #4435.
|
|
69
|
+
*/
|
|
70
|
+
function resolvePromptBudgets(): ReturnType<typeof computeBudgets> {
|
|
71
|
+
try {
|
|
72
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
73
|
+
const sessionWindow = prefs?.preferences.context_window_override;
|
|
74
|
+
const windowTokens = resolveExecutorContextWindow(undefined, prefs?.preferences, sessionWindow);
|
|
75
|
+
return computeBudgets(windowTokens);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
logWarning("prompt", `resolvePromptBudgets failed: ${(e as Error).message}`);
|
|
78
|
+
return computeBudgets(200_000);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Character budget for dependency/prior slice summaries injected into dispatch
|
|
84
|
+
* prompts. Scales with the executor's configured context window (issue #4435).
|
|
85
|
+
*/
|
|
86
|
+
function resolveSummaryBudgetChars(): number {
|
|
87
|
+
return resolvePromptBudgets().summaryBudgetChars;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function formatProjectClassificationForPlanning(classification: ProjectClassification): string {
|
|
91
|
+
const sampleFiles = classification.contentFiles.slice(0, 8);
|
|
92
|
+
const sample = sampleFiles.length > 0 ? sampleFiles.map((file) => `\`${file}\``).join(", ") : "(none)";
|
|
93
|
+
const lines = [
|
|
94
|
+
"### Project Classification",
|
|
95
|
+
"",
|
|
96
|
+
`- **Kind:** ${classification.kind}`,
|
|
97
|
+
`- **Content files:** ${classification.contentFiles.length}`,
|
|
98
|
+
`- **Sample files:** ${sample}`,
|
|
99
|
+
`- **Reason:** ${classification.reason}`,
|
|
100
|
+
"",
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
if (classification.kind === "untyped-existing") {
|
|
104
|
+
if (classification.contentFiles.length <= 2) {
|
|
105
|
+
lines.push(
|
|
106
|
+
"**Workflow sizing:** This is a tiny existing untyped project. Prefer exactly one slice unless the milestone request clearly spans multiple independent user-visible capabilities.",
|
|
107
|
+
);
|
|
108
|
+
} else if (classification.contentFiles.length <= 5) {
|
|
109
|
+
lines.push(
|
|
110
|
+
"**Workflow sizing:** This is a small existing untyped project. Prefer 1-2 slices unless the milestone request clearly spans multiple independent user-visible capabilities.",
|
|
111
|
+
);
|
|
112
|
+
} else {
|
|
113
|
+
lines.push(
|
|
114
|
+
"**Workflow sizing:** Existing untyped project. Use generic file-level workflow guidance and size slices by real capability boundaries, not by missing tooling markers.",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
} else if (classification.kind === "greenfield") {
|
|
118
|
+
lines.push("**Workflow sizing:** No project content exists yet. Use normal greenfield sizing for the requested scope.");
|
|
119
|
+
} else if (classification.kind === "typed-existing") {
|
|
120
|
+
lines.push("**Workflow sizing:** Known project markers exist. Use normal ecosystem-aware planning guidance.");
|
|
121
|
+
} else {
|
|
122
|
+
lines.push("**Workflow sizing:** Invalid repository state. Planning should surface this as a blocker rather than inventing project structure.");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return lines.join("\n");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function normalizeArtifactRef(value: string): string {
|
|
129
|
+
return value.trim().replace(/^[-\s]+/, "").replace(/^["'`]+|["'`]+$/g, "").replaceAll("\\", "/").replace(/^\.\//, "");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function parseCoveredArtifacts(validationContent: string): Set<string> {
|
|
133
|
+
const covered = new Set<string>();
|
|
134
|
+
const lines = validationContent.split(/\r?\n/);
|
|
135
|
+
let inCoveredArtifacts = false;
|
|
136
|
+
for (const line of lines) {
|
|
137
|
+
if (/^\s*covered[-_]?artifacts\s*:/i.test(line)) {
|
|
138
|
+
inCoveredArtifacts = true;
|
|
139
|
+
const inline = line.split(/covered[-_]?artifacts\s*:/i)[1]?.trim();
|
|
140
|
+
if (inline && inline !== "[]") {
|
|
141
|
+
inline.replace(/^\[|\]$/g, "").split(",").map(normalizeArtifactRef).filter(Boolean).forEach((item) => covered.add(item));
|
|
142
|
+
}
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (!inCoveredArtifacts) continue;
|
|
146
|
+
if (/^\S/.test(line) && !/^\s*-/.test(line)) break;
|
|
147
|
+
const item = line.match(/^\s*-\s*(.+)$/)?.[1];
|
|
148
|
+
if (item) covered.add(normalizeArtifactRef(item));
|
|
149
|
+
}
|
|
150
|
+
return covered;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function isValidationFreshOrApplicable(validationContent: string | null, currentArtifacts: string[]): boolean {
|
|
154
|
+
if (!validationContent) return false;
|
|
155
|
+
if (!/validation_metadata:/i.test(validationContent)) return false;
|
|
156
|
+
const coveredArtifacts = parseCoveredArtifacts(validationContent);
|
|
157
|
+
if (coveredArtifacts.size === 0) return false;
|
|
158
|
+
return currentArtifacts
|
|
159
|
+
.map(normalizeArtifactRef)
|
|
160
|
+
.filter(Boolean)
|
|
161
|
+
.every((artifact) => coveredArtifacts.has(artifact));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function formatCloseoutReviewInstructions(validationContent: string | null, validationRel: string, currentArtifacts: string[]): string {
|
|
165
|
+
const verdict = validationContent ? extractVerdict(validationContent) : null;
|
|
166
|
+
const validationFresh = isValidationFreshOrApplicable(validationContent, currentArtifacts);
|
|
167
|
+
if (verdict === "pass" && validationFresh) {
|
|
168
|
+
return [
|
|
169
|
+
"### Passing Validation Artifact",
|
|
170
|
+
"",
|
|
171
|
+
`A passing validation artifact is present at \`${validationRel}\`. Treat it as authoritative for success criteria, requirement coverage, verification classes, and cross-slice integration.`,
|
|
172
|
+
"",
|
|
173
|
+
"Do not delegate fresh reviewer/security/tester audits and do not redo the validation evidence review unless the artifact is internally inconsistent with the inlined summaries. Focus this unit on final milestone narrative, learnings, PROJECT/requirements updates, and `gsd_complete_milestone`.",
|
|
174
|
+
].join("\n");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (verdict) {
|
|
178
|
+
return [
|
|
179
|
+
"### Validation Requires Attention",
|
|
180
|
+
"",
|
|
181
|
+
`A validation artifact is present at \`${validationRel}\` with verdict \`${verdict}\`, but it is missing freshness metadata or does not cover current milestone artifacts. Do not treat the milestone as complete unless the issues are resolved and evidence supports completion.`,
|
|
182
|
+
].join("\n");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return [
|
|
186
|
+
"### No Passing Validation Artifact",
|
|
187
|
+
"",
|
|
188
|
+
`No passing validation artifact was found at \`${validationRel}\`. Use the full closeout review path before completion.`,
|
|
189
|
+
].join("\n");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function capPreamble(preamble: string): string {
|
|
193
|
+
// Cap inlined context at min(static ceiling, scaled inline budget).
|
|
194
|
+
// The ceiling bounds repeated auto prompt payloads; the scaled
|
|
195
|
+
// budget tightens the cap for small-window users whose true safe limit is
|
|
196
|
+
// below 30K. `computeBudgets` allocates 40% of total chars to inline context.
|
|
197
|
+
const budget = Math.min(MAX_PREAMBLE_CHARS, resolvePromptBudgets().inlineContextBudgetChars);
|
|
198
|
+
if (preamble.length <= budget) return preamble;
|
|
199
|
+
return truncateAtSectionBoundary(preamble, budget).content;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
type PromptContextMode = "inline" | "excerpt" | "on-demand" | "skipped";
|
|
203
|
+
|
|
204
|
+
interface PromptContextTelemetryEntry {
|
|
205
|
+
readonly key: string;
|
|
206
|
+
readonly mode: PromptContextMode;
|
|
207
|
+
readonly chars: number;
|
|
208
|
+
readonly reason?: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function trackPromptContext(
|
|
212
|
+
entries: PromptContextTelemetryEntry[],
|
|
213
|
+
key: string,
|
|
214
|
+
mode: PromptContextMode,
|
|
215
|
+
body: string | null | undefined,
|
|
216
|
+
reason?: string,
|
|
217
|
+
): void {
|
|
218
|
+
entries.push({
|
|
219
|
+
key,
|
|
220
|
+
mode,
|
|
221
|
+
chars: body?.length ?? 0,
|
|
222
|
+
...(reason ? { reason } : {}),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function emitPromptContextTelemetry(
|
|
227
|
+
unitType: string,
|
|
228
|
+
entries: readonly PromptContextTelemetryEntry[],
|
|
229
|
+
finalBody: string,
|
|
230
|
+
): void {
|
|
231
|
+
debugLog("prompt-context", {
|
|
232
|
+
unitType,
|
|
233
|
+
finalChars: finalBody.length,
|
|
234
|
+
loaded: entries.filter((entry) => entry.mode !== "skipped").map((entry) => ({
|
|
235
|
+
key: entry.key,
|
|
236
|
+
mode: entry.mode,
|
|
237
|
+
chars: entry.chars,
|
|
238
|
+
...(entry.reason ? { reason: entry.reason } : {}),
|
|
239
|
+
})),
|
|
240
|
+
skipped: entries.filter((entry) => entry.mode === "skipped").map((entry) => ({
|
|
241
|
+
key: entry.key,
|
|
242
|
+
reason: entry.reason ?? "not applicable",
|
|
243
|
+
})),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function renderContextModeForPrompt(
|
|
248
|
+
unitType: string,
|
|
249
|
+
base: string,
|
|
250
|
+
renderMode: ContextModeRenderMode = "standalone",
|
|
251
|
+
): string {
|
|
252
|
+
const effectivePrefs = loadEffectiveGSDPreferences(base)?.preferences;
|
|
253
|
+
return composeContextModeInstructions(unitType, {
|
|
254
|
+
enabled: isContextModeEnabled(effectivePrefs),
|
|
255
|
+
renderMode,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function renderContextModeBlockForPrompt(
|
|
260
|
+
unitType: string,
|
|
261
|
+
base: string,
|
|
262
|
+
renderMode: ContextModeRenderMode = "standalone",
|
|
263
|
+
): string {
|
|
264
|
+
const contextMode = renderContextModeForPrompt(unitType, base, renderMode);
|
|
265
|
+
if (!contextMode) return "";
|
|
266
|
+
if (renderMode === "nested") return contextMode;
|
|
267
|
+
|
|
268
|
+
const snapshot = readCompactionSnapshot(base);
|
|
269
|
+
if (!snapshot?.trim()) return contextMode;
|
|
270
|
+
|
|
271
|
+
return `${contextMode}\n\n## Context Snapshot\nSource: \`.gsd/last-snapshot.md\`\n\n${snapshot.trimEnd()}`;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function prependContextModeToBlock(
|
|
275
|
+
unitType: string,
|
|
276
|
+
base: string,
|
|
277
|
+
block: string,
|
|
278
|
+
renderMode: ContextModeRenderMode = "standalone",
|
|
279
|
+
): string {
|
|
280
|
+
const contextMode = renderContextModeBlockForPrompt(unitType, base, renderMode);
|
|
281
|
+
if (!contextMode) return block;
|
|
282
|
+
if (!block.trim()) return contextMode;
|
|
283
|
+
return `${contextMode}\n\n${block}`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function resolveEffectiveUatType(content: string): UatType {
|
|
287
|
+
const uatType = getUatType(content);
|
|
288
|
+
if (uatType === "artifact-driven" && hasBrowserRequiredText(content)) {
|
|
289
|
+
return "browser-executable";
|
|
290
|
+
}
|
|
291
|
+
return uatType;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function shouldDispatchUatForContent(content: string, prefs: GSDPreferences | undefined): boolean {
|
|
295
|
+
const uatType = resolveEffectiveUatType(content);
|
|
296
|
+
return !!prefs?.uat_dispatch || uatType !== "artifact-driven" || hasBrowserRequiredText(content);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// ─── Executor Constraints ─────────────────────────────────────────────────────
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Format executor context constraints for injection into the plan-slice prompt.
|
|
303
|
+
* Uses the budget engine to compute task count ranges and inline context budgets
|
|
304
|
+
* based on the configured executor model's context window.
|
|
305
|
+
*/
|
|
306
|
+
function formatExecutorConstraints(
|
|
307
|
+
sessionContextWindow?: number,
|
|
308
|
+
modelRegistry?: MinimalModelRegistry,
|
|
309
|
+
sessionProvider?: string,
|
|
310
|
+
): string {
|
|
311
|
+
let windowTokens: number;
|
|
312
|
+
try {
|
|
313
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
314
|
+
windowTokens = resolveExecutorContextWindow(modelRegistry, prefs?.preferences, sessionContextWindow, sessionProvider);
|
|
315
|
+
} catch (e) {
|
|
316
|
+
logWarning("prompt", `resolveExecutorContextWindow failed: ${(e as Error).message}`);
|
|
317
|
+
// Delegate to the budget engine without prefs (the path that just threw)
|
|
318
|
+
// so DEFAULT_CONTEXT_WINDOW stays the single source of truth.
|
|
319
|
+
windowTokens = resolveExecutorContextWindow(undefined, undefined, sessionContextWindow, sessionProvider);
|
|
320
|
+
}
|
|
321
|
+
const budgets = computeBudgets(windowTokens);
|
|
322
|
+
const { min, max } = budgets.taskCountRange;
|
|
323
|
+
const execWindowK = Math.round(windowTokens / 1000);
|
|
324
|
+
const perTaskBudgetK = Math.round(budgets.inlineContextBudgetChars / 1000);
|
|
325
|
+
return [
|
|
326
|
+
`## Executor Context Constraints`,
|
|
327
|
+
``,
|
|
328
|
+
`The agent that executes each task has a **${execWindowK}K token** context window.`,
|
|
329
|
+
`- Recommended task count for this slice: **${min}–${max} tasks**`,
|
|
330
|
+
`- Each task gets ~${perTaskBudgetK}K chars of inline context (plans, code, decisions)`,
|
|
331
|
+
`- Keep individual tasks completable within a single context window — if a task needs more context than fits, split it`,
|
|
332
|
+
].join("\n");
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Returns a markdown bullet list of known context file paths for the given
|
|
337
|
+
* milestone (and optionally slice). Falls back to a generic tool-agnostic
|
|
338
|
+
* instruction when no GSD artifacts are found.
|
|
339
|
+
*
|
|
340
|
+
* @param base - Absolute path to the project root.
|
|
341
|
+
* @param mid - Milestone ID (e.g. `"M001"`).
|
|
342
|
+
* @param sid - Optional slice ID (e.g. `"S01"`). When provided, the slice
|
|
343
|
+
* RESEARCH file is preferred over the milestone-level one.
|
|
344
|
+
* @returns Markdown string of file path bullets, or a fallback instruction.
|
|
345
|
+
*/
|
|
346
|
+
export function buildSourceFilePaths(
|
|
347
|
+
base: string,
|
|
348
|
+
mid: string,
|
|
349
|
+
sid?: string,
|
|
350
|
+
): string {
|
|
351
|
+
const paths: string[] = [];
|
|
352
|
+
|
|
353
|
+
const projectPath = resolveGsdRootFile(base, "PROJECT");
|
|
354
|
+
if (existsSync(projectPath)) {
|
|
355
|
+
paths.push(`- **Project**: \`${relGsdRootFile("PROJECT")}\``);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const requirementsPath = resolveGsdRootFile(base, "REQUIREMENTS");
|
|
359
|
+
if (existsSync(requirementsPath)) {
|
|
360
|
+
paths.push(`- **Requirements**: \`${relGsdRootFile("REQUIREMENTS")}\``);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
364
|
+
if (existsSync(decisionsPath)) {
|
|
365
|
+
paths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const queuePath = resolveGsdRootFile(base, "QUEUE");
|
|
369
|
+
if (existsSync(queuePath)) {
|
|
370
|
+
paths.push(`- **Queue**: \`${relGsdRootFile("QUEUE")}\``);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
374
|
+
if (contextPath) {
|
|
375
|
+
paths.push(`- **Milestone Context**: \`${relMilestoneFile(base, mid, "CONTEXT")}\``);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
379
|
+
if (roadmapPath) {
|
|
380
|
+
paths.push(`- **Roadmap**: \`${relMilestoneFile(base, mid, "ROADMAP")}\``);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (sid) {
|
|
384
|
+
const researchPath = resolveSliceFile(base, mid, sid, "RESEARCH");
|
|
385
|
+
if (researchPath) {
|
|
386
|
+
paths.push(`- **Slice Research**: \`${relSliceFile(base, mid, sid, "RESEARCH")}\``);
|
|
387
|
+
}
|
|
388
|
+
} else {
|
|
389
|
+
const researchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
390
|
+
if (researchPath) {
|
|
391
|
+
paths.push(`- **Milestone Research**: \`${relMilestoneFile(base, mid, "RESEARCH")}\``);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return paths.length > 0
|
|
396
|
+
? paths.join("\n")
|
|
397
|
+
: "- Use the Grep/Glob/Read tools to identify the relevant source files before planning.";
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ─── Inline Helpers ───────────────────────────────────────────────────────
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Load a file and format it for inlining into a prompt.
|
|
404
|
+
* Returns the content wrapped with a source path header, or a fallback
|
|
405
|
+
* message if the file doesn't exist. This eliminates tool calls — the LLM
|
|
406
|
+
* gets the content directly instead of "Read this file:".
|
|
407
|
+
*/
|
|
408
|
+
export async function inlineFile(
|
|
409
|
+
absPath: string | null, relPath: string, label: string,
|
|
410
|
+
): Promise<string> {
|
|
411
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
412
|
+
if (!content) {
|
|
413
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n_(not found — file does not exist yet)_`;
|
|
414
|
+
}
|
|
415
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n${content.trim()}`;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Load a file for inlining, returning null if it doesn't exist.
|
|
420
|
+
* Use when the file is optional and should be omitted entirely if absent.
|
|
421
|
+
*/
|
|
422
|
+
export async function inlineFileOptional(
|
|
423
|
+
absPath: string | null, relPath: string, label: string,
|
|
424
|
+
): Promise<string | null> {
|
|
425
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
426
|
+
if (!content) return null;
|
|
427
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n${content.trim()}`;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Smart file inlining — for large files, use semantic chunking to include
|
|
432
|
+
* only the most relevant portions based on the task context.
|
|
433
|
+
* Falls back to full content for small files or when no query is provided.
|
|
434
|
+
*
|
|
435
|
+
* @param absPath Absolute file path
|
|
436
|
+
* @param relPath Relative display path
|
|
437
|
+
* @param label Section label
|
|
438
|
+
* @param query Task description for relevance scoring (optional)
|
|
439
|
+
* @param threshold Character threshold for chunking (default: 3000)
|
|
440
|
+
*/
|
|
441
|
+
export async function inlineFileSmart(
|
|
442
|
+
absPath: string | null, relPath: string, label: string,
|
|
443
|
+
query?: string, threshold = 3000,
|
|
444
|
+
): Promise<string> {
|
|
445
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
446
|
+
if (!content) {
|
|
447
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n_(not found — file does not exist yet)_`;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// For small files or no query, include full content
|
|
451
|
+
if (content.length <= threshold || !query) {
|
|
452
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n${content.trim()}`;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// For large files, truncate at section boundary
|
|
456
|
+
const truncated = truncateAtSectionBoundary(content, threshold).content;
|
|
457
|
+
return `### ${label}\nSource: \`${relPath}\`\n\n${truncated}`;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function inlineCompactTemplate(name: "plan" | "task-summary" | "slice-summary", label: string): string {
|
|
461
|
+
const compact: Record<typeof name, string> = {
|
|
462
|
+
plan: [
|
|
463
|
+
"# {{sliceId}}: {{sliceTitle}}",
|
|
464
|
+
"",
|
|
465
|
+
"**Goal:** {{goal}}",
|
|
466
|
+
"**Demo:** {{demo}}",
|
|
467
|
+
"",
|
|
468
|
+
"## Must-Haves",
|
|
469
|
+
"- {{mustHave}}",
|
|
470
|
+
"",
|
|
471
|
+
"## Threat Surface",
|
|
472
|
+
"- Abuse: {{abuseScenarios}}",
|
|
473
|
+
"- Data exposure: {{sensitiveDataAccessible}}",
|
|
474
|
+
"- Input trust: {{untrustedInput}}",
|
|
475
|
+
"",
|
|
476
|
+
"## Requirement Impact",
|
|
477
|
+
"- Requirements touched: {{requirementIds}}",
|
|
478
|
+
"- Re-verify: {{whatMustBeRetested}}",
|
|
479
|
+
"- Decisions revisited: {{decisionIds}}",
|
|
480
|
+
"",
|
|
481
|
+
"## Proof Level",
|
|
482
|
+
"- This slice proves: {{contract | integration | operational | final-assembly}}",
|
|
483
|
+
"- Real runtime required: {{yes/no}}",
|
|
484
|
+
"- Human/UAT required: {{yes/no}}",
|
|
485
|
+
"",
|
|
486
|
+
"## Verification",
|
|
487
|
+
"- {{testFileOrCommand}}",
|
|
488
|
+
"",
|
|
489
|
+
"## Observability / Diagnostics",
|
|
490
|
+
"- Runtime signals: {{signalOrNone}}",
|
|
491
|
+
"- Inspection surfaces: {{surfaceOrNone}}",
|
|
492
|
+
"- Failure visibility: {{failureSignalOrNone}}",
|
|
493
|
+
"- Redaction constraints: {{secretOrPiiBoundaryOrNone}}",
|
|
494
|
+
"",
|
|
495
|
+
"## Integration Closure",
|
|
496
|
+
"- Upstream surfaces consumed: {{filesModulesContracts}}",
|
|
497
|
+
"- New wiring introduced: {{entrypointOrNone}}",
|
|
498
|
+
"- Remaining end-to-end work: {{listOrNothing}}",
|
|
499
|
+
"",
|
|
500
|
+
"## Tasks",
|
|
501
|
+
"- [ ] **T01: {{taskTitle}}** `est:{{estimate}}`",
|
|
502
|
+
" - Why: {{whyThisTaskExists}}",
|
|
503
|
+
" - Files: `{{filePath}}`",
|
|
504
|
+
" - Do: {{specificImplementationStepsAndConstraints}}",
|
|
505
|
+
" - Verify: {{testCommandOrRuntimeCheck}}",
|
|
506
|
+
" - Done when: {{measurableAcceptanceCondition}}",
|
|
507
|
+
"",
|
|
508
|
+
"## Files Likely Touched",
|
|
509
|
+
"- `{{filePath}}`",
|
|
510
|
+
].join("\n"),
|
|
511
|
+
"task-summary": [
|
|
512
|
+
"---",
|
|
513
|
+
"id: {{taskId}}",
|
|
514
|
+
"parent: {{sliceId}}",
|
|
515
|
+
"milestone: {{milestoneId}}",
|
|
516
|
+
"provides: [{{whatThisTaskProvides}}]",
|
|
517
|
+
"key_files: [{{filePath}}]",
|
|
518
|
+
"key_decisions: [{{decision}}]",
|
|
519
|
+
"patterns_established: [{{pattern}}]",
|
|
520
|
+
"observability_surfaces: [{{diagnosticOrNone}}]",
|
|
521
|
+
"duration: {{duration}}",
|
|
522
|
+
"verification_result: passed",
|
|
523
|
+
"completed_at: {{date}}",
|
|
524
|
+
"blocker_discovered: false",
|
|
525
|
+
"---",
|
|
526
|
+
"",
|
|
527
|
+
"# {{taskId}}: {{taskTitle}}",
|
|
528
|
+
"**{{oneLiner}}**",
|
|
529
|
+
"",
|
|
530
|
+
"## What Happened",
|
|
531
|
+
"{{narrative}}",
|
|
532
|
+
"",
|
|
533
|
+
"## Verification",
|
|
534
|
+
"{{whatWasVerifiedAndHow}}",
|
|
535
|
+
"",
|
|
536
|
+
"## Verification Evidence",
|
|
537
|
+
"| # | Command | Exit Code | Verdict | Duration |",
|
|
538
|
+
"|---|---------|-----------|---------|----------|",
|
|
539
|
+
"| {{row}} | {{command}} | {{exitCode}} | {{verdict}} | {{duration}} |",
|
|
540
|
+
"",
|
|
541
|
+
"## Diagnostics",
|
|
542
|
+
"{{diagnosticsOrNone}}",
|
|
543
|
+
"",
|
|
544
|
+
"## Deviations",
|
|
545
|
+
"{{deviationsFromPlan_OR_none}}",
|
|
546
|
+
"",
|
|
547
|
+
"## Known Issues",
|
|
548
|
+
"{{issuesDiscoveredButNotFixed_OR_none}}",
|
|
549
|
+
"",
|
|
550
|
+
"## Files Created/Modified",
|
|
551
|
+
"- `{{filePath}}` - {{description}}",
|
|
552
|
+
].join("\n"),
|
|
553
|
+
"slice-summary": [
|
|
554
|
+
"---",
|
|
555
|
+
"id: {{sliceId}}",
|
|
556
|
+
"parent: {{milestoneId}}",
|
|
557
|
+
"milestone: {{milestoneId}}",
|
|
558
|
+
"provides: [{{whatThisSliceProvides}}]",
|
|
559
|
+
"requires: []",
|
|
560
|
+
"affects: []",
|
|
561
|
+
"key_files: [{{filePath}}]",
|
|
562
|
+
"key_decisions: [{{decision}}]",
|
|
563
|
+
"patterns_established: [{{pattern}}]",
|
|
564
|
+
"observability_surfaces: [{{diagnosticOrNone}}]",
|
|
565
|
+
"drill_down_paths: [{{pathToTaskSummary}}]",
|
|
566
|
+
"duration: {{duration}}",
|
|
567
|
+
"verification_result: passed",
|
|
568
|
+
"completed_at: {{date}}",
|
|
569
|
+
"---",
|
|
570
|
+
"",
|
|
571
|
+
"# {{sliceId}}: {{sliceTitle}}",
|
|
572
|
+
"**{{oneLiner}}**",
|
|
573
|
+
"",
|
|
574
|
+
"## What Happened",
|
|
575
|
+
"{{narrative}}",
|
|
576
|
+
"",
|
|
577
|
+
"## Verification",
|
|
578
|
+
"{{whatWasVerifiedAcrossAllTasks}}",
|
|
579
|
+
"",
|
|
580
|
+
"## Requirements Advanced",
|
|
581
|
+
"- {{requirementId}} - {{howThisSliceAdvancedIt}}",
|
|
582
|
+
"",
|
|
583
|
+
"## Requirements Validated",
|
|
584
|
+
"- {{requirementId}} - {{whatProofNowMakesItValidated}}",
|
|
585
|
+
"",
|
|
586
|
+
"## New Requirements Surfaced",
|
|
587
|
+
"- {{newRequirementOr_none}}",
|
|
588
|
+
"",
|
|
589
|
+
"## Requirements Invalidated or Re-scoped",
|
|
590
|
+
"- {{requirementIdOr_none}} - {{whatChanged}}",
|
|
591
|
+
"",
|
|
592
|
+
"## Operational Readiness",
|
|
593
|
+
"- Health signal: {{healthSignalOrNA}}",
|
|
594
|
+
"- Failure signal: {{failureSignalOrNA}}",
|
|
595
|
+
"- Recovery: {{recoveryOrNA}}",
|
|
596
|
+
"- Monitoring gaps: {{gapsOrNone}}",
|
|
597
|
+
"",
|
|
598
|
+
"## Deviations",
|
|
599
|
+
"{{deviationsFromPlan_OR_none}}",
|
|
600
|
+
"",
|
|
601
|
+
"## Known Limitations",
|
|
602
|
+
"{{whatDoesntWorkYet_OR_whatWasDeferredToLaterSlices}}",
|
|
603
|
+
"",
|
|
604
|
+
"## Follow-ups",
|
|
605
|
+
"{{workDeferredOrDiscoveredDuringExecution_OR_none}}",
|
|
606
|
+
"",
|
|
607
|
+
"## Files Created/Modified",
|
|
608
|
+
"- `{{filePath}}` - {{description}}",
|
|
609
|
+
"",
|
|
610
|
+
"## Forward Intelligence",
|
|
611
|
+
"### What the next slice should know",
|
|
612
|
+
"- {{insightThatWouldHelpDownstreamWork}}",
|
|
613
|
+
"### What's fragile",
|
|
614
|
+
"- {{fragileAreaOrThinImplementation}} - {{whyItMatters}}",
|
|
615
|
+
"### Authoritative diagnostics",
|
|
616
|
+
"- {{whereAFutureAgentShouldLookFirst}} - {{whyThisSignalIsTrustworthy}}",
|
|
617
|
+
"### What assumptions changed",
|
|
618
|
+
"- {{originalAssumption}} - {{whatActuallyHappened}}",
|
|
619
|
+
].join("\n"),
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
return `${compact[name]}\n\n### Output Template: ${label}\nSource: \`templates/${name}.md\``;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Compact slice-summary excerpt for milestone-level closers (#4780).
|
|
627
|
+
*
|
|
628
|
+
* Emits the frontmatter fields + short body section heads rather than the
|
|
629
|
+
* full SUMMARY.md body, and keeps the source path in the header so the
|
|
630
|
+
* closer agent can Read the full file on demand when drafting LEARNINGS.
|
|
631
|
+
*
|
|
632
|
+
* Scope: designed for `buildCompleteMilestonePrompt`, which previously
|
|
633
|
+
* inlined the full SUMMARY per slice and routinely paid ~300–500K tokens
|
|
634
|
+
* per close when the narrative was never synthesized. Not used by
|
|
635
|
+
* `buildValidateMilestonePrompt` yet — validate needs fuller verification
|
|
636
|
+
* evidence; follow-up PR can extend or parameterize.
|
|
637
|
+
*
|
|
638
|
+
* If parsing fails (unrecognizable frontmatter, missing id, etc.) the
|
|
639
|
+
* function falls back to `inlineFile` so the closer loses no information.
|
|
640
|
+
*/
|
|
641
|
+
export async function buildSliceSummaryExcerpt(
|
|
642
|
+
absPath: string | null, relPath: string, sid: string,
|
|
643
|
+
): Promise<string> {
|
|
644
|
+
const header = `### ${sid} Summary (excerpt)\nSource: \`${relPath}\``;
|
|
645
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
646
|
+
if (!content) {
|
|
647
|
+
return `${header}\n\n_(not found — file does not exist yet)_`;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
const s = parseSummary(content);
|
|
651
|
+
if (!s.frontmatter.id) {
|
|
652
|
+
// Unrecognizable — fall back to full file so no context is lost.
|
|
653
|
+
return `### ${sid} Summary\nSource: \`${relPath}\`\n\n${content.trim()}`;
|
|
654
|
+
}
|
|
655
|
+
const lines: string[] = [header, ""];
|
|
656
|
+
if (s.title) lines.push(`**Title:** ${s.title}`);
|
|
657
|
+
if (s.oneLiner) lines.push(`**One-liner:** ${s.oneLiner}`);
|
|
658
|
+
if (s.frontmatter.verification_result) {
|
|
659
|
+
lines.push(`**Verification:** \`${s.frontmatter.verification_result}\``);
|
|
660
|
+
}
|
|
661
|
+
lines.push(`**Blockers:** ${s.frontmatter.blocker_discovered ? "⚠️ blocker recorded — Read full summary" : "none"}`);
|
|
662
|
+
if (s.frontmatter.duration) lines.push(`**Duration:** ${s.frontmatter.duration}`);
|
|
663
|
+
if (s.frontmatter.provides.length > 0) lines.push(`**Provides:** ${s.frontmatter.provides.join("; ")}`);
|
|
664
|
+
if (s.frontmatter.affects.length > 0) lines.push(`**Affects:** ${s.frontmatter.affects.join("; ")}`);
|
|
665
|
+
if (s.frontmatter.key_decisions.length > 0) lines.push(`**Key decisions:** ${s.frontmatter.key_decisions.join("; ")}`);
|
|
666
|
+
if (s.frontmatter.patterns_established.length > 0) lines.push(`**Patterns established:** ${s.frontmatter.patterns_established.join("; ")}`);
|
|
667
|
+
if (s.frontmatter.key_files.length > 0) {
|
|
668
|
+
const files = s.frontmatter.key_files.slice(0, 8);
|
|
669
|
+
const more = s.frontmatter.key_files.length > files.length ? ` (+${s.frontmatter.key_files.length - files.length} more)` : "";
|
|
670
|
+
lines.push(`**Key files:** ${files.join(", ")}${more}`);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Cap section bodies (coderabbit review on #4908): if any of these
|
|
674
|
+
// narrative sections balloon, excerpt mode still inflates and
|
|
675
|
+
// undermines the token-reduction goal. 800 chars (~200 tokens) is
|
|
676
|
+
// enough to carry intent; the closer agent Reads the full file when
|
|
677
|
+
// it needs richer context for LEARNINGS synthesis.
|
|
678
|
+
const SECTION_CAP_CHARS = 800;
|
|
679
|
+
const capSection = (body: string): string => {
|
|
680
|
+
const trimmed = body.trim();
|
|
681
|
+
if (trimmed.length <= SECTION_CAP_CHARS) return trimmed;
|
|
682
|
+
return `${trimmed.slice(0, SECTION_CAP_CHARS)}\n… (truncated — see full \`${relPath}\`)`;
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
if (s.deviations && s.deviations.trim()) {
|
|
686
|
+
lines.push("", "#### Deviations", capSection(s.deviations));
|
|
687
|
+
}
|
|
688
|
+
if (s.knownLimitations && s.knownLimitations.trim()) {
|
|
689
|
+
lines.push("", "#### Known limitations", capSection(s.knownLimitations));
|
|
690
|
+
}
|
|
691
|
+
if (s.followUps && s.followUps.trim()) {
|
|
692
|
+
lines.push("", "#### Follow-ups", capSection(s.followUps));
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
lines.push(
|
|
696
|
+
"",
|
|
697
|
+
`> **On-demand:** read \`${relPath}\` for the full "What Happened" narrative, integration notes, and detailed file-change list when drafting LEARNINGS, the Decision Re-evaluation table, or cross-slice synthesis.`,
|
|
698
|
+
);
|
|
699
|
+
return lines.join("\n");
|
|
700
|
+
} catch {
|
|
701
|
+
// Defensive — any parse failure falls back to full inline.
|
|
702
|
+
return `### ${sid} Summary\nSource: \`${relPath}\`\n\n${capMalformedSummary(content, relPath)}`;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export async function buildSliceAssessmentExcerpt(
|
|
707
|
+
absPath: string | null, relPath: string, sid: string,
|
|
708
|
+
): Promise<string | null> {
|
|
709
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
710
|
+
if (!content) return null;
|
|
711
|
+
|
|
712
|
+
const verdict = extractVerdict(content);
|
|
713
|
+
const edgeCases = extractMarkdownSection(content, "Edge Cases");
|
|
714
|
+
const checksMatch = content.match(/\b(\d+\s*\/\s*\d+)\s+checks?\s+passed\b/i);
|
|
715
|
+
const lines = [
|
|
716
|
+
`### ${sid} Assessment (excerpt)`,
|
|
717
|
+
`Source: \`${relPath}\``,
|
|
718
|
+
"",
|
|
719
|
+
];
|
|
720
|
+
if (verdict) lines.push(`**Verdict:** \`${verdict.toUpperCase()}\``);
|
|
721
|
+
if (checksMatch) lines.push(`**Checks:** ${checksMatch[1]} passed`);
|
|
722
|
+
if (edgeCases?.trim()) {
|
|
723
|
+
const trimmed = edgeCases.trim();
|
|
724
|
+
lines.push(
|
|
725
|
+
"",
|
|
726
|
+
"#### Edge cases",
|
|
727
|
+
trimmed.length > 600 ? `${trimmed.slice(0, 600)}\n… (truncated — see full \`${relPath}\`)` : trimmed,
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
lines.push("", `> **On-demand:** read \`${relPath}\` only if validation needs full UAT assessment detail.`);
|
|
731
|
+
return lines.join("\n");
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
export async function buildTaskSummaryExcerpt(
|
|
735
|
+
absPath: string | null, relPath: string, tid: string, options?: { blocker?: boolean },
|
|
736
|
+
): Promise<string> {
|
|
737
|
+
const label = options?.blocker ? "Blocker Task Summary" : "Task Summary";
|
|
738
|
+
const header = `### ${label}: ${tid} (excerpt)\nSource: \`${relPath}\``;
|
|
739
|
+
const content = absPath ? await loadFile(absPath) : null;
|
|
740
|
+
if (!content) {
|
|
741
|
+
return `${header}\n\n_(not found — file does not exist yet)_`;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
try {
|
|
745
|
+
const s = parseSummary(content);
|
|
746
|
+
if (!s.frontmatter.id) {
|
|
747
|
+
return `### ${label}: ${tid}\nSource: \`${relPath}\`\n\n${capMalformedSummary(content, relPath)}`;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
const lines: string[] = [header, ""];
|
|
751
|
+
if (s.title) lines.push(`**Title:** ${s.title}`);
|
|
752
|
+
if (s.oneLiner) lines.push(`**One-liner:** ${s.oneLiner}`);
|
|
753
|
+
if (s.frontmatter.verification_result) {
|
|
754
|
+
lines.push(`**Verification:** \`${s.frontmatter.verification_result}\``);
|
|
755
|
+
}
|
|
756
|
+
lines.push(`**Blocker discovered:** ${s.frontmatter.blocker_discovered ? "yes — read full summary if blocker details are insufficient" : "no"}`);
|
|
757
|
+
if (s.frontmatter.provides.length > 0) lines.push(`**Provides:** ${s.frontmatter.provides.slice(0, 4).join("; ")}`);
|
|
758
|
+
if (s.frontmatter.key_decisions.length > 0) lines.push(`**Key decisions:** ${s.frontmatter.key_decisions.slice(0, 4).join("; ")}`);
|
|
759
|
+
if (s.frontmatter.patterns_established.length > 0) lines.push(`**Patterns established:** ${s.frontmatter.patterns_established.slice(0, 4).join("; ")}`);
|
|
760
|
+
if (s.frontmatter.key_files.length > 0) {
|
|
761
|
+
const files = s.frontmatter.key_files.slice(0, 6);
|
|
762
|
+
const more = s.frontmatter.key_files.length > files.length ? ` (+${s.frontmatter.key_files.length - files.length} more)` : "";
|
|
763
|
+
lines.push(`**Key files:** ${files.join(", ")}${more}`);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const SECTION_CAP_CHARS = 500;
|
|
767
|
+
const capSection = (body: string): string => {
|
|
768
|
+
const trimmed = body.trim();
|
|
769
|
+
if (trimmed.length <= SECTION_CAP_CHARS) return trimmed;
|
|
770
|
+
return `${trimmed.slice(0, SECTION_CAP_CHARS)}\n… (truncated — see full \`${relPath}\`)`;
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
const verification = extractMarkdownSection(content, "Verification");
|
|
774
|
+
const diagnostics = extractMarkdownSection(content, "Diagnostics");
|
|
775
|
+
const knownIssues = extractMarkdownSection(content, "Known Issues");
|
|
776
|
+
|
|
777
|
+
if (verification && verification.trim()) {
|
|
778
|
+
lines.push("", "#### Verification", capSection(verification));
|
|
779
|
+
}
|
|
780
|
+
if (diagnostics && diagnostics.trim()) {
|
|
781
|
+
lines.push("", "#### Diagnostics", capSection(diagnostics));
|
|
782
|
+
}
|
|
783
|
+
if (s.deviations && s.deviations.trim()) {
|
|
784
|
+
lines.push("", "#### Deviations", capSection(s.deviations));
|
|
785
|
+
}
|
|
786
|
+
if (knownIssues && knownIssues.trim()) {
|
|
787
|
+
lines.push("", "#### Known issues", capSection(knownIssues));
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
lines.push(
|
|
791
|
+
"",
|
|
792
|
+
`> **On-demand:** read \`${relPath}\` only when this excerpt is absent/truncated or you need fuller blocker, implementation, or file-change evidence.`,
|
|
793
|
+
);
|
|
794
|
+
return lines.join("\n");
|
|
795
|
+
} catch {
|
|
796
|
+
return `### ${label}: ${tid}\nSource: \`${relPath}\`\n\n${capMalformedSummary(content, relPath)}`;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function capMalformedSummary(content: string, relPath: string): string {
|
|
801
|
+
const trimmed = content.trim();
|
|
802
|
+
const limit = 1_500;
|
|
803
|
+
if (trimmed.length <= limit) return trimmed;
|
|
804
|
+
return `${trimmed.slice(0, limit).trimEnd()}\n\n[Truncated malformed summary — read \`${relPath}\` for full details.]`;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Load and inline dependency slice summaries (full content, not just paths).
|
|
809
|
+
*/
|
|
810
|
+
export async function inlineDependencySummaries(
|
|
811
|
+
mid: string, sid: string, base: string, budgetChars?: number,
|
|
812
|
+
): Promise<string> {
|
|
813
|
+
// DB primary path — get slice depends directly
|
|
814
|
+
let depends: string[] | null = null;
|
|
815
|
+
try {
|
|
816
|
+
const { isDbAvailable, getSlice } = await import("./gsd-db.js");
|
|
817
|
+
if (isDbAvailable()) {
|
|
818
|
+
const slice = getSlice(mid, sid);
|
|
819
|
+
if (slice) {
|
|
820
|
+
if (slice.depends.length === 0) return "- (no dependencies)";
|
|
821
|
+
depends = slice.depends as string[];
|
|
822
|
+
}
|
|
823
|
+
// If slice not found in DB, fall through to file-based parsing
|
|
824
|
+
}
|
|
825
|
+
} catch (err) {
|
|
826
|
+
logWarning("prompt", `inlineDependencySummaries DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// If DB didn't provide depends, fall back to roadmap parsing
|
|
830
|
+
if (!depends) {
|
|
831
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
832
|
+
if (roadmapPath) {
|
|
833
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
834
|
+
if (roadmapContent) {
|
|
835
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
836
|
+
const slice = parsed.slices.find(s => s.id === sid);
|
|
837
|
+
if (slice && slice.depends.length > 0) {
|
|
838
|
+
depends = slice.depends;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (!depends) {
|
|
843
|
+
return "- (no dependencies)";
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
const sections: string[] = [];
|
|
848
|
+
const seen = new Set<string>();
|
|
849
|
+
for (const dep of depends) {
|
|
850
|
+
if (seen.has(dep)) continue;
|
|
851
|
+
seen.add(dep);
|
|
852
|
+
const summaryFile = resolveSliceFile(base, mid, dep, "SUMMARY");
|
|
853
|
+
const summaryContent = summaryFile ? await loadFile(summaryFile) : null;
|
|
854
|
+
const relPath = relSliceFile(base, mid, dep, "SUMMARY");
|
|
855
|
+
if (summaryContent) {
|
|
856
|
+
sections.push(`#### ${dep} Summary\nSource: \`${relPath}\`\n\n${summaryContent.trim()}`);
|
|
857
|
+
} else {
|
|
858
|
+
sections.push(`- \`${relPath}\` _(not found)_`);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
const result = sections.join("\n\n");
|
|
863
|
+
if (budgetChars !== undefined && result.length > budgetChars) {
|
|
864
|
+
return truncateAtSectionBoundary(result, budgetChars).content;
|
|
865
|
+
}
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Load a well-known .gsd/ root file for optional inlining.
|
|
871
|
+
* Handles the existsSync check internally.
|
|
872
|
+
*/
|
|
873
|
+
export async function inlineGsdRootFile(
|
|
874
|
+
base: string, filename: string, label: string,
|
|
875
|
+
): Promise<string | null> {
|
|
876
|
+
const key = filename.replace(/\.md$/i, "").toUpperCase() as "PROJECT" | "DECISIONS" | "QUEUE" | "STATE" | "REQUIREMENTS" | "KNOWLEDGE";
|
|
877
|
+
const absPath = resolveGsdRootFile(base, key);
|
|
878
|
+
if (!existsSync(absPath)) return null;
|
|
879
|
+
return inlineFileOptional(absPath, relGsdRootFile(key), label);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// ─── DB-Aware Inline Helpers ──────────────────────────────────────────────
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Inline decisions with optional milestone scoping from the DB.
|
|
886
|
+
* Falls back to filesystem via inlineGsdRootFile only when DB is unavailable.
|
|
887
|
+
*
|
|
888
|
+
* Cascade logic (R005):
|
|
889
|
+
* 1. Query with { milestoneId, scope } if scope provided
|
|
890
|
+
* 2. If empty AND scope was provided, retry with { milestoneId } only (drop scope)
|
|
891
|
+
* 3. If still empty, return null (intentional per D020)
|
|
892
|
+
*/
|
|
893
|
+
export async function inlineDecisionsFromDb(
|
|
894
|
+
base: string, milestoneId?: string, scope?: string, level?: InlineLevel,
|
|
895
|
+
): Promise<string | null> {
|
|
896
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
897
|
+
try {
|
|
898
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
899
|
+
if (isDbAvailable()) {
|
|
900
|
+
// ADR-013 Phase 6 cutover (Stage 1): read decisions from the `memories`
|
|
901
|
+
// table. Both `queryDecisions` (legacy) and `queryDecisionsFromMemories`
|
|
902
|
+
// return identical Decision[] for active rows once Phase 5 dual-write is
|
|
903
|
+
// caught up. Switching the read here lets the destructive Phase 6 step
|
|
904
|
+
// (#5755) retire the legacy `decisions` table without changing prompt
|
|
905
|
+
// contents. Projection regen (`DECISIONS.md`) still sources from the
|
|
906
|
+
// legacy table — that switch lands separately to handle superseded
|
|
907
|
+
// history cleanly.
|
|
908
|
+
const { queryDecisionsFromMemories, formatDecisionsForPrompt } = await import("./context-store.js");
|
|
909
|
+
|
|
910
|
+
// First query: try with both milestoneId and scope (if scope provided)
|
|
911
|
+
let decisions = queryDecisionsFromMemories({ milestoneId, scope });
|
|
912
|
+
|
|
913
|
+
// Cascade: if empty AND scope was provided, retry without scope
|
|
914
|
+
if (decisions.length === 0 && scope) {
|
|
915
|
+
decisions = queryDecisionsFromMemories({ milestoneId });
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
if (decisions.length > 0) {
|
|
919
|
+
// Use compact format for non-full levels to save ~35% tokens
|
|
920
|
+
const formatted = inlineLevel !== "full"
|
|
921
|
+
? formatDecisionsCompact(decisions)
|
|
922
|
+
: formatDecisionsForPrompt(decisions);
|
|
923
|
+
return `### Decisions\nSource: \`.gsd/DECISIONS.md\`\n\n${formatted}`;
|
|
924
|
+
}
|
|
925
|
+
// DB available but cascade returned empty — intentional per D020, don't fall back to file
|
|
926
|
+
return null;
|
|
927
|
+
}
|
|
928
|
+
} catch (err) {
|
|
929
|
+
logWarning("prompt", `inlineDecisionsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
930
|
+
}
|
|
931
|
+
// DB unavailable — fall back to filesystem
|
|
932
|
+
return inlineGsdRootFile(base, "decisions.md", "Decisions");
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* Inline requirements with optional milestone and slice scoping from the DB.
|
|
937
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
938
|
+
*/
|
|
939
|
+
export async function inlineRequirementsFromDb(
|
|
940
|
+
base: string, milestoneId?: string, sliceId?: string, level?: InlineLevel,
|
|
941
|
+
): Promise<string | null> {
|
|
942
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
943
|
+
try {
|
|
944
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
945
|
+
if (isDbAvailable()) {
|
|
946
|
+
const { queryRequirements, formatRequirementsForPrompt } = await import("./context-store.js");
|
|
947
|
+
const requirements = queryRequirements({ milestoneId, sliceId });
|
|
948
|
+
if (requirements.length > 0) {
|
|
949
|
+
// Use compact format for non-full levels to save ~40% tokens
|
|
950
|
+
const formatted = inlineLevel !== "full"
|
|
951
|
+
? formatRequirementsCompact(requirements)
|
|
952
|
+
: formatRequirementsForPrompt(requirements);
|
|
953
|
+
return `### Requirements\nSource: \`.gsd/REQUIREMENTS.md\`\n\n${formatted}`;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
} catch (err) {
|
|
957
|
+
logWarning("prompt", `inlineRequirementsFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
958
|
+
}
|
|
959
|
+
return inlineGsdRootFile(base, "requirements.md", "Requirements");
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Inline project context from the DB.
|
|
964
|
+
* Falls back to filesystem via inlineGsdRootFile when DB unavailable or empty.
|
|
965
|
+
*/
|
|
966
|
+
export async function inlineProjectFromDb(
|
|
967
|
+
base: string,
|
|
968
|
+
): Promise<string | null> {
|
|
969
|
+
try {
|
|
970
|
+
const { isDbAvailable } = await import("./gsd-db.js");
|
|
971
|
+
if (isDbAvailable()) {
|
|
972
|
+
const { queryProject } = await import("./context-store.js");
|
|
973
|
+
const content = queryProject();
|
|
974
|
+
if (content) {
|
|
975
|
+
return `### Project\nSource: \`.gsd/PROJECT.md\`\n\n${content}`;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
} catch (err) {
|
|
979
|
+
logWarning("prompt", `inlineProjectFromDb failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
980
|
+
}
|
|
981
|
+
return inlineGsdRootFile(base, "project.md", "Project");
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function onDemandProjectBlock(reason: string): string {
|
|
985
|
+
return [
|
|
986
|
+
"### On-demand Project Context",
|
|
987
|
+
"",
|
|
988
|
+
`Project context is available at \`${relGsdRootFile("PROJECT")}\`. Read it only if ${reason}.`,
|
|
989
|
+
].join("\n");
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function onDemandDecisionsBlock(reason: string): string {
|
|
993
|
+
return [
|
|
994
|
+
"### On-demand Decisions",
|
|
995
|
+
"",
|
|
996
|
+
`Decision records are available at \`${relGsdRootFile("DECISIONS")}\`. Read them only if ${reason}.`,
|
|
997
|
+
].join("\n");
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function onDemandMilestoneContextBlock(contextRel: string, reason: string): string {
|
|
1001
|
+
return [
|
|
1002
|
+
"### On-demand Milestone Context",
|
|
1003
|
+
"",
|
|
1004
|
+
`Milestone context is available at \`${contextRel}\`. Read it only if ${reason}.`,
|
|
1005
|
+
].join("\n");
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// ─── Stopwords for keyword extraction ─────────────────────────────────────
|
|
1009
|
+
const STOPWORDS = new Set(['of', 'the', 'and', 'a', 'for', '+', '-', 'to', 'in', 'on', 'with', 'is', 'as', 'by']);
|
|
1010
|
+
|
|
1011
|
+
// Generic words that don't provide meaningful scope differentiation
|
|
1012
|
+
const GENERIC_WORDS = new Set([
|
|
1013
|
+
'setup', 'integration', 'implementation', 'testing', 'test', 'tests',
|
|
1014
|
+
'config', 'configuration', 'init', 'initial', 'basic', 'core',
|
|
1015
|
+
'main', 'primary', 'final', 'complete', 'finish', 'end',
|
|
1016
|
+
'start', 'begin', 'first', 'last', 'update', 'updates',
|
|
1017
|
+
'fix', 'fixes', 'add', 'adds', 'remove', 'removes',
|
|
1018
|
+
'create', 'creates', 'build', 'builds', 'deploy', 'deployment',
|
|
1019
|
+
'refactor', 'refactoring', 'cleanup', 'polish', 'review',
|
|
1020
|
+
// Process/activity words that describe what you're doing, not what domain
|
|
1021
|
+
'hardening', 'validation', 'verification', 'optimization',
|
|
1022
|
+
'improvement', 'enhancement', 'infrastructure',
|
|
1023
|
+
]);
|
|
1024
|
+
|
|
1025
|
+
// Pattern to match slice/milestone/task IDs (e.g., S01, M001, T03)
|
|
1026
|
+
const UNIT_ID_PATTERN = /^[smt]\d+$/i;
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Derive a scope keyword from slice title and optional description.
|
|
1030
|
+
* Returns the most specific noun (first non-generic keyword) for decision scoping.
|
|
1031
|
+
*
|
|
1032
|
+
* Examples:
|
|
1033
|
+
* - "Auth Middleware & Protected Route" → "auth"
|
|
1034
|
+
* - "Database & User Model Setup" → "database"
|
|
1035
|
+
* - "Integration Testing" → undefined (too generic)
|
|
1036
|
+
* - "API Rate Limiting" → "api"
|
|
1037
|
+
*
|
|
1038
|
+
* @param sliceTitle - The slice title
|
|
1039
|
+
* @param sliceDescription - Optional roadmap description (demo text)
|
|
1040
|
+
* @returns A single lowercase keyword or undefined if no meaningful scope
|
|
1041
|
+
*/
|
|
1042
|
+
export function deriveSliceScope(sliceTitle: string, sliceDescription?: string): string | undefined {
|
|
1043
|
+
// Combine title and description for keyword extraction
|
|
1044
|
+
const combinedText = sliceDescription
|
|
1045
|
+
? `${sliceTitle} ${sliceDescription}`
|
|
1046
|
+
: sliceTitle;
|
|
1047
|
+
|
|
1048
|
+
// Extract all words, lowercase, remove punctuation
|
|
1049
|
+
const words = combinedText
|
|
1050
|
+
.split(/[\s&+,;:|/\\()-]+/)
|
|
1051
|
+
.map(w => w.toLowerCase().replace(/[^a-z0-9]/g, ''))
|
|
1052
|
+
.filter(w => w.length >= 2);
|
|
1053
|
+
|
|
1054
|
+
// Find the first word that is:
|
|
1055
|
+
// 1. Not a stopword
|
|
1056
|
+
// 2. Not a generic word
|
|
1057
|
+
// 3. Not a unit ID (S01, M001, T03)
|
|
1058
|
+
// 4. At least 3 characters (meaningful scope)
|
|
1059
|
+
for (const word of words) {
|
|
1060
|
+
if (STOPWORDS.has(word)) continue;
|
|
1061
|
+
if (GENERIC_WORDS.has(word)) continue;
|
|
1062
|
+
if (UNIT_ID_PATTERN.test(word)) continue;
|
|
1063
|
+
if (word.length < 3) continue;
|
|
1064
|
+
return word;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
return undefined;
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Extract keywords from a slice title for scoped knowledge queries.
|
|
1071
|
+
* Splits on whitespace, filters stopwords, lowercases.
|
|
1072
|
+
* Example: 'KNOWLEDGE scoping + roadmap excerpt' → ['knowledge', 'scoping', 'roadmap', 'excerpt']
|
|
1073
|
+
*/
|
|
1074
|
+
function extractKeywords(title: string): string[] {
|
|
1075
|
+
return title
|
|
1076
|
+
.split(/\s+/)
|
|
1077
|
+
.map(w => w.toLowerCase().replace(/[^a-z0-9]/g, ''))
|
|
1078
|
+
.filter(w => w.length > 0 && !STOPWORDS.has(w));
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Inline scoped KNOWLEDGE.md content based on keywords from slice title.
|
|
1083
|
+
* Reads KNOWLEDGE.md, filters to sections matching keywords, formats with header.
|
|
1084
|
+
* Returns null if no KNOWLEDGE.md exists or no sections match.
|
|
1085
|
+
*/
|
|
1086
|
+
export async function inlineKnowledgeScoped(
|
|
1087
|
+
base: string,
|
|
1088
|
+
keywords: string[],
|
|
1089
|
+
): Promise<string | null> {
|
|
1090
|
+
const knowledgePath = resolveGsdRootFile(base, "KNOWLEDGE");
|
|
1091
|
+
if (!existsSync(knowledgePath)) return null;
|
|
1092
|
+
|
|
1093
|
+
const content = await loadFile(knowledgePath);
|
|
1094
|
+
if (!content) return null;
|
|
1095
|
+
|
|
1096
|
+
// Import queryKnowledge from context-store
|
|
1097
|
+
const { queryKnowledge } = await import("./context-store.js");
|
|
1098
|
+
const scoped = await queryKnowledge(content, keywords);
|
|
1099
|
+
|
|
1100
|
+
// Return null if no sections matched (empty string from queryKnowledge)
|
|
1101
|
+
if (!scoped) return null;
|
|
1102
|
+
|
|
1103
|
+
return `### Project Knowledge (scoped)\nSource: \`${relGsdRootFile("KNOWLEDGE")}\`\n\n${scoped.trim()}`;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Budget-capped knowledge inline for milestone-level prompt assembly.
|
|
1108
|
+
*
|
|
1109
|
+
* Addresses issue #4719: the six milestone-phase prompts (research-milestone,
|
|
1110
|
+
* plan-milestone, complete-slice, complete-milestone, validate-milestone,
|
|
1111
|
+
* reassess-roadmap) previously injected the full KNOWLEDGE.md (~226KB for a
|
|
1112
|
+
* real project) on every invocation. This helper scopes by caller-supplied
|
|
1113
|
+
* keywords and caps the payload at `maxChars` (default 12,000 chars).
|
|
1114
|
+
*
|
|
1115
|
+
* Returns null when no KNOWLEDGE.md exists or no entries match any keyword.
|
|
1116
|
+
*/
|
|
1117
|
+
export async function inlineKnowledgeBudgeted(
|
|
1118
|
+
base: string,
|
|
1119
|
+
keywords: string[],
|
|
1120
|
+
options?: { maxChars?: number },
|
|
1121
|
+
): Promise<string | null> {
|
|
1122
|
+
const DEFAULT_MAX_CHARS = 12_000;
|
|
1123
|
+
const HARD_MAX_CHARS = 100_000;
|
|
1124
|
+
const raw = Number(options?.maxChars ?? DEFAULT_MAX_CHARS);
|
|
1125
|
+
const maxChars = Number.isFinite(raw)
|
|
1126
|
+
? Math.max(0, Math.min(Math.floor(raw), HARD_MAX_CHARS))
|
|
1127
|
+
: DEFAULT_MAX_CHARS;
|
|
1128
|
+
|
|
1129
|
+
const knowledgePath = resolveGsdRootFile(base, "KNOWLEDGE");
|
|
1130
|
+
if (!existsSync(knowledgePath)) return null;
|
|
1131
|
+
|
|
1132
|
+
const content = await loadFile(knowledgePath);
|
|
1133
|
+
if (!content) return null;
|
|
1134
|
+
|
|
1135
|
+
const { queryKnowledge } = await import("./context-store.js");
|
|
1136
|
+
const scoped = await queryKnowledge(content, keywords);
|
|
1137
|
+
if (!scoped) return null;
|
|
1138
|
+
|
|
1139
|
+
const trimmed = scoped.trim();
|
|
1140
|
+
const truncated =
|
|
1141
|
+
trimmed.length > maxChars
|
|
1142
|
+
? `${trimmed.slice(0, maxChars)}\n\n[...truncated ${trimmed.length - maxChars} chars; rerun with narrower scope if needed]`
|
|
1143
|
+
: trimmed;
|
|
1144
|
+
|
|
1145
|
+
return `### Project Knowledge (scoped)\nSource: \`${relGsdRootFile("KNOWLEDGE")}\`\n\n${truncated}`;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Inline a roadmap excerpt for a specific slice.
|
|
1150
|
+
* Reads full roadmap, extracts minimal excerpt with header + predecessor + target row.
|
|
1151
|
+
* Returns null if roadmap doesn't exist or slice not found.
|
|
1152
|
+
*/
|
|
1153
|
+
export async function inlineRoadmapExcerpt(
|
|
1154
|
+
base: string,
|
|
1155
|
+
mid: string,
|
|
1156
|
+
sid: string,
|
|
1157
|
+
): Promise<string | null> {
|
|
1158
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1159
|
+
if (!roadmapPath || !existsSync(roadmapPath)) return null;
|
|
1160
|
+
|
|
1161
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
1162
|
+
const content = await loadFile(roadmapPath);
|
|
1163
|
+
if (!content) return null;
|
|
1164
|
+
|
|
1165
|
+
// Import formatRoadmapExcerpt from context-store
|
|
1166
|
+
const { formatRoadmapExcerpt } = await import("./context-store.js");
|
|
1167
|
+
const excerpt = formatRoadmapExcerpt(content, sid, roadmapRel);
|
|
1168
|
+
|
|
1169
|
+
// Return null if slice not found in roadmap
|
|
1170
|
+
if (!excerpt) return null;
|
|
1171
|
+
|
|
1172
|
+
return `### Milestone Roadmap (excerpt)\nSource: \`${roadmapRel}\`\n\n${excerpt}`;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
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
|
+
// ─── Text Helpers ──────────────────────────────────────────────────────────
|
|
1457
|
+
|
|
1458
|
+
export function extractMarkdownSection(content: string, heading: string): string | null {
|
|
1459
|
+
const match = new RegExp(`^## ${escapeRegExp(heading)}\\s*$`, "m").exec(content);
|
|
1460
|
+
if (!match) return null;
|
|
1461
|
+
|
|
1462
|
+
const start = match.index + match[0].length;
|
|
1463
|
+
const rest = content.slice(start);
|
|
1464
|
+
const nextHeading = rest.match(/^##\s+/m);
|
|
1465
|
+
const end = nextHeading?.index ?? rest.length;
|
|
1466
|
+
return rest.slice(0, end).trim();
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
export function escapeRegExp(value: string): string {
|
|
1470
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
function oneLine(text: string): string {
|
|
1474
|
+
return text.replace(/\s+/g, " ").trim();
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
// ─── Section Builders ──────────────────────────────────────────────────────
|
|
1478
|
+
|
|
1479
|
+
export function buildResumeSection(
|
|
1480
|
+
continueContent: string | null,
|
|
1481
|
+
legacyContinueContent: string | null,
|
|
1482
|
+
continueRelPath: string,
|
|
1483
|
+
legacyContinueRelPath: string | null,
|
|
1484
|
+
): string {
|
|
1485
|
+
const resolvedContent = continueContent ?? legacyContinueContent;
|
|
1486
|
+
const resolvedRelPath = continueContent ? continueRelPath : legacyContinueRelPath;
|
|
1487
|
+
|
|
1488
|
+
if (!resolvedContent || !resolvedRelPath) {
|
|
1489
|
+
return ["## Resume State", "- No continue file present. Start from the top of the task plan."].join("\n");
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
const cont = parseContinue(resolvedContent);
|
|
1493
|
+
const lines = [
|
|
1494
|
+
"## Resume State",
|
|
1495
|
+
`Source: \`${resolvedRelPath}\``,
|
|
1496
|
+
`- Status: ${cont.frontmatter.status || "in_progress"}`,
|
|
1497
|
+
];
|
|
1498
|
+
|
|
1499
|
+
if (cont.frontmatter.step && cont.frontmatter.totalSteps) {
|
|
1500
|
+
lines.push(`- Progress: step ${cont.frontmatter.step} of ${cont.frontmatter.totalSteps}`);
|
|
1501
|
+
}
|
|
1502
|
+
if (cont.completedWork) lines.push(`- Completed: ${oneLine(cont.completedWork)}`);
|
|
1503
|
+
if (cont.remainingWork) lines.push(`- Remaining: ${oneLine(cont.remainingWork)}`);
|
|
1504
|
+
if (cont.decisions) lines.push(`- Decisions: ${oneLine(cont.decisions)}`);
|
|
1505
|
+
if (cont.nextAction) lines.push(`- Next action: ${oneLine(cont.nextAction)}`);
|
|
1506
|
+
|
|
1507
|
+
return lines.join("\n");
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
export async function buildCarryForwardSection(priorSummaryPaths: string[], base: string): Promise<string> {
|
|
1511
|
+
if (priorSummaryPaths.length === 0) {
|
|
1512
|
+
return ["## Carry-Forward Context", "- No prior task summaries in this slice."].join("\n");
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
const items = await Promise.all(priorSummaryPaths.map(async (relPath) => {
|
|
1516
|
+
const absPath = join(base, relPath);
|
|
1517
|
+
const content = await loadFile(absPath);
|
|
1518
|
+
if (!content) return `- \`${relPath}\``;
|
|
1519
|
+
|
|
1520
|
+
const summary = parseSummary(content);
|
|
1521
|
+
const provided = summary.frontmatter.provides.slice(0, 2).join("; ");
|
|
1522
|
+
const decisions = summary.frontmatter.key_decisions.slice(0, 2).join("; ");
|
|
1523
|
+
const patterns = summary.frontmatter.patterns_established.slice(0, 2).join("; ");
|
|
1524
|
+
const keyFiles = summary.frontmatter.key_files.slice(0, 3).join("; ");
|
|
1525
|
+
const diagnostics = extractMarkdownSection(content, "Diagnostics");
|
|
1526
|
+
|
|
1527
|
+
const parts = [summary.title || relPath];
|
|
1528
|
+
if (summary.oneLiner) parts.push(summary.oneLiner);
|
|
1529
|
+
if (provided) parts.push(`provides: ${provided}`);
|
|
1530
|
+
if (decisions) parts.push(`decisions: ${decisions}`);
|
|
1531
|
+
if (patterns) parts.push(`patterns: ${patterns}`);
|
|
1532
|
+
if (keyFiles) parts.push(`key_files: ${keyFiles}`);
|
|
1533
|
+
if (diagnostics) parts.push(`diagnostics: ${oneLine(diagnostics)}`);
|
|
1534
|
+
|
|
1535
|
+
return `- \`${relPath}\` — ${parts.join(" | ")}`;
|
|
1536
|
+
}));
|
|
1537
|
+
|
|
1538
|
+
return ["## Carry-Forward Context", ...items].join("\n");
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
export function extractSliceExecutionExcerpt(content: string | null, relPath: string): string {
|
|
1542
|
+
if (!content) {
|
|
1543
|
+
return [
|
|
1544
|
+
"## Slice Plan Excerpt",
|
|
1545
|
+
`Slice plan not found at dispatch time. Read \`${relPath}\` before running slice-level verification.`,
|
|
1546
|
+
].join("\n");
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
const lines = content.split("\n");
|
|
1550
|
+
const goalLine = lines.find(l => l.startsWith("**Goal:**"))?.trim();
|
|
1551
|
+
const demoLine = lines.find(l => l.startsWith("**Demo:**"))?.trim();
|
|
1552
|
+
|
|
1553
|
+
const verification = extractMarkdownSection(content, "Verification");
|
|
1554
|
+
const observability = extractMarkdownSection(content, "Observability / Diagnostics");
|
|
1555
|
+
|
|
1556
|
+
const parts = ["## Slice Plan Excerpt", `Source: \`${relPath}\``];
|
|
1557
|
+
if (goalLine) parts.push(goalLine);
|
|
1558
|
+
if (demoLine) parts.push(demoLine);
|
|
1559
|
+
if (verification) {
|
|
1560
|
+
parts.push("", "### Slice Verification", verification.trim());
|
|
1561
|
+
}
|
|
1562
|
+
if (observability) {
|
|
1563
|
+
parts.push("", "### Slice Observability / Diagnostics", observability.trim());
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
return parts.join("\n");
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
// ─── Prior Task Summaries ──────────────────────────────────────────────────
|
|
1570
|
+
|
|
1571
|
+
export async function getPriorTaskSummaryPaths(
|
|
1572
|
+
mid: string, sid: string, currentTid: string, base: string,
|
|
1573
|
+
): Promise<string[]> {
|
|
1574
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
1575
|
+
if (!tDir) return [];
|
|
1576
|
+
|
|
1577
|
+
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY");
|
|
1578
|
+
const currentNum = parseInt(currentTid.replace(/^T/, ""), 10);
|
|
1579
|
+
const sRel = relSlicePath(base, mid, sid);
|
|
1580
|
+
|
|
1581
|
+
return summaryFiles
|
|
1582
|
+
.filter(f => {
|
|
1583
|
+
const num = parseInt(f.replace(/^T/, ""), 10);
|
|
1584
|
+
return num < currentNum;
|
|
1585
|
+
})
|
|
1586
|
+
.map(f => `${sRel}/tasks/${f}`);
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Get carry-forward summary paths scoped to a task's derived dependencies.
|
|
1591
|
+
*
|
|
1592
|
+
* Instead of all prior tasks (order-based), returns only summaries for task
|
|
1593
|
+
* IDs in `dependsOn`. Used by reactive-execute to give each subagent only
|
|
1594
|
+
* the context it actually needs — not sibling tasks from a parallel batch.
|
|
1595
|
+
*
|
|
1596
|
+
* Falls back to order-based when dependsOn is empty (root tasks still get
|
|
1597
|
+
* any available prior summaries for continuity).
|
|
1598
|
+
*/
|
|
1599
|
+
export async function getDependencyTaskSummaryPaths(
|
|
1600
|
+
mid: string, sid: string, currentTid: string,
|
|
1601
|
+
dependsOn: string[], base: string,
|
|
1602
|
+
): Promise<string[]> {
|
|
1603
|
+
// If no dependencies, fall back to order-based for root tasks
|
|
1604
|
+
if (dependsOn.length === 0) {
|
|
1605
|
+
return getPriorTaskSummaryPaths(mid, sid, currentTid, base);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
1609
|
+
if (!tDir) return [];
|
|
1610
|
+
|
|
1611
|
+
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY");
|
|
1612
|
+
const sRel = relSlicePath(base, mid, sid);
|
|
1613
|
+
const depSet = new Set(dependsOn.map((d) => d.toUpperCase()));
|
|
1614
|
+
|
|
1615
|
+
return summaryFiles
|
|
1616
|
+
.filter((f) => {
|
|
1617
|
+
// Extract task ID from filename: "T02-SUMMARY.md" → "T02"
|
|
1618
|
+
const tid = f.replace(/-SUMMARY\.md$/i, "").toUpperCase();
|
|
1619
|
+
return depSet.has(tid);
|
|
1620
|
+
})
|
|
1621
|
+
.map((f) => `${sRel}/tasks/${f}`);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
// ─── Adaptive Replanning Checks ────────────────────────────────────────────
|
|
1625
|
+
|
|
1626
|
+
/**
|
|
1627
|
+
* Check if the most recently completed slice needs reassessment.
|
|
1628
|
+
* Returns { sliceId } if reassessment is needed, null otherwise.
|
|
1629
|
+
*
|
|
1630
|
+
* Skips reassessment when:
|
|
1631
|
+
* - No roadmap exists yet
|
|
1632
|
+
* - No slices are completed
|
|
1633
|
+
* - The last completed slice already has an assessment file
|
|
1634
|
+
* - All slices are complete (milestone done — no point reassessing)
|
|
1635
|
+
*/
|
|
1636
|
+
export async function checkNeedsReassessment(
|
|
1637
|
+
base: string, mid: string, state: GSDState,
|
|
1638
|
+
): Promise<{ sliceId: string } | null> {
|
|
1639
|
+
// DB primary path — fall through to file-based when DB has no data for this milestone
|
|
1640
|
+
try {
|
|
1641
|
+
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
1642
|
+
if (isDbAvailable()) {
|
|
1643
|
+
const slices = getMilestoneSlices(mid);
|
|
1644
|
+
if (slices.length > 0) {
|
|
1645
|
+
const completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
|
|
1646
|
+
const hasIncomplete = slices.some(s => s.status !== "complete");
|
|
1647
|
+
if (completedSliceIds.length === 0 || !hasIncomplete) return null;
|
|
1648
|
+
const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
|
|
1649
|
+
const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
|
|
1650
|
+
const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
|
|
1651
|
+
if (hasAssessment) return null;
|
|
1652
|
+
const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
|
|
1653
|
+
const hasSummary = !!(summaryFile && await loadFile(summaryFile));
|
|
1654
|
+
if (!hasSummary) return null;
|
|
1655
|
+
return { sliceId: lastCompleted };
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
} catch (err) {
|
|
1659
|
+
logWarning("prompt", `checkNeedsReassessment DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
// File-based fallback using roadmap checkboxes
|
|
1663
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1664
|
+
if (!roadmapPath) return null;
|
|
1665
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
1666
|
+
if (!roadmapContent) return null;
|
|
1667
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
1668
|
+
const fileCompletedIds = parsed.slices.filter(s => s.done).map(s => s.id);
|
|
1669
|
+
const fileHasIncomplete = parsed.slices.some(s => !s.done);
|
|
1670
|
+
if (fileCompletedIds.length === 0 || !fileHasIncomplete) return null;
|
|
1671
|
+
const lastDone = fileCompletedIds[fileCompletedIds.length - 1];
|
|
1672
|
+
const assessFile = resolveSliceFile(base, mid, lastDone, "ASSESSMENT");
|
|
1673
|
+
const hasAssess = !!(assessFile && await loadFile(assessFile));
|
|
1674
|
+
if (hasAssess) return null;
|
|
1675
|
+
const summFile = resolveSliceFile(base, mid, lastDone, "SUMMARY");
|
|
1676
|
+
const hasSumm = !!(summFile && await loadFile(summFile));
|
|
1677
|
+
if (!hasSumm) return null;
|
|
1678
|
+
return { sliceId: lastDone };
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
/**
|
|
1682
|
+
* Check if the most recently completed slice needs a UAT run.
|
|
1683
|
+
* Returns { sliceId, uatType } if UAT should be dispatched, null otherwise.
|
|
1684
|
+
*
|
|
1685
|
+
* Skips when:
|
|
1686
|
+
* - No roadmap or no completed slices
|
|
1687
|
+
* - uat_dispatch is not enabled and the UAT spec does not require runtime/browser evidence
|
|
1688
|
+
* - No UAT file exists for the slice
|
|
1689
|
+
* - UAT result file already exists (idempotent — already ran)
|
|
1690
|
+
*/
|
|
1691
|
+
export async function checkNeedsRunUat(
|
|
1692
|
+
base: string, mid: string, state: GSDState, prefs: GSDPreferences | undefined,
|
|
1693
|
+
): Promise<{ sliceId: string; uatType: UatType } | null> {
|
|
1694
|
+
// DB primary path — fall through to file-based when DB has no data for this milestone
|
|
1695
|
+
try {
|
|
1696
|
+
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
1697
|
+
if (isDbAvailable()) {
|
|
1698
|
+
const slices = getMilestoneSlices(mid);
|
|
1699
|
+
if (slices.length > 0) {
|
|
1700
|
+
const completedSlices = slices.filter(s => s.status === "complete");
|
|
1701
|
+
if (completedSlices.length === 0) return null;
|
|
1702
|
+
for (const completed of [...completedSlices].reverse()) {
|
|
1703
|
+
const sid = completed.id;
|
|
1704
|
+
const uatFile = resolveSliceFile(base, mid, sid, "UAT");
|
|
1705
|
+
if (!uatFile) continue;
|
|
1706
|
+
const uatContent = await loadFile(uatFile);
|
|
1707
|
+
if (!uatContent) continue;
|
|
1708
|
+
// If the UAT file already contains a verdict, UAT has been run — skip
|
|
1709
|
+
if (hasVerdict(uatContent)) continue;
|
|
1710
|
+
// Also check the ASSESSMENT file — the run-uat prompt writes the verdict
|
|
1711
|
+
// there (via gsd_summary_save artifact_type:"ASSESSMENT"), not into the
|
|
1712
|
+
// UAT spec file. Without this check the unit re-dispatches indefinitely.
|
|
1713
|
+
const assessmentFile = resolveSliceFile(base, mid, sid, "ASSESSMENT");
|
|
1714
|
+
if (assessmentFile) {
|
|
1715
|
+
const assessmentContent = await loadFile(assessmentFile);
|
|
1716
|
+
if (assessmentContent && hasVerdict(assessmentContent)) continue;
|
|
1717
|
+
}
|
|
1718
|
+
if (!shouldDispatchUatForContent(uatContent, prefs)) continue;
|
|
1719
|
+
return { sliceId: sid, uatType: resolveEffectiveUatType(uatContent) };
|
|
1720
|
+
}
|
|
1721
|
+
return null;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
} catch (err) {
|
|
1725
|
+
logWarning("prompt", `checkNeedsRunUat DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// File-based fallback using roadmap checkboxes
|
|
1729
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1730
|
+
if (!roadmapPath) return null;
|
|
1731
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
1732
|
+
if (!roadmapContent) return null;
|
|
1733
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
1734
|
+
const completedFileSlices = parsed.slices.filter(s => s.done);
|
|
1735
|
+
if (completedFileSlices.length === 0) return null;
|
|
1736
|
+
for (const completed of [...completedFileSlices].reverse()) {
|
|
1737
|
+
const uatSid = completed.id;
|
|
1738
|
+
const uatFileFb = resolveSliceFile(base, mid, uatSid, "UAT");
|
|
1739
|
+
if (!uatFileFb) continue;
|
|
1740
|
+
const uatContentFb = await loadFile(uatFileFb);
|
|
1741
|
+
if (!uatContentFb) continue;
|
|
1742
|
+
// If the UAT file already contains a verdict, UAT has been run — skip
|
|
1743
|
+
if (hasVerdict(uatContentFb)) continue;
|
|
1744
|
+
// Also check the ASSESSMENT file for the file-based fallback path (same
|
|
1745
|
+
// reason as the DB path above — verdict lives in ASSESSMENT, not UAT).
|
|
1746
|
+
const assessmentFileFb = resolveSliceFile(base, mid, uatSid, "ASSESSMENT");
|
|
1747
|
+
if (assessmentFileFb) {
|
|
1748
|
+
const assessmentContentFb = await loadFile(assessmentFileFb);
|
|
1749
|
+
if (assessmentContentFb && hasVerdict(assessmentContentFb)) continue;
|
|
1750
|
+
}
|
|
1751
|
+
if (!shouldDispatchUatForContent(uatContentFb, prefs)) continue;
|
|
1752
|
+
return { sliceId: uatSid, uatType: resolveEffectiveUatType(uatContentFb) };
|
|
1753
|
+
}
|
|
1754
|
+
return null;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
// ─── Prompt Builders ──────────────────────────────────────────────────────
|
|
1758
|
+
|
|
1759
|
+
/**
|
|
1760
|
+
* Build a prompt for the discuss-milestone unit type.
|
|
1761
|
+
* Loads the guided-discuss-milestone template and inlines the CONTEXT-DRAFT
|
|
1762
|
+
* as a seed when present. The discussion agent interviews the user, writes
|
|
1763
|
+
* a full CONTEXT.md, and the phase transitions to pre-planning automatically.
|
|
1764
|
+
*/
|
|
1765
|
+
export async function buildDiscussMilestonePrompt(
|
|
1766
|
+
mid: string,
|
|
1767
|
+
midTitle: string,
|
|
1768
|
+
base: string,
|
|
1769
|
+
structuredQuestionsAvailable = "false",
|
|
1770
|
+
{ headless = false }: { headless?: boolean } = {},
|
|
1771
|
+
): Promise<string> {
|
|
1772
|
+
const discussTemplates = inlineTemplate("context", "Context");
|
|
1773
|
+
|
|
1774
|
+
if (headless) {
|
|
1775
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
1776
|
+
const roadmapContent = roadmapPath ? await loadFile(roadmapPath) : null;
|
|
1777
|
+
return loadPrompt("discuss-headless", {
|
|
1778
|
+
seedContext: roadmapContent ?? "",
|
|
1779
|
+
inlinedTemplates: discussTemplates,
|
|
1780
|
+
workingDirectory: base,
|
|
1781
|
+
milestoneId: mid,
|
|
1782
|
+
contextPath: relMilestoneFile(base, mid, "CONTEXT"),
|
|
1783
|
+
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1784
|
+
multiMilestoneCommitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
const contextModeInstructions = renderContextModeForPrompt("discuss-milestone", base);
|
|
1789
|
+
|
|
1790
|
+
const basePrompt = loadPrompt("guided-discuss-milestone", {
|
|
1791
|
+
workingDirectory: base,
|
|
1792
|
+
milestoneId: mid,
|
|
1793
|
+
milestoneTitle: midTitle,
|
|
1794
|
+
inlinedTemplates: discussTemplates,
|
|
1795
|
+
structuredQuestionsAvailable,
|
|
1796
|
+
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1797
|
+
fastPathInstruction: "",
|
|
1798
|
+
});
|
|
1799
|
+
const promptWithContextMode = prependContextModeToBlock("discuss-milestone", base, basePrompt);
|
|
1800
|
+
|
|
1801
|
+
// If a CONTEXT-DRAFT.md exists, append it as seed material
|
|
1802
|
+
const draftPath = resolveMilestoneFile(base, mid, "CONTEXT-DRAFT");
|
|
1803
|
+
const draftContent = draftPath ? await loadFile(draftPath) : null;
|
|
1804
|
+
|
|
1805
|
+
if (draftContent) {
|
|
1806
|
+
return `${promptWithContextMode}\n\n## Prior Discussion (Draft Seed)\n\nThe following draft was captured from a prior multi-milestone discussion. Use it as seed material — the user has already provided this context. Start with a brief reflection on what the draft covers, then probe for any gaps or open questions before writing the full CONTEXT.md.\n\n${draftContent}`;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
return contextModeInstructions ? promptWithContextMode : basePrompt;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Build a prompt for the workflow-preferences unit type (deep mode).
|
|
1814
|
+
* Default-writing stage: records high-impact workflow defaults in
|
|
1815
|
+
* .gsd/PREFERENCES.md. Runs ONCE per project, early
|
|
1816
|
+
* in deep-mode bootstrap before discuss-project.
|
|
1817
|
+
*/
|
|
1818
|
+
export async function buildWorkflowPreferencesPrompt(
|
|
1819
|
+
base: string,
|
|
1820
|
+
structuredQuestionsAvailable = "false",
|
|
1821
|
+
): Promise<string> {
|
|
1822
|
+
return prependContextModeToBlock("workflow-preferences", base, loadPrompt("guided-workflow-preferences", {
|
|
1823
|
+
workingDirectory: base,
|
|
1824
|
+
structuredQuestionsAvailable,
|
|
1825
|
+
}));
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
/**
|
|
1829
|
+
* Build a prompt for the research-project (parallel) unit type (deep mode).
|
|
1830
|
+
* Orchestrator that spawns 4 parallel Task() calls covering stack, features,
|
|
1831
|
+
* architecture, and pitfalls. Each subagent writes its findings to .gsd/research/.
|
|
1832
|
+
* Fires after research-decision marker says "research" and project research files
|
|
1833
|
+
* are missing. Skipped entirely if user picked "skip".
|
|
1834
|
+
*/
|
|
1835
|
+
export async function buildResearchProjectPrompt(
|
|
1836
|
+
base: string,
|
|
1837
|
+
structuredQuestionsAvailable = "false",
|
|
1838
|
+
): Promise<string> {
|
|
1839
|
+
return prependContextModeToBlock("research-project", base, loadPrompt("guided-research-project", {
|
|
1840
|
+
workingDirectory: base,
|
|
1841
|
+
structuredQuestionsAvailable,
|
|
1842
|
+
}));
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* Build a prompt for the research-decision unit type (deep mode).
|
|
1847
|
+
* Fixed-question stage: asks "research first or skip?" via ask_user_questions
|
|
1848
|
+
* and writes .gsd/runtime/research-decision.json. Fires after discuss-requirements
|
|
1849
|
+
* and before research-project-parallel.
|
|
1850
|
+
*/
|
|
1851
|
+
export async function buildResearchDecisionPrompt(
|
|
1852
|
+
base: string,
|
|
1853
|
+
structuredQuestionsAvailable = "false",
|
|
1854
|
+
): Promise<string> {
|
|
1855
|
+
return prependContextModeToBlock("research-decision", base, loadPrompt("guided-research-decision", {
|
|
1856
|
+
workingDirectory: base,
|
|
1857
|
+
structuredQuestionsAvailable,
|
|
1858
|
+
}));
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* Build a prompt for the discuss-project unit type (deep mode).
|
|
1863
|
+
* Project-level interview: produces .gsd/PROJECT.md.
|
|
1864
|
+
* Fires before any milestone-level work when planning_depth === "deep" and
|
|
1865
|
+
* PROJECT.md is missing.
|
|
1866
|
+
*/
|
|
1867
|
+
export async function buildDiscussProjectPrompt(
|
|
1868
|
+
base: string,
|
|
1869
|
+
structuredQuestionsAvailable = "false",
|
|
1870
|
+
): Promise<string> {
|
|
1871
|
+
const inlinedTemplates = inlineTemplate("project", "Project");
|
|
1872
|
+
|
|
1873
|
+
return prependContextModeToBlock("discuss-project", base, loadPrompt("guided-discuss-project", {
|
|
1874
|
+
workingDirectory: base,
|
|
1875
|
+
inlinedTemplates,
|
|
1876
|
+
structuredQuestionsAvailable,
|
|
1877
|
+
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1878
|
+
}));
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
/**
|
|
1882
|
+
* Build a prompt for the discuss-requirements unit type (deep mode).
|
|
1883
|
+
* Requirements-level interview: produces .gsd/REQUIREMENTS.md using the
|
|
1884
|
+
* structured R### format. Reads PROJECT.md as authoritative context.
|
|
1885
|
+
* Fires when planning_depth === "deep", PROJECT.md exists, and REQUIREMENTS.md is missing.
|
|
1886
|
+
*/
|
|
1887
|
+
export async function buildDiscussRequirementsPrompt(
|
|
1888
|
+
base: string,
|
|
1889
|
+
structuredQuestionsAvailable = "false",
|
|
1890
|
+
): Promise<string> {
|
|
1891
|
+
const inlinedTemplates = inlineTemplate("requirements", "Requirements");
|
|
1892
|
+
|
|
1893
|
+
return prependContextModeToBlock("discuss-requirements", base, loadPrompt("guided-discuss-requirements", {
|
|
1894
|
+
workingDirectory: base,
|
|
1895
|
+
inlinedTemplates,
|
|
1896
|
+
structuredQuestionsAvailable,
|
|
1897
|
+
commitInstruction: "Do not commit planning artifacts — .gsd/ is managed externally.",
|
|
1898
|
+
}));
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
export async function buildResearchMilestonePrompt(mid: string, midTitle: string, base: string): Promise<string> {
|
|
1902
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
1903
|
+
|
|
1904
|
+
// Keep research milestone prompts focused on the milestone brief and
|
|
1905
|
+
// research template. Project-wide docs stay on-demand instead of being
|
|
1906
|
+
// loaded at the start of every milestone.
|
|
1907
|
+
const resolveArtifact: ArtifactResolver = async (key) => {
|
|
1908
|
+
switch (key) {
|
|
1909
|
+
case "milestone-context": {
|
|
1910
|
+
const p = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
1911
|
+
const r = relMilestoneFile(base, mid, "CONTEXT");
|
|
1912
|
+
const body = await inlineFile(p, r, "Milestone Context");
|
|
1913
|
+
trackPromptContext(contextTelemetry, "milestone-context", "inline", body);
|
|
1914
|
+
return body;
|
|
1915
|
+
}
|
|
1916
|
+
case "project":
|
|
1917
|
+
case "requirements":
|
|
1918
|
+
case "decisions":
|
|
1919
|
+
trackPromptContext(contextTelemetry, key, "skipped", null, "handled as on-demand path");
|
|
1920
|
+
return null;
|
|
1921
|
+
case "templates": {
|
|
1922
|
+
const body = inlineTemplate("research", "Research");
|
|
1923
|
+
trackPromptContext(contextTelemetry, "templates", "inline", body);
|
|
1924
|
+
return body;
|
|
1925
|
+
}
|
|
1926
|
+
default:
|
|
1927
|
+
return null;
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
|
|
1931
|
+
const composed = await composeUnitContext("research-milestone", {
|
|
1932
|
+
base: { unitType: "research-milestone", basePath: base, milestoneId: mid },
|
|
1933
|
+
resolveArtifact,
|
|
1934
|
+
});
|
|
1935
|
+
|
|
1936
|
+
// Knowledge block stays outside the composer — budgeted, scoped via
|
|
1937
|
+
// keyword extraction (#4719). Inserted before the template so research
|
|
1938
|
+
// instructions remain the final contract in the preloaded block.
|
|
1939
|
+
const knowledgeInlineRM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
|
|
1940
|
+
const parts: string[] = [];
|
|
1941
|
+
if (composed.prepend) parts.push(composed.prepend);
|
|
1942
|
+
if (knowledgeInlineRM && composed.inline) {
|
|
1943
|
+
const idx = composed.inline.lastIndexOf("### Output Template:");
|
|
1944
|
+
if (idx > 0) {
|
|
1945
|
+
const before = composed.inline.slice(0, idx).replace(/\n\n---\n\n$/, "");
|
|
1946
|
+
const after = composed.inline.slice(idx);
|
|
1947
|
+
parts.push(before, knowledgeInlineRM, after);
|
|
1948
|
+
} else {
|
|
1949
|
+
parts.push(composed.inline, knowledgeInlineRM);
|
|
1950
|
+
}
|
|
1951
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInlineRM);
|
|
1952
|
+
} else if (composed.inline) {
|
|
1953
|
+
parts.push(composed.inline);
|
|
1954
|
+
if (knowledgeInlineRM) parts.push(knowledgeInlineRM);
|
|
1955
|
+
trackPromptContext(contextTelemetry, "knowledge", knowledgeInlineRM ? "inline" : "skipped", knowledgeInlineRM, knowledgeInlineRM ? undefined : "missing");
|
|
1956
|
+
} else {
|
|
1957
|
+
trackPromptContext(contextTelemetry, "knowledge", knowledgeInlineRM ? "inline" : "skipped", knowledgeInlineRM, knowledgeInlineRM ? undefined : "missing");
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
const onDemandDocs = [
|
|
1961
|
+
"### On-demand Planning Context",
|
|
1962
|
+
"",
|
|
1963
|
+
"Broader project context is available if the research needs it. Read only the specific source that answers the question:",
|
|
1964
|
+
"",
|
|
1965
|
+
`- \`${relGsdRootFile("PROJECT")}\` — product/project narrative`,
|
|
1966
|
+
`- \`${relGsdRootFile("REQUIREMENTS")}\` — requirement status and acceptance criteria`,
|
|
1967
|
+
`- \`${relGsdRootFile("DECISIONS")}\` — active architecture/product decisions`,
|
|
1968
|
+
].join("\n");
|
|
1969
|
+
parts.push(onDemandDocs);
|
|
1970
|
+
trackPromptContext(contextTelemetry, "project,requirements,decisions", "on-demand", onDemandDocs);
|
|
1971
|
+
|
|
1972
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${parts.join("\n\n---\n\n")}`;
|
|
1973
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
1974
|
+
trackPromptContext(
|
|
1975
|
+
contextTelemetry,
|
|
1976
|
+
"cap",
|
|
1977
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
1978
|
+
null,
|
|
1979
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
1980
|
+
);
|
|
1981
|
+
|
|
1982
|
+
const inlinedContext = prependContextModeToBlock(
|
|
1983
|
+
"research-milestone",
|
|
1984
|
+
base,
|
|
1985
|
+
cappedInlinedContext,
|
|
1986
|
+
);
|
|
1987
|
+
emitPromptContextTelemetry("research-milestone", contextTelemetry, inlinedContext);
|
|
1988
|
+
|
|
1989
|
+
const outputRelPath = relMilestoneFile(base, mid, "RESEARCH");
|
|
1990
|
+
return loadPrompt("research-milestone", {
|
|
1991
|
+
workingDirectory: base,
|
|
1992
|
+
milestoneId: mid, milestoneTitle: midTitle,
|
|
1993
|
+
milestonePath: relMilestonePath(base, mid),
|
|
1994
|
+
contextPath: relMilestoneFile(base, mid, "CONTEXT"),
|
|
1995
|
+
outputPath: join(base, outputRelPath),
|
|
1996
|
+
inlinedContext,
|
|
1997
|
+
skillActivation: buildSkillActivationBlock({
|
|
1998
|
+
base,
|
|
1999
|
+
milestoneId: mid,
|
|
2000
|
+
milestoneTitle: midTitle,
|
|
2001
|
+
extraContext: [inlinedContext],
|
|
2002
|
+
unitType: "research-milestone",
|
|
2003
|
+
}),
|
|
2004
|
+
...buildSkillDiscoveryVars(),
|
|
2005
|
+
});
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
export async function buildPlanMilestonePrompt(mid: string, midTitle: string, base: string, level?: InlineLevel): Promise<string> {
|
|
2009
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
2010
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
2011
|
+
const contextRel = relMilestoneFile(base, mid, "CONTEXT");
|
|
2012
|
+
const researchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
2013
|
+
const researchRel = relMilestoneFile(base, mid, "RESEARCH");
|
|
2014
|
+
|
|
2015
|
+
const inlined: string[] = [];
|
|
2016
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
2017
|
+
const pushTracked = (key: string, body: string, reason?: string): void => {
|
|
2018
|
+
inlined.push(body);
|
|
2019
|
+
trackPromptContext(contextTelemetry, key, "inline", body, reason);
|
|
2020
|
+
};
|
|
2021
|
+
|
|
2022
|
+
// Inject phase handoff anchor from research phase (if available)
|
|
2023
|
+
const researchAnchor = readPhaseAnchor(base, mid, "research-milestone");
|
|
2024
|
+
if (researchAnchor) {
|
|
2025
|
+
pushTracked("research-anchor", formatAnchorForPrompt(researchAnchor));
|
|
2026
|
+
} else {
|
|
2027
|
+
trackPromptContext(contextTelemetry, "research-anchor", "skipped", null, "missing");
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
pushTracked("project-classification", formatProjectClassificationForPlanning(classifyProject(base)));
|
|
2031
|
+
|
|
2032
|
+
pushTracked("milestone-context", await inlineFile(contextPath, contextRel, "Milestone Context"));
|
|
2033
|
+
const researchInline = await inlineFileOptional(researchPath, researchRel, "Milestone Research");
|
|
2034
|
+
if (researchInline) {
|
|
2035
|
+
pushTracked("milestone-research", researchInline);
|
|
2036
|
+
} else {
|
|
2037
|
+
trackPromptContext(contextTelemetry, "milestone-research", "skipped", null, "missing");
|
|
2038
|
+
}
|
|
2039
|
+
const { inlinePriorMilestoneSummary } = await import("./files.js");
|
|
2040
|
+
const priorSummaryInline = await inlinePriorMilestoneSummary(mid, base);
|
|
2041
|
+
if (priorSummaryInline) {
|
|
2042
|
+
pushTracked("prior-milestone-summary", priorSummaryInline);
|
|
2043
|
+
} else {
|
|
2044
|
+
trackPromptContext(contextTelemetry, "prior-milestone-summary", "skipped", null, "missing");
|
|
2045
|
+
}
|
|
2046
|
+
if (inlineLevel === "full") {
|
|
2047
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
2048
|
+
if (projectInline) {
|
|
2049
|
+
pushTracked("project", projectInline, inlineLevel);
|
|
2050
|
+
} else {
|
|
2051
|
+
trackPromptContext(contextTelemetry, "project", "skipped", null, "missing");
|
|
2052
|
+
}
|
|
2053
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
2054
|
+
if (requirementsInline) {
|
|
2055
|
+
pushTracked("requirements", requirementsInline, inlineLevel);
|
|
2056
|
+
} else {
|
|
2057
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "missing");
|
|
2058
|
+
}
|
|
2059
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
2060
|
+
if (decisionsInline) {
|
|
2061
|
+
pushTracked("decisions", decisionsInline, inlineLevel);
|
|
2062
|
+
} else {
|
|
2063
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, "missing");
|
|
2064
|
+
}
|
|
2065
|
+
} else if (inlineLevel === "standard") {
|
|
2066
|
+
trackPromptContext(contextTelemetry, "project", "skipped", null, "handled as on-demand path");
|
|
2067
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
2068
|
+
if (requirementsInline) {
|
|
2069
|
+
pushTracked("requirements", requirementsInline, inlineLevel);
|
|
2070
|
+
} else {
|
|
2071
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "missing");
|
|
2072
|
+
}
|
|
2073
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, "handled as on-demand path");
|
|
2074
|
+
} else {
|
|
2075
|
+
trackPromptContext(contextTelemetry, "project", "skipped", null, "handled as on-demand path");
|
|
2076
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "minimal inline level");
|
|
2077
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, "handled as on-demand path");
|
|
2078
|
+
}
|
|
2079
|
+
if (inlineLevel !== "full") {
|
|
2080
|
+
const onDemandDocs = [
|
|
2081
|
+
"### On-demand Planning Context",
|
|
2082
|
+
"",
|
|
2083
|
+
"Broader project context is available if roadmap planning needs it. Read only the source that answers the planning question:",
|
|
2084
|
+
"",
|
|
2085
|
+
`- \`${relGsdRootFile("PROJECT")}\` - product/project narrative`,
|
|
2086
|
+
`- \`${relGsdRootFile("DECISIONS")}\` - active architecture/product decisions`,
|
|
2087
|
+
].join("\n");
|
|
2088
|
+
inlined.push(onDemandDocs);
|
|
2089
|
+
trackPromptContext(contextTelemetry, "project,decisions", "on-demand", onDemandDocs);
|
|
2090
|
+
}
|
|
2091
|
+
const queuePath = resolveGsdRootFile(base, "QUEUE");
|
|
2092
|
+
if (existsSync(queuePath)) {
|
|
2093
|
+
const queueInline = await inlineFileSmart(
|
|
2094
|
+
queuePath,
|
|
2095
|
+
relGsdRootFile("QUEUE"),
|
|
2096
|
+
"Project Queue",
|
|
2097
|
+
`${mid} ${midTitle}`,
|
|
2098
|
+
);
|
|
2099
|
+
pushTracked("project-queue", queueInline);
|
|
2100
|
+
} else {
|
|
2101
|
+
trackPromptContext(contextTelemetry, "project-queue", "skipped", null, "missing");
|
|
2102
|
+
}
|
|
2103
|
+
// Scoped + budgeted — see issue #4719
|
|
2104
|
+
const knowledgeInlinePM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
|
|
2105
|
+
if (knowledgeInlinePM) {
|
|
2106
|
+
pushTracked("knowledge", knowledgeInlinePM);
|
|
2107
|
+
} else {
|
|
2108
|
+
trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
|
|
2109
|
+
}
|
|
2110
|
+
pushTracked("templates", inlineTemplate("roadmap", "Roadmap"));
|
|
2111
|
+
if (inlineLevel === "full") {
|
|
2112
|
+
pushTracked("templates", inlineTemplate("decisions", "Decisions"));
|
|
2113
|
+
pushTracked("templates", inlineTemplate("plan", "Slice Plan"));
|
|
2114
|
+
pushTracked("templates", inlineTemplate("task-plan", "Task Plan"));
|
|
2115
|
+
pushTracked("templates", inlineTemplate("secrets-manifest", "Secrets Manifest"));
|
|
2116
|
+
} else if (inlineLevel === "standard") {
|
|
2117
|
+
pushTracked("templates", inlineTemplate("decisions", "Decisions"));
|
|
2118
|
+
pushTracked("templates", inlineTemplate("plan", "Slice Plan"));
|
|
2119
|
+
pushTracked("templates", inlineTemplate("task-plan", "Task Plan"));
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
2123
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
2124
|
+
trackPromptContext(
|
|
2125
|
+
contextTelemetry,
|
|
2126
|
+
"cap",
|
|
2127
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
2128
|
+
null,
|
|
2129
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
2130
|
+
);
|
|
2131
|
+
const inlinedContext = prependContextModeToBlock(
|
|
2132
|
+
"plan-milestone",
|
|
2133
|
+
base,
|
|
2134
|
+
cappedInlinedContext,
|
|
2135
|
+
);
|
|
2136
|
+
emitPromptContextTelemetry("plan-milestone", contextTelemetry, inlinedContext);
|
|
2137
|
+
|
|
2138
|
+
const outputRelPath = relMilestoneFile(base, mid, "ROADMAP");
|
|
2139
|
+
const researchOutputPath = join(base, relMilestoneFile(base, mid, "RESEARCH"));
|
|
2140
|
+
const secretsOutputPath = join(base, relMilestoneFile(base, mid, "SECRETS"));
|
|
2141
|
+
return loadPrompt("plan-milestone", {
|
|
2142
|
+
workingDirectory: base,
|
|
2143
|
+
milestoneId: mid, milestoneTitle: midTitle,
|
|
2144
|
+
milestonePath: relMilestonePath(base, mid),
|
|
2145
|
+
contextPath: contextRel,
|
|
2146
|
+
researchPath: researchRel,
|
|
2147
|
+
researchOutputPath,
|
|
2148
|
+
outputPath: join(base, outputRelPath),
|
|
2149
|
+
secretsOutputPath,
|
|
2150
|
+
inlinedContext,
|
|
2151
|
+
sourceFilePaths: buildSourceFilePaths(base, mid),
|
|
2152
|
+
skillActivation: buildSkillActivationBlock({
|
|
2153
|
+
base,
|
|
2154
|
+
milestoneId: mid,
|
|
2155
|
+
milestoneTitle: midTitle,
|
|
2156
|
+
extraContext: [inlinedContext],
|
|
2157
|
+
unitType: "plan-milestone",
|
|
2158
|
+
}),
|
|
2159
|
+
...buildSkillDiscoveryVars(),
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
export async function buildResearchSlicePrompt(
|
|
2164
|
+
mid: string, _midTitle: string, sid: string, sTitle: string, base: string,
|
|
2165
|
+
options?: { contextModeRenderMode?: ContextModeRenderMode },
|
|
2166
|
+
): Promise<string> {
|
|
2167
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
2168
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
2169
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
2170
|
+
const contextRel = relMilestoneFile(base, mid, "CONTEXT");
|
|
2171
|
+
const milestoneResearchPath = resolveMilestoneFile(base, mid, "RESEARCH");
|
|
2172
|
+
const milestoneResearchRel = relMilestoneFile(base, mid, "RESEARCH");
|
|
2173
|
+
|
|
2174
|
+
const sliceContextPath = resolveSliceFile(base, mid, sid, "CONTEXT");
|
|
2175
|
+
const sliceContextRel = relSliceFile(base, mid, sid, "CONTEXT");
|
|
2176
|
+
|
|
2177
|
+
const inlined: string[] = [];
|
|
2178
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
2179
|
+
|
|
2180
|
+
// Use roadmap excerpt instead of full roadmap for context reduction
|
|
2181
|
+
const roadmapExcerptRS = await inlineRoadmapExcerpt(base, mid, sid);
|
|
2182
|
+
if (roadmapExcerptRS) {
|
|
2183
|
+
inlined.push(roadmapExcerptRS);
|
|
2184
|
+
trackPromptContext(contextTelemetry, "roadmap", "excerpt", roadmapExcerptRS);
|
|
2185
|
+
} else {
|
|
2186
|
+
// Fall back to full roadmap if excerpt fails
|
|
2187
|
+
const roadmapInline = await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap");
|
|
2188
|
+
inlined.push(roadmapInline);
|
|
2189
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", roadmapInline, "excerpt unavailable");
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
const contextInline = await inlineFileOptional(contextPath, contextRel, "Milestone Context");
|
|
2193
|
+
if (contextInline) {
|
|
2194
|
+
inlined.push(contextInline);
|
|
2195
|
+
trackPromptContext(contextTelemetry, "milestone-context", "inline", contextInline);
|
|
2196
|
+
} else {
|
|
2197
|
+
trackPromptContext(contextTelemetry, "milestone-context", "skipped", null, "missing");
|
|
2198
|
+
}
|
|
2199
|
+
const sliceCtxInline = await inlineFileOptional(sliceContextPath, sliceContextRel, "Slice Context (from discussion)");
|
|
2200
|
+
if (sliceCtxInline) {
|
|
2201
|
+
inlined.push(sliceCtxInline);
|
|
2202
|
+
trackPromptContext(contextTelemetry, "slice-context", "inline", sliceCtxInline);
|
|
2203
|
+
} else {
|
|
2204
|
+
trackPromptContext(contextTelemetry, "slice-context", "skipped", null, "missing");
|
|
2205
|
+
}
|
|
2206
|
+
const researchInline = await inlineFileOptional(milestoneResearchPath, milestoneResearchRel, "Milestone Research");
|
|
2207
|
+
if (researchInline) {
|
|
2208
|
+
inlined.push(researchInline);
|
|
2209
|
+
trackPromptContext(contextTelemetry, "milestone-research", "inline", researchInline);
|
|
2210
|
+
} else {
|
|
2211
|
+
trackPromptContext(contextTelemetry, "milestone-research", "skipped", null, "missing");
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
// Derive scope from slice title for decision filtering (R005)
|
|
2215
|
+
const derivedScope = deriveSliceScope(sTitle);
|
|
2216
|
+
if (derivedScope) {
|
|
2217
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, derivedScope);
|
|
2218
|
+
if (decisionsInline) {
|
|
2219
|
+
inlined.push(decisionsInline);
|
|
2220
|
+
trackPromptContext(contextTelemetry, "decisions", "inline", decisionsInline, `scope:${derivedScope}`);
|
|
2221
|
+
} else {
|
|
2222
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, `no scoped decisions for ${derivedScope}`);
|
|
2223
|
+
}
|
|
2224
|
+
} else {
|
|
2225
|
+
const onDemandDecisions = [
|
|
2226
|
+
"### On-demand Decisions",
|
|
2227
|
+
"",
|
|
2228
|
+
`No specific decision scope was derived from "${sTitle}". Read \`${relGsdRootFile("DECISIONS")}\` only if research needs prior architecture/product decisions.`,
|
|
2229
|
+
].join("\n");
|
|
2230
|
+
inlined.push(onDemandDecisions);
|
|
2231
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", onDemandDecisions, "no derived scope");
|
|
2232
|
+
}
|
|
2233
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, sid);
|
|
2234
|
+
if (requirementsInline) {
|
|
2235
|
+
inlined.push(requirementsInline);
|
|
2236
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
2237
|
+
} else {
|
|
2238
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "missing");
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// Use scoped knowledge based on slice title keywords
|
|
2242
|
+
const keywords = extractKeywords(sTitle);
|
|
2243
|
+
const knowledgeInlineRS = await inlineKnowledgeScoped(base, keywords);
|
|
2244
|
+
if (knowledgeInlineRS) {
|
|
2245
|
+
inlined.push(knowledgeInlineRS);
|
|
2246
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInlineRS);
|
|
2247
|
+
} else {
|
|
2248
|
+
trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// Knowledge graph: subgraph for this slice (graceful — skipped if no graph.json)
|
|
2252
|
+
const graphBlockRS = await inlineGraphSubgraph(base, `${sid} ${sTitle}`, { budget: 3000 });
|
|
2253
|
+
if (graphBlockRS) {
|
|
2254
|
+
inlined.push(graphBlockRS);
|
|
2255
|
+
trackPromptContext(contextTelemetry, "graph-subgraph", "inline", graphBlockRS);
|
|
2256
|
+
} else {
|
|
2257
|
+
trackPromptContext(contextTelemetry, "graph-subgraph", "skipped", null, "missing");
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
const templateInline = inlineTemplate("research", "Research");
|
|
2261
|
+
inlined.push(templateInline);
|
|
2262
|
+
trackPromptContext(contextTelemetry, "templates", "inline", templateInline);
|
|
2263
|
+
|
|
2264
|
+
const depContent = await inlineDependencySummaries(mid, sid, base, resolveSummaryBudgetChars());
|
|
2265
|
+
trackPromptContext(contextTelemetry, "dependency-summaries", depContent.trim() ? "inline" : "skipped", depContent, depContent.trim() ? undefined : "none");
|
|
2266
|
+
const activeOverrides = await loadActiveOverrides(base);
|
|
2267
|
+
const overridesInline = formatOverridesSection(activeOverrides);
|
|
2268
|
+
if (overridesInline) {
|
|
2269
|
+
inlined.unshift(overridesInline);
|
|
2270
|
+
trackPromptContext(contextTelemetry, "overrides", "inline", overridesInline);
|
|
2271
|
+
} else {
|
|
2272
|
+
trackPromptContext(contextTelemetry, "overrides", "skipped", null, "none active");
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
2276
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
2277
|
+
trackPromptContext(
|
|
2278
|
+
contextTelemetry,
|
|
2279
|
+
"cap",
|
|
2280
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
2281
|
+
null,
|
|
2282
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
2283
|
+
);
|
|
2284
|
+
const inlinedContext = prependContextModeToBlock(
|
|
2285
|
+
"research-slice",
|
|
2286
|
+
base,
|
|
2287
|
+
cappedInlinedContext,
|
|
2288
|
+
options?.contextModeRenderMode,
|
|
2289
|
+
);
|
|
2290
|
+
emitPromptContextTelemetry("research-slice", contextTelemetry, inlinedContext);
|
|
2291
|
+
|
|
2292
|
+
const outputRelPath = relSliceFile(base, mid, sid, "RESEARCH");
|
|
2293
|
+
return loadPrompt("research-slice", {
|
|
2294
|
+
workingDirectory: base,
|
|
2295
|
+
milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
|
|
2296
|
+
slicePath: relSlicePath(base, mid, sid),
|
|
2297
|
+
roadmapPath: roadmapRel,
|
|
2298
|
+
contextPath: contextRel,
|
|
2299
|
+
milestoneResearchPath: milestoneResearchRel,
|
|
2300
|
+
outputPath: join(base, outputRelPath),
|
|
2301
|
+
inlinedContext,
|
|
2302
|
+
dependencySummaries: depContent,
|
|
2303
|
+
skillActivation: buildSkillActivationBlock({
|
|
2304
|
+
base,
|
|
2305
|
+
milestoneId: mid,
|
|
2306
|
+
sliceId: sid,
|
|
2307
|
+
sliceTitle: sTitle,
|
|
2308
|
+
extraContext: [inlinedContext, depContent],
|
|
2309
|
+
unitType: "research-slice",
|
|
2310
|
+
}),
|
|
2311
|
+
...buildSkillDiscoveryVars(),
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
/**
|
|
2316
|
+
* Shared assembly for plan-slice and refine-slice prompts. Both builders need
|
|
2317
|
+
* the same inlined context (roadmap excerpt, slice context, research, decisions,
|
|
2318
|
+
* requirements, knowledge, graph subgraph, templates, dependency summaries,
|
|
2319
|
+
* overrides). Extracted to prevent drift between the two sites.
|
|
2320
|
+
*
|
|
2321
|
+
* `prependBlocks` are pushed onto the start of the inlined array BEFORE any
|
|
2322
|
+
* shared content, so callers can add unit-specific headers (e.g., the refine
|
|
2323
|
+
* sketch-scope constraint).
|
|
2324
|
+
*/
|
|
2325
|
+
async function renderSlicePrompt(options: {
|
|
2326
|
+
mid: string;
|
|
2327
|
+
sid: string;
|
|
2328
|
+
sTitle: string;
|
|
2329
|
+
base: string;
|
|
2330
|
+
level: InlineLevel;
|
|
2331
|
+
promptTemplate: "plan-slice" | "refine-slice";
|
|
2332
|
+
prependBlocks?: string[];
|
|
2333
|
+
extraVars?: Record<string, string>;
|
|
2334
|
+
sessionContextWindow?: number;
|
|
2335
|
+
modelRegistry?: MinimalModelRegistry;
|
|
2336
|
+
sessionProvider?: string;
|
|
2337
|
+
contextModeRenderMode?: ContextModeRenderMode;
|
|
2338
|
+
}): Promise<string> {
|
|
2339
|
+
const {
|
|
2340
|
+
mid, sid, sTitle, base, level, promptTemplate, prependBlocks = [], extraVars = {},
|
|
2341
|
+
sessionContextWindow, modelRegistry, sessionProvider,
|
|
2342
|
+
} = options;
|
|
2343
|
+
|
|
2344
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
2345
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
2346
|
+
const researchPath = resolveSliceFile(base, mid, sid, "RESEARCH");
|
|
2347
|
+
const researchRel = relSliceFile(base, mid, sid, "RESEARCH");
|
|
2348
|
+
const sliceContextPath = resolveSliceFile(base, mid, sid, "CONTEXT");
|
|
2349
|
+
const sliceContextRel = relSliceFile(base, mid, sid, "CONTEXT");
|
|
2350
|
+
|
|
2351
|
+
const inlined: string[] = [...prependBlocks];
|
|
2352
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
2353
|
+
for (const block of prependBlocks) {
|
|
2354
|
+
trackPromptContext(contextTelemetry, "prepend", "inline", block);
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
// Phase handoff anchor from research phase (if available)
|
|
2358
|
+
const researchSliceAnchor = readPhaseAnchor(base, mid, "research-slice");
|
|
2359
|
+
if (researchSliceAnchor) {
|
|
2360
|
+
const body = formatAnchorForPrompt(researchSliceAnchor);
|
|
2361
|
+
inlined.push(body);
|
|
2362
|
+
trackPromptContext(contextTelemetry, "research-anchor", "inline", body);
|
|
2363
|
+
} else {
|
|
2364
|
+
trackPromptContext(contextTelemetry, "research-anchor", "skipped", null, "missing");
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// Roadmap excerpt with full-roadmap fallback
|
|
2368
|
+
const roadmapExcerpt = await inlineRoadmapExcerpt(base, mid, sid);
|
|
2369
|
+
if (roadmapExcerpt) {
|
|
2370
|
+
inlined.push(roadmapExcerpt);
|
|
2371
|
+
trackPromptContext(contextTelemetry, "roadmap", "excerpt", roadmapExcerpt);
|
|
2372
|
+
} else {
|
|
2373
|
+
const body = await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap");
|
|
2374
|
+
inlined.push(body);
|
|
2375
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", body, "excerpt unavailable");
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
const sliceCtxInline = await inlineFileOptional(sliceContextPath, sliceContextRel, "Slice Context (from discussion)");
|
|
2379
|
+
if (sliceCtxInline) {
|
|
2380
|
+
inlined.push(sliceCtxInline);
|
|
2381
|
+
trackPromptContext(contextTelemetry, "slice-context", "inline", sliceCtxInline);
|
|
2382
|
+
} else {
|
|
2383
|
+
trackPromptContext(contextTelemetry, "slice-context", "skipped", null, "missing");
|
|
2384
|
+
}
|
|
2385
|
+
const researchInline = await inlineFileOptional(researchPath, researchRel, "Slice Research");
|
|
2386
|
+
if (researchInline) {
|
|
2387
|
+
inlined.push(researchInline);
|
|
2388
|
+
trackPromptContext(contextTelemetry, "slice-research", "inline", researchInline);
|
|
2389
|
+
} else {
|
|
2390
|
+
trackPromptContext(contextTelemetry, "slice-research", "skipped", null, "missing");
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2393
|
+
if (level !== "minimal") {
|
|
2394
|
+
const derivedScope = deriveSliceScope(sTitle);
|
|
2395
|
+
if (derivedScope) {
|
|
2396
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, derivedScope, level);
|
|
2397
|
+
if (decisionsInline) {
|
|
2398
|
+
inlined.push(decisionsInline);
|
|
2399
|
+
trackPromptContext(contextTelemetry, "decisions", "inline", decisionsInline, `scope:${derivedScope}`);
|
|
2400
|
+
} else {
|
|
2401
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, `no scoped decisions for ${derivedScope}`);
|
|
2402
|
+
}
|
|
2403
|
+
} else {
|
|
2404
|
+
const onDemandDecisions = [
|
|
2405
|
+
"### On-demand Decisions",
|
|
2406
|
+
"",
|
|
2407
|
+
`No specific decision scope was derived from "${sTitle}". Read \`${relGsdRootFile("DECISIONS")}\` only if planning needs prior architecture/product decisions.`,
|
|
2408
|
+
].join("\n");
|
|
2409
|
+
inlined.push(onDemandDecisions);
|
|
2410
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", onDemandDecisions, "no derived scope");
|
|
2411
|
+
}
|
|
2412
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, sid, level);
|
|
2413
|
+
if (requirementsInline) {
|
|
2414
|
+
inlined.push(requirementsInline);
|
|
2415
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
2416
|
+
} else {
|
|
2417
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "missing");
|
|
2418
|
+
}
|
|
2419
|
+
} else {
|
|
2420
|
+
trackPromptContext(contextTelemetry, "decisions", "skipped", null, "minimal inline level");
|
|
2421
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "minimal inline level");
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
const knowledgeInline = await inlineKnowledgeScoped(base, extractKeywords(sTitle));
|
|
2425
|
+
if (knowledgeInline) {
|
|
2426
|
+
inlined.push(knowledgeInline);
|
|
2427
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInline);
|
|
2428
|
+
} else {
|
|
2429
|
+
trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
const graphBlock = await inlineGraphSubgraph(base, `${sid} ${sTitle}`, { budget: 3000 });
|
|
2433
|
+
if (graphBlock) {
|
|
2434
|
+
inlined.push(graphBlock);
|
|
2435
|
+
trackPromptContext(contextTelemetry, "graph-subgraph", "inline", graphBlock);
|
|
2436
|
+
} else {
|
|
2437
|
+
trackPromptContext(contextTelemetry, "graph-subgraph", "skipped", null, "missing");
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
const planTemplateInline = level === "minimal" ? inlineCompactTemplate("plan", "Slice Plan") : inlineTemplate("plan", "Slice Plan");
|
|
2441
|
+
inlined.push(planTemplateInline);
|
|
2442
|
+
trackPromptContext(contextTelemetry, "templates", "inline", planTemplateInline);
|
|
2443
|
+
if (level === "full") {
|
|
2444
|
+
const taskPlanTemplateInline = inlineTemplate("task-plan", "Task Plan");
|
|
2445
|
+
inlined.push(taskPlanTemplateInline);
|
|
2446
|
+
trackPromptContext(contextTelemetry, "templates", "inline", taskPlanTemplateInline);
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
const depContent = await inlineDependencySummaries(mid, sid, base, resolveSummaryBudgetChars());
|
|
2450
|
+
const overridesInline = formatOverridesSection(await loadActiveOverrides(base));
|
|
2451
|
+
if (overridesInline) {
|
|
2452
|
+
inlined.unshift(overridesInline);
|
|
2453
|
+
trackPromptContext(contextTelemetry, "overrides", "inline", overridesInline);
|
|
2454
|
+
} else {
|
|
2455
|
+
trackPromptContext(contextTelemetry, "overrides", "skipped", null, "none active");
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
2459
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
2460
|
+
trackPromptContext(
|
|
2461
|
+
contextTelemetry,
|
|
2462
|
+
"cap",
|
|
2463
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
2464
|
+
null,
|
|
2465
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
2466
|
+
);
|
|
2467
|
+
const inlinedContext = prependContextModeToBlock(
|
|
2468
|
+
promptTemplate,
|
|
2469
|
+
base,
|
|
2470
|
+
cappedInlinedContext,
|
|
2471
|
+
options.contextModeRenderMode,
|
|
2472
|
+
);
|
|
2473
|
+
emitPromptContextTelemetry(promptTemplate, contextTelemetry, inlinedContext);
|
|
2474
|
+
const executorContextConstraints = formatExecutorConstraints(sessionContextWindow, modelRegistry, sessionProvider);
|
|
2475
|
+
const outputRelPath = relSliceFile(base, mid, sid, "PLAN");
|
|
2476
|
+
const commitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
|
|
2477
|
+
|
|
2478
|
+
return loadPrompt(promptTemplate, {
|
|
2479
|
+
workingDirectory: base,
|
|
2480
|
+
milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
|
|
2481
|
+
slicePath: relSlicePath(base, mid, sid),
|
|
2482
|
+
roadmapPath: roadmapRel,
|
|
2483
|
+
researchPath: researchRel,
|
|
2484
|
+
outputPath: join(base, outputRelPath),
|
|
2485
|
+
inlinedContext,
|
|
2486
|
+
dependencySummaries: depContent,
|
|
2487
|
+
sourceFilePaths: buildSourceFilePaths(base, mid, sid),
|
|
2488
|
+
executorContextConstraints,
|
|
2489
|
+
commitInstruction,
|
|
2490
|
+
skillActivation: buildSkillActivationBlock({
|
|
2491
|
+
base,
|
|
2492
|
+
milestoneId: mid,
|
|
2493
|
+
sliceId: sid,
|
|
2494
|
+
sliceTitle: sTitle,
|
|
2495
|
+
extraContext: [inlinedContext, depContent],
|
|
2496
|
+
unitType: promptTemplate,
|
|
2497
|
+
}),
|
|
2498
|
+
...extraVars,
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
export async function buildPlanSlicePrompt(
|
|
2503
|
+
mid: string, _midTitle: string, sid: string, sTitle: string, base: string, level?: InlineLevel,
|
|
2504
|
+
options?: {
|
|
2505
|
+
softScopeHint?: string;
|
|
2506
|
+
sessionContextWindow?: number;
|
|
2507
|
+
modelRegistry?: MinimalModelRegistry;
|
|
2508
|
+
sessionProvider?: string;
|
|
2509
|
+
/** Failure context from a prior pre-exec gate run (#4551). When present, a
|
|
2510
|
+
* "Fix these specific issues" section is appended so the LLM addresses the
|
|
2511
|
+
* exact problems instead of producing an identical plan that fails again. */
|
|
2512
|
+
priorPreExecFailure?: {
|
|
2513
|
+
blockingFindings: string[];
|
|
2514
|
+
verdictExcerpt: string;
|
|
2515
|
+
};
|
|
2516
|
+
},
|
|
2517
|
+
): Promise<string> {
|
|
2518
|
+
const prependBlocks: string[] = [];
|
|
2519
|
+
// ADR-011: when the refining-phase dispatch rule gracefully downgrades to
|
|
2520
|
+
// plan-slice (progressive_planning was toggled off mid-milestone), it
|
|
2521
|
+
// forwards the stored sketch_scope as a SOFT hint — context, not a hard
|
|
2522
|
+
// constraint. The planner is free to expand beyond it.
|
|
2523
|
+
if (options?.softScopeHint && options.softScopeHint.trim().length > 0) {
|
|
2524
|
+
prependBlocks.push(
|
|
2525
|
+
`## Prior Sketch Scope (soft hint — non-binding)\n\n${options.softScopeHint.trim()}\n\n` +
|
|
2526
|
+
`This scope was captured during an earlier progressive-planning pass that was later disabled. Treat it as context only — you may plan beyond it if the work genuinely requires more scope. Do NOT treat this as a hard boundary.`,
|
|
2527
|
+
);
|
|
2528
|
+
}
|
|
2529
|
+
// #4551: inject pre-exec failure context so the re-dispatched plan-slice
|
|
2530
|
+
// addresses the exact blocked references rather than reproducing the same plan.
|
|
2531
|
+
if (options?.priorPreExecFailure) {
|
|
2532
|
+
const { blockingFindings, verdictExcerpt } = options.priorPreExecFailure;
|
|
2533
|
+
const findingsList = blockingFindings.length > 0
|
|
2534
|
+
? blockingFindings.map(f => `- ${f}`).join("\n")
|
|
2535
|
+
: "- (no specific findings recorded)";
|
|
2536
|
+
prependBlocks.push(
|
|
2537
|
+
`## Fix these specific issues from the prior pre-exec check\n\n` +
|
|
2538
|
+
`The previous plan-slice attempt was blocked by pre-execution validation.\n` +
|
|
2539
|
+
`Gate verdict: ${verdictExcerpt}\n\n` +
|
|
2540
|
+
`Blocked references that must be resolved in this plan:\n${findingsList}\n\n` +
|
|
2541
|
+
`**How to fix each type of issue:**\n` +
|
|
2542
|
+
`- **"[file] X doesn't exist and isn't created by prior or same-task outputs"**: ` +
|
|
2543
|
+
`Either (a) add an earlier task that creates X on disk before the task that needs it, ` +
|
|
2544
|
+
`or (b) if this task IS the one that creates X, move X from inputs to expected_output. ` +
|
|
2545
|
+
`Do NOT put X in a task's expected_output if that task only reads or verifies X — only tasks that actually write X to disk should list it in expected_output.\n` +
|
|
2546
|
+
`- **"[file] X: Task T_early reads X but it's created by task T_late (sequence violation)"**: ` +
|
|
2547
|
+
`Either (a) reorder tasks so T_late (the creator) runs before T_early (the reader), ` +
|
|
2548
|
+
`or (b) if T_late doesn't actually create X (it only reads/tests it), remove X from T_late's expected_output entirely.\n` +
|
|
2549
|
+
`- **"[package] P not found on npm"**: Either remove the npm install for P, or use the correct package name.\n\n` +
|
|
2550
|
+
`Every file listed in a task's inputs must either exist on disk already or appear in an earlier task's expected_output. ` +
|
|
2551
|
+
`A task's expected_output must only list files it actually writes to disk.`,
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
return renderSlicePrompt({
|
|
2555
|
+
mid, sid, sTitle, base,
|
|
2556
|
+
level: level ?? resolveInlineLevel(),
|
|
2557
|
+
promptTemplate: "plan-slice",
|
|
2558
|
+
prependBlocks,
|
|
2559
|
+
sessionContextWindow: options?.sessionContextWindow,
|
|
2560
|
+
modelRegistry: options?.modelRegistry,
|
|
2561
|
+
sessionProvider: options?.sessionProvider,
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
/**
|
|
2566
|
+
* ADR-011 refine-slice: expand a sketch into a full plan using the current
|
|
2567
|
+
* codebase state and prior slice summary. Mechanically similar to plan-slice
|
|
2568
|
+
* but framed as a *transformation* (sketch → full plan) rather than a
|
|
2569
|
+
* blank-sheet planning pass. Reuses inlineDependencySummaries for prior
|
|
2570
|
+
* slice SUMMARY and inlines the stored sketch_scope as a hard constraint.
|
|
2571
|
+
*/
|
|
2572
|
+
export async function buildRefineSlicePrompt(
|
|
2573
|
+
mid: string, _midTitle: string, sid: string, sTitle: string, base: string, level?: InlineLevel,
|
|
2574
|
+
options?: { sessionContextWindow?: number; modelRegistry?: MinimalModelRegistry; sessionProvider?: string },
|
|
2575
|
+
): Promise<string> {
|
|
2576
|
+
// Pull the stored sketch scope from the DB — the hard constraint we plan within.
|
|
2577
|
+
let sketchScope = "";
|
|
2578
|
+
try {
|
|
2579
|
+
const { isDbAvailable, getSlice } = await import("./gsd-db.js");
|
|
2580
|
+
if (isDbAvailable()) {
|
|
2581
|
+
sketchScope = getSlice(mid, sid)?.sketch_scope ?? "";
|
|
2582
|
+
}
|
|
2583
|
+
} catch {
|
|
2584
|
+
sketchScope = "";
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
const prependBlocks: string[] = [];
|
|
2588
|
+
if (sketchScope.trim().length > 0) {
|
|
2589
|
+
prependBlocks.push(
|
|
2590
|
+
`## Sketch Scope (hard constraint)\n\n${sketchScope.trim()}\n\n` +
|
|
2591
|
+
`Treat this as the authoritative boundary for the slice. Do not plan work outside this scope; if the scope is too narrow, surface it as a deviation rather than expanding silently.`,
|
|
2592
|
+
);
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
return renderSlicePrompt({
|
|
2596
|
+
mid, sid, sTitle, base,
|
|
2597
|
+
level: level ?? resolveInlineLevel(),
|
|
2598
|
+
promptTemplate: "refine-slice",
|
|
2599
|
+
prependBlocks,
|
|
2600
|
+
extraVars: { sketchScope },
|
|
2601
|
+
sessionContextWindow: options?.sessionContextWindow,
|
|
2602
|
+
modelRegistry: options?.modelRegistry,
|
|
2603
|
+
sessionProvider: options?.sessionProvider,
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
/** Options for customizing execute-task prompt construction. */
|
|
2608
|
+
export interface ExecuteTaskPromptOptions {
|
|
2609
|
+
level?: InlineLevel;
|
|
2610
|
+
/** Override carry-forward paths (dependency-based instead of order-based). */
|
|
2611
|
+
carryForwardPaths?: string[];
|
|
2612
|
+
/** Session model context window in tokens, forwarded to the budget engine. */
|
|
2613
|
+
sessionContextWindow?: number;
|
|
2614
|
+
/** Model registry forwarded to the budget engine for executor-model lookup. */
|
|
2615
|
+
modelRegistry?: MinimalModelRegistry;
|
|
2616
|
+
/** Session model provider, used for provider-specific effective context windows. */
|
|
2617
|
+
sessionProvider?: string;
|
|
2618
|
+
/** Render compact Context Mode guidance when embedded inside another prompt. */
|
|
2619
|
+
contextModeRenderMode?: ContextModeRenderMode;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
export async function buildExecuteTaskPrompt(
|
|
2623
|
+
mid: string, sid: string, sTitle: string,
|
|
2624
|
+
tid: string, tTitle: string, base: string,
|
|
2625
|
+
level?: InlineLevel | ExecuteTaskPromptOptions,
|
|
2626
|
+
): Promise<string> {
|
|
2627
|
+
const opts: ExecuteTaskPromptOptions = typeof level === "object" && level !== null && !Array.isArray(level)
|
|
2628
|
+
? level
|
|
2629
|
+
: { level: level as InlineLevel | undefined };
|
|
2630
|
+
const inlineLevel = opts.level ?? resolveInlineLevel();
|
|
2631
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
2632
|
+
|
|
2633
|
+
// Inject phase handoff anchor from planning phase (if available)
|
|
2634
|
+
const planAnchor = readPhaseAnchor(base, mid, "plan-slice");
|
|
2635
|
+
|
|
2636
|
+
const priorSummaries = opts.carryForwardPaths ?? await getPriorTaskSummaryPaths(mid, sid, tid, base);
|
|
2637
|
+
const priorLines = priorSummaries.length > 0
|
|
2638
|
+
? priorSummaries.map(p => `- \`${p}\``).join("\n")
|
|
2639
|
+
: "- (no prior tasks)";
|
|
2640
|
+
|
|
2641
|
+
const taskPlanPath = resolveTaskFile(base, mid, sid, tid, "PLAN");
|
|
2642
|
+
const taskPlanContent = taskPlanPath ? await loadFile(taskPlanPath) : null;
|
|
2643
|
+
const taskPlanRelPath = relSlicePath(base, mid, sid) + `/tasks/${tid}-PLAN.md`;
|
|
2644
|
+
const taskPlanInline = taskPlanContent
|
|
2645
|
+
? [
|
|
2646
|
+
"## Inlined Task Plan (authoritative local execution contract)",
|
|
2647
|
+
`Source: \`${taskPlanRelPath}\``,
|
|
2648
|
+
"",
|
|
2649
|
+
taskPlanContent.trim(),
|
|
2650
|
+
].join("\n")
|
|
2651
|
+
: [
|
|
2652
|
+
"## Inlined Task Plan (authoritative local execution contract)",
|
|
2653
|
+
`Task plan not found at dispatch time. Read \`${taskPlanRelPath}\` before executing.`,
|
|
2654
|
+
].join("\n");
|
|
2655
|
+
trackPromptContext(contextTelemetry, "task-plan", taskPlanContent ? "inline" : "on-demand", taskPlanInline, taskPlanContent ? undefined : "missing at dispatch");
|
|
2656
|
+
|
|
2657
|
+
const slicePlanPath = resolveSliceFile(base, mid, sid, "PLAN");
|
|
2658
|
+
const slicePlanContent = slicePlanPath ? await loadFile(slicePlanPath) : null;
|
|
2659
|
+
const slicePlanExcerpt = extractSliceExecutionExcerpt(slicePlanContent, relSliceFile(base, mid, sid, "PLAN"));
|
|
2660
|
+
trackPromptContext(contextTelemetry, "slice-plan", slicePlanExcerpt ? "excerpt" : "skipped", slicePlanExcerpt, slicePlanExcerpt ? undefined : "missing");
|
|
2661
|
+
|
|
2662
|
+
// Check for continue file (new naming or legacy)
|
|
2663
|
+
const continueFile = resolveSliceFile(base, mid, sid, "CONTINUE");
|
|
2664
|
+
const legacyContinueDir = resolveSlicePath(base, mid, sid);
|
|
2665
|
+
const legacyContinuePath = legacyContinueDir ? join(legacyContinueDir, "continue.md") : null;
|
|
2666
|
+
const continueContent = continueFile ? await loadFile(continueFile) : null;
|
|
2667
|
+
const legacyContinueContent = !continueContent && legacyContinuePath ? await loadFile(legacyContinuePath) : null;
|
|
2668
|
+
const continueRelPath = relSliceFile(base, mid, sid, "CONTINUE");
|
|
2669
|
+
const resumeSection = buildResumeSection(
|
|
2670
|
+
continueContent,
|
|
2671
|
+
legacyContinueContent,
|
|
2672
|
+
continueRelPath,
|
|
2673
|
+
legacyContinuePath ? `${relSlicePath(base, mid, sid)}/continue.md` : null,
|
|
2674
|
+
);
|
|
2675
|
+
trackPromptContext(contextTelemetry, "resume-section", resumeSection.trim() ? "inline" : "skipped", resumeSection, resumeSection.trim() ? undefined : "missing");
|
|
2676
|
+
|
|
2677
|
+
// For minimal inline level, only carry forward the most recent prior summary
|
|
2678
|
+
const effectivePriorSummaries = inlineLevel === "minimal" && priorSummaries.length > 1
|
|
2679
|
+
? priorSummaries.slice(-1)
|
|
2680
|
+
: priorSummaries;
|
|
2681
|
+
const carryForwardSection = await buildCarryForwardSection(effectivePriorSummaries, base);
|
|
2682
|
+
|
|
2683
|
+
// Inline project knowledge if available (smart-chunked for relevance)
|
|
2684
|
+
const knowledgeAbsPath = resolveGsdRootFile(base, "KNOWLEDGE");
|
|
2685
|
+
const knowledgeInlineET = existsSync(knowledgeAbsPath)
|
|
2686
|
+
? await inlineFileSmart(
|
|
2687
|
+
knowledgeAbsPath,
|
|
2688
|
+
relGsdRootFile("KNOWLEDGE"),
|
|
2689
|
+
"Project Knowledge",
|
|
2690
|
+
`${tTitle} ${sTitle}`, // use task + slice title as relevance query
|
|
2691
|
+
)
|
|
2692
|
+
: null;
|
|
2693
|
+
// Only include if it has content (not a "not found" result)
|
|
2694
|
+
const knowledgeContent = knowledgeInlineET && !knowledgeInlineET.includes("not found") ? knowledgeInlineET : null;
|
|
2695
|
+
|
|
2696
|
+
// Knowledge graph: tight subgraph for this task (graceful — skipped if no graph.json)
|
|
2697
|
+
const graphBlockET = await inlineGraphSubgraph(base, `${tid} ${tTitle}`, { budget: 2000 });
|
|
2698
|
+
const decisionsOnDemandET = [
|
|
2699
|
+
"### On-demand Decisions Template",
|
|
2700
|
+
"",
|
|
2701
|
+
"If this task records a durable architecture or product decision, read `templates/decisions.md` before calling `capture_thought` or `gsd_decision_save`.",
|
|
2702
|
+
].join("\n");
|
|
2703
|
+
|
|
2704
|
+
const inlinedTemplates = inlineLevel === "minimal"
|
|
2705
|
+
? inlineCompactTemplate("task-summary", "Task Summary")
|
|
2706
|
+
: [
|
|
2707
|
+
inlineTemplate("task-summary", "Task Summary"),
|
|
2708
|
+
decisionsOnDemandET,
|
|
2709
|
+
...(knowledgeContent ? [knowledgeContent] : []),
|
|
2710
|
+
...(graphBlockET ? [graphBlockET] : []),
|
|
2711
|
+
].join("\n\n---\n\n");
|
|
2712
|
+
|
|
2713
|
+
const taskSummaryPath = join(base, `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md`);
|
|
2714
|
+
|
|
2715
|
+
const activeOverrides = await loadActiveOverrides(base);
|
|
2716
|
+
const overridesSection = formatOverridesSection(activeOverrides);
|
|
2717
|
+
|
|
2718
|
+
// Compute verification budget for the executor's context window (issue #707)
|
|
2719
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
2720
|
+
const contextWindow = resolveExecutorContextWindow(opts.modelRegistry, prefs?.preferences, opts.sessionContextWindow, opts.sessionProvider);
|
|
2721
|
+
const budgets = computeBudgets(contextWindow);
|
|
2722
|
+
const verificationBudget = `~${Math.round(budgets.verificationBudgetChars / 1000)}K chars`;
|
|
2723
|
+
|
|
2724
|
+
// Truncate carry-forward section when it exceeds 40% of inline context budget.
|
|
2725
|
+
const carryForwardBudget = Math.floor(budgets.inlineContextBudgetChars * 0.4);
|
|
2726
|
+
let finalCarryForward = carryForwardSection;
|
|
2727
|
+
if (carryForwardSection.length > carryForwardBudget) {
|
|
2728
|
+
finalCarryForward = truncateAtSectionBoundary(carryForwardSection, carryForwardBudget).content;
|
|
2729
|
+
}
|
|
2730
|
+
trackPromptContext(
|
|
2731
|
+
contextTelemetry,
|
|
2732
|
+
"prior-task-summaries",
|
|
2733
|
+
finalCarryForward.trim() ? "excerpt" : "skipped",
|
|
2734
|
+
finalCarryForward,
|
|
2735
|
+
finalCarryForward.length < carryForwardSection.length ? `truncated from ${carryForwardSection.length} chars` : undefined,
|
|
2736
|
+
);
|
|
2737
|
+
|
|
2738
|
+
// Inline RUNTIME.md if present
|
|
2739
|
+
const runtimePath = resolveRuntimeFile(base);
|
|
2740
|
+
const runtimeContent = existsSync(runtimePath) ? await loadFile(runtimePath) : null;
|
|
2741
|
+
const runtimeContext = runtimeContent
|
|
2742
|
+
? `### Runtime Context\nSource: \`.gsd/RUNTIME.md\`\n\n${runtimeContent.trim()}`
|
|
2743
|
+
: "";
|
|
2744
|
+
trackPromptContext(contextTelemetry, "runtime", runtimeContext ? "inline" : "skipped", runtimeContext, runtimeContext ? undefined : "missing");
|
|
2745
|
+
|
|
2746
|
+
let phaseAnchorSection = planAnchor ? formatAnchorForPrompt(planAnchor) : "";
|
|
2747
|
+
trackPromptContext(contextTelemetry, "plan-anchor", phaseAnchorSection ? "inline" : "skipped", phaseAnchorSection, phaseAnchorSection ? undefined : "missing");
|
|
2748
|
+
|
|
2749
|
+
// ADR-011 Phase 2: inject any resolved-but-unapplied escalation override
|
|
2750
|
+
// into this task's prompt. Claim is atomic via DB UPDATE WHERE IS NULL, so
|
|
2751
|
+
// if a parallel build already injected it, we skip. Feature-gated by
|
|
2752
|
+
// phases.mid_execution_escalation. Prepended to phaseAnchorSection so it
|
|
2753
|
+
// appears near the top of the prompt above planning anchors.
|
|
2754
|
+
if (prefs?.preferences?.phases?.mid_execution_escalation === true) {
|
|
2755
|
+
try {
|
|
2756
|
+
const { claimOverrideForInjection } = await import("./escalation.js");
|
|
2757
|
+
const claimed = claimOverrideForInjection(base, mid, sid);
|
|
2758
|
+
if (claimed) {
|
|
2759
|
+
const block = claimed.injectionBlock + "\n\n---\n\n";
|
|
2760
|
+
phaseAnchorSection = phaseAnchorSection
|
|
2761
|
+
? `${block}${phaseAnchorSection}`
|
|
2762
|
+
: block;
|
|
2763
|
+
}
|
|
2764
|
+
} catch (escalationErr) {
|
|
2765
|
+
// Escalation module unavailable or threw — log and proceed.
|
|
2766
|
+
logWarning("prompt", `escalation override injection failed: ${(escalationErr as Error).message}`);
|
|
2767
|
+
}
|
|
2768
|
+
}
|
|
2769
|
+
|
|
2770
|
+
// Task-scoped gates owned by execute-task (Q5/Q6/Q7). Pull only the
|
|
2771
|
+
// gates that plan-slice actually seeded for this task — tasks with no
|
|
2772
|
+
// external dependencies legitimately skip Q5, tasks with no runtime
|
|
2773
|
+
// load dimension skip Q6, etc.
|
|
2774
|
+
const etPending = getPendingGatesForTurn(mid, sid, "execute-task", tid);
|
|
2775
|
+
assertGateCoverage(etPending, "execute-task", { requireAll: false });
|
|
2776
|
+
const gatesToClose = renderGatesToCloseBlock(
|
|
2777
|
+
getGatesForTurn("execute-task"),
|
|
2778
|
+
{ pending: new Set(etPending.map((g) => g.gate_id)), allowOmit: true },
|
|
2779
|
+
);
|
|
2780
|
+
phaseAnchorSection = prependContextModeToBlock("execute-task", base, phaseAnchorSection, opts.contextModeRenderMode);
|
|
2781
|
+
trackPromptContext(contextTelemetry, "context-mode", phaseAnchorSection ? "inline" : "skipped", phaseAnchorSection, phaseAnchorSection ? undefined : "disabled or empty");
|
|
2782
|
+
trackPromptContext(contextTelemetry, "overrides", overridesSection ? "inline" : "skipped", overridesSection, overridesSection ? undefined : "none active");
|
|
2783
|
+
trackPromptContext(contextTelemetry, "gates", gatesToClose ? "inline" : "skipped", gatesToClose, gatesToClose ? undefined : "none pending");
|
|
2784
|
+
trackPromptContext(contextTelemetry, "knowledge", knowledgeContent ? "inline" : "skipped", knowledgeContent, knowledgeContent ? undefined : "missing");
|
|
2785
|
+
trackPromptContext(contextTelemetry, "graph-subgraph", graphBlockET ? "inline" : "skipped", graphBlockET, graphBlockET ? undefined : "missing");
|
|
2786
|
+
if (inlineLevel !== "minimal") {
|
|
2787
|
+
trackPromptContext(contextTelemetry, "decisions-template", "on-demand", decisionsOnDemandET);
|
|
2788
|
+
}
|
|
2789
|
+
trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates, inlineLevel);
|
|
2790
|
+
|
|
2791
|
+
const prompt = loadPrompt("execute-task", {
|
|
2792
|
+
overridesSection,
|
|
2793
|
+
runtimeContext,
|
|
2794
|
+
phaseAnchorSection,
|
|
2795
|
+
workingDirectory: base,
|
|
2796
|
+
milestoneId: mid, sliceId: sid, sliceTitle: sTitle, taskId: tid, taskTitle: tTitle,
|
|
2797
|
+
planPath: join(base, relSliceFile(base, mid, sid, "PLAN")),
|
|
2798
|
+
slicePath: relSlicePath(base, mid, sid),
|
|
2799
|
+
taskPlanPath: taskPlanRelPath,
|
|
2800
|
+
taskPlanInline,
|
|
2801
|
+
slicePlanExcerpt,
|
|
2802
|
+
carryForwardSection: finalCarryForward,
|
|
2803
|
+
resumeSection,
|
|
2804
|
+
priorTaskLines: priorLines,
|
|
2805
|
+
taskSummaryPath,
|
|
2806
|
+
inlinedTemplates,
|
|
2807
|
+
verificationBudget,
|
|
2808
|
+
gatesToClose,
|
|
2809
|
+
skillActivation: buildSkillActivationBlock({
|
|
2810
|
+
base,
|
|
2811
|
+
milestoneId: mid,
|
|
2812
|
+
sliceId: sid,
|
|
2813
|
+
sliceTitle: sTitle,
|
|
2814
|
+
taskId: tid,
|
|
2815
|
+
taskTitle: tTitle,
|
|
2816
|
+
taskPlanContent,
|
|
2817
|
+
extraContext: [taskPlanInline, slicePlanExcerpt, finalCarryForward, resumeSection],
|
|
2818
|
+
unitType: "execute-task",
|
|
2819
|
+
}),
|
|
2820
|
+
});
|
|
2821
|
+
emitPromptContextTelemetry("execute-task", contextTelemetry, prompt);
|
|
2822
|
+
return prompt;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
export async function buildCompleteSlicePrompt(
|
|
2826
|
+
mid: string, midTitle: string, sid: string, sTitle: string, base: string, level?: InlineLevel,
|
|
2827
|
+
): Promise<string> {
|
|
2828
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
2829
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
2830
|
+
|
|
2831
|
+
// #4782 phase 3: complete-slice migrated through composer. Manifest
|
|
2832
|
+
// declares [roadmap, slice-context, slice-plan, requirements,
|
|
2833
|
+
// prior-task-summaries, templates]. Overrides prepend and knowledge
|
|
2834
|
+
// splice stay imperative — they need the composer v2 contract
|
|
2835
|
+
// (computed + prepend blocks; see RFC #4924).
|
|
2836
|
+
const resolveArtifact: ArtifactResolver = async (key) => {
|
|
2837
|
+
switch (key) {
|
|
2838
|
+
case "roadmap": {
|
|
2839
|
+
const p = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
2840
|
+
const r = relMilestoneFile(base, mid, "ROADMAP");
|
|
2841
|
+
const body = await inlineFile(p, r, "Milestone Roadmap");
|
|
2842
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", body);
|
|
2843
|
+
return body;
|
|
2844
|
+
}
|
|
2845
|
+
case "slice-context": {
|
|
2846
|
+
const p = resolveSliceFile(base, mid, sid, "CONTEXT");
|
|
2847
|
+
const r = relSliceFile(base, mid, sid, "CONTEXT");
|
|
2848
|
+
const body = await inlineFileOptional(p, r, "Slice Context (from discussion)");
|
|
2849
|
+
trackPromptContext(contextTelemetry, "slice-context", body ? "inline" : "skipped", body, body ? undefined : "missing");
|
|
2850
|
+
return body;
|
|
2851
|
+
}
|
|
2852
|
+
case "slice-plan": {
|
|
2853
|
+
const p = resolveSliceFile(base, mid, sid, "PLAN");
|
|
2854
|
+
const r = relSliceFile(base, mid, sid, "PLAN");
|
|
2855
|
+
const body = await inlineFile(p, r, "Slice Plan");
|
|
2856
|
+
trackPromptContext(contextTelemetry, "slice-plan", "inline", body);
|
|
2857
|
+
return body;
|
|
2858
|
+
}
|
|
2859
|
+
case "requirements":
|
|
2860
|
+
if (inlineLevel === "minimal") {
|
|
2861
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "minimal inline level");
|
|
2862
|
+
return null;
|
|
2863
|
+
}
|
|
2864
|
+
{
|
|
2865
|
+
const body = await inlineRequirementsFromDb(base, mid, sid, inlineLevel);
|
|
2866
|
+
trackPromptContext(contextTelemetry, "requirements", body ? "inline" : "skipped", body, body ? undefined : "missing");
|
|
2867
|
+
return body;
|
|
2868
|
+
}
|
|
2869
|
+
case "prior-task-summaries": {
|
|
2870
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
2871
|
+
if (!tDir) {
|
|
2872
|
+
trackPromptContext(contextTelemetry, "prior-task-summaries", "skipped", null, "missing tasks dir");
|
|
2873
|
+
return null;
|
|
2874
|
+
}
|
|
2875
|
+
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY").sort();
|
|
2876
|
+
const sRel = relSlicePath(base, mid, sid);
|
|
2877
|
+
const blocks: string[] = [];
|
|
2878
|
+
for (const file of summaryFiles) {
|
|
2879
|
+
const absPath = join(tDir, file);
|
|
2880
|
+
const relPath = `${sRel}/tasks/${file}`;
|
|
2881
|
+
const taskId = file.replace(/-SUMMARY\.md$/i, "");
|
|
2882
|
+
blocks.push(await buildTaskSummaryExcerpt(absPath, relPath, taskId));
|
|
2883
|
+
}
|
|
2884
|
+
const body = blocks.length > 0 ? blocks.join("\n\n---\n\n") : null;
|
|
2885
|
+
trackPromptContext(contextTelemetry, "prior-task-summaries", body ? "excerpt" : "skipped", body, body ? undefined : "missing");
|
|
2886
|
+
return body;
|
|
2887
|
+
}
|
|
2888
|
+
case "templates": {
|
|
2889
|
+
const parts = [inlineLevel === "minimal"
|
|
2890
|
+
? inlineCompactTemplate("slice-summary", "Slice Summary")
|
|
2891
|
+
: inlineTemplate("slice-summary", "Slice Summary")];
|
|
2892
|
+
if (inlineLevel !== "minimal") {
|
|
2893
|
+
parts.push(inlineTemplate("uat", "UAT"));
|
|
2894
|
+
}
|
|
2895
|
+
const body = parts.join("\n\n---\n\n");
|
|
2896
|
+
trackPromptContext(contextTelemetry, "templates", "inline", body);
|
|
2897
|
+
return body;
|
|
2898
|
+
}
|
|
2899
|
+
default:
|
|
2900
|
+
return null;
|
|
2901
|
+
}
|
|
2902
|
+
};
|
|
2903
|
+
|
|
2904
|
+
const composed = await composeInlinedContext("complete-slice", resolveArtifact);
|
|
2905
|
+
|
|
2906
|
+
// Knowledge splices in between requirements and prior-task-summaries
|
|
2907
|
+
// so overall order matches pre-migration: roadmap → slice-context →
|
|
2908
|
+
// slice-plan → requirements → KNOWLEDGE → task summaries → templates.
|
|
2909
|
+
const knowledgeInlineCS = await inlineKnowledgeBudgeted(
|
|
2910
|
+
base,
|
|
2911
|
+
[...extractKeywords(midTitle), ...extractKeywords(sTitle)],
|
|
2912
|
+
);
|
|
2913
|
+
if (knowledgeInlineCS) {
|
|
2914
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInlineCS);
|
|
2915
|
+
} else {
|
|
2916
|
+
trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
|
|
2917
|
+
}
|
|
2918
|
+
|
|
2919
|
+
let body = composed;
|
|
2920
|
+
if (knowledgeInlineCS && body) {
|
|
2921
|
+
// Splice knowledge right before the first "### Task Summary:" block
|
|
2922
|
+
// to preserve pre-migration ordering. If no task summaries exist,
|
|
2923
|
+
// splice before the templates block (which inlineTemplate emits as
|
|
2924
|
+
// "### Output Template: Slice Summary").
|
|
2925
|
+
const taskIdx = body.indexOf("### Task Summary:");
|
|
2926
|
+
const templatesIdx = body.lastIndexOf("### Output Template: Slice Summary");
|
|
2927
|
+
const spliceIdx = taskIdx > -1 ? taskIdx : templatesIdx;
|
|
2928
|
+
if (spliceIdx > 0) {
|
|
2929
|
+
const before = body.slice(0, spliceIdx).replace(/\n\n---\n\n$/, "");
|
|
2930
|
+
const after = body.slice(spliceIdx);
|
|
2931
|
+
body = [before, knowledgeInlineCS, after].join("\n\n---\n\n");
|
|
2932
|
+
} else {
|
|
2933
|
+
body = `${body}\n\n---\n\n${knowledgeInlineCS}`;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
// Overrides section prepends to the top of the inlined context —
|
|
2938
|
+
// standard pattern for slice-level builders (until composer v2 lands
|
|
2939
|
+
// the prepend contract).
|
|
2940
|
+
const completeActiveOverrides = await loadActiveOverrides(base);
|
|
2941
|
+
const completeOverridesInline = formatOverridesSection(completeActiveOverrides);
|
|
2942
|
+
if (completeOverridesInline) {
|
|
2943
|
+
trackPromptContext(contextTelemetry, "overrides", "inline", completeOverridesInline);
|
|
2944
|
+
} else {
|
|
2945
|
+
trackPromptContext(contextTelemetry, "overrides", "skipped", null, "none active");
|
|
2946
|
+
}
|
|
2947
|
+
const finalBody = completeOverridesInline
|
|
2948
|
+
? `${completeOverridesInline}\n\n---\n\n${body}`
|
|
2949
|
+
: body;
|
|
2950
|
+
|
|
2951
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${finalBody}`;
|
|
2952
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
2953
|
+
trackPromptContext(
|
|
2954
|
+
contextTelemetry,
|
|
2955
|
+
"cap",
|
|
2956
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
2957
|
+
null,
|
|
2958
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
2959
|
+
);
|
|
2960
|
+
const inlinedContext = prependContextModeToBlock(
|
|
2961
|
+
"complete-slice",
|
|
2962
|
+
base,
|
|
2963
|
+
cappedInlinedContext,
|
|
2964
|
+
);
|
|
2965
|
+
emitPromptContextTelemetry("complete-slice", contextTelemetry, inlinedContext);
|
|
2966
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
2967
|
+
|
|
2968
|
+
const sliceRel = relSlicePath(base, mid, sid);
|
|
2969
|
+
const sliceSummaryPath = join(base, `${sliceRel}/${sid}-SUMMARY.md`);
|
|
2970
|
+
const sliceUatPath = join(base, `${sliceRel}/${sid}-UAT.md`);
|
|
2971
|
+
|
|
2972
|
+
// Gates owned by complete-slice (e.g. Q8). Pull from the DB so the
|
|
2973
|
+
// prompt only prompts for gates the plan actually seeded. The tool
|
|
2974
|
+
// handler closes each gate based on the SUMMARY.md section content
|
|
2975
|
+
// after the assistant calls gsd_complete_slice.
|
|
2976
|
+
const csPending = getPendingGatesForTurn(mid, sid, "complete-slice");
|
|
2977
|
+
// coverage check: every pending row must be owned by complete-slice.
|
|
2978
|
+
// requireAll:false because a slice may have already closed some gates.
|
|
2979
|
+
assertGateCoverage(csPending, "complete-slice", { requireAll: false });
|
|
2980
|
+
const gatesToClose = renderGatesToCloseBlock(
|
|
2981
|
+
getGatesForTurn("complete-slice"),
|
|
2982
|
+
{ pending: new Set(csPending.map((g) => g.gate_id)), allowOmit: true },
|
|
2983
|
+
);
|
|
2984
|
+
|
|
2985
|
+
return loadPrompt("complete-slice", {
|
|
2986
|
+
workingDirectory: base,
|
|
2987
|
+
milestoneId: mid, sliceId: sid, sliceTitle: sTitle,
|
|
2988
|
+
slicePath: sliceRel,
|
|
2989
|
+
roadmapPath: join(base, roadmapRel),
|
|
2990
|
+
inlinedContext,
|
|
2991
|
+
sliceSummaryPath,
|
|
2992
|
+
sliceUatPath,
|
|
2993
|
+
gatesToClose,
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
|
|
2997
|
+
export async function buildCompleteMilestonePrompt(
|
|
2998
|
+
mid: string, midTitle: string, base: string, level?: InlineLevel,
|
|
2999
|
+
): Promise<string> {
|
|
3000
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
3001
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
3002
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
3003
|
+
const validationPath = resolveMilestoneFile(base, mid, "VALIDATION");
|
|
3004
|
+
const validationRel = relMilestoneFile(base, mid, "VALIDATION");
|
|
3005
|
+
const validationContent = validationPath ? await loadFile(validationPath) : null;
|
|
3006
|
+
|
|
3007
|
+
const inlined: string[] = [];
|
|
3008
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
3009
|
+
const roadmapInline = await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap");
|
|
3010
|
+
inlined.push(roadmapInline);
|
|
3011
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", roadmapInline);
|
|
3012
|
+
|
|
3013
|
+
// Inline all slice summaries (deduplicated by slice ID)
|
|
3014
|
+
let sliceIds: string[] = [];
|
|
3015
|
+
try {
|
|
3016
|
+
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
3017
|
+
if (isDbAvailable()) {
|
|
3018
|
+
sliceIds = getMilestoneSlices(mid)
|
|
3019
|
+
.filter(s => s.status !== "skipped")
|
|
3020
|
+
.map(s => s.id);
|
|
3021
|
+
}
|
|
3022
|
+
} catch (err) {
|
|
3023
|
+
logWarning("prompt", `buildCompleteMilestonePrompt DB lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3024
|
+
}
|
|
3025
|
+
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
3026
|
+
if (sliceIds.length === 0 && roadmapPath) {
|
|
3027
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
3028
|
+
if (roadmapContent) {
|
|
3029
|
+
sliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
const seenSlices = new Set<string>();
|
|
3033
|
+
const summaryRelPaths: string[] = [];
|
|
3034
|
+
for (const sid of sliceIds) {
|
|
3035
|
+
if (seenSlices.has(sid)) continue;
|
|
3036
|
+
seenSlices.add(sid);
|
|
3037
|
+
const summaryPath = resolveSliceFile(base, mid, sid, "SUMMARY");
|
|
3038
|
+
const summaryRel = relSliceFile(base, mid, sid, "SUMMARY");
|
|
3039
|
+
summaryRelPaths.push(summaryRel);
|
|
3040
|
+
// Compact excerpt instead of full inline (#4780). Closer Reads the
|
|
3041
|
+
// full file on-demand when synthesizing LEARNINGS narrative.
|
|
3042
|
+
const summaryExcerpt = await buildSliceSummaryExcerpt(summaryPath, summaryRel, sid);
|
|
3043
|
+
inlined.push(summaryExcerpt);
|
|
3044
|
+
trackPromptContext(contextTelemetry, "slice-summary", "excerpt", summaryExcerpt);
|
|
3045
|
+
}
|
|
3046
|
+
if (summaryRelPaths.length > 0) {
|
|
3047
|
+
const pathList = summaryRelPaths.map(p => `- \`${p}\``).join("\n");
|
|
3048
|
+
const onDemandSummaries = `### On-demand Slice Summaries\n\nExcerpted above. Read the full file for any slice when the excerpt's section heads don't carry enough narrative for the milestone summary you're drafting:\n\n${pathList}`;
|
|
3049
|
+
inlined.push(onDemandSummaries);
|
|
3050
|
+
trackPromptContext(contextTelemetry, "slice-summary", "on-demand", onDemandSummaries);
|
|
3051
|
+
}
|
|
3052
|
+
const validationContext = [
|
|
3053
|
+
formatCloseoutReviewInstructions(validationContent, validationRel, [validationRel, roadmapRel, ...summaryRelPaths]),
|
|
3054
|
+
];
|
|
3055
|
+
trackPromptContext(contextTelemetry, "validation-review-instructions", "inline", validationContext[0]);
|
|
3056
|
+
if (validationContent) {
|
|
3057
|
+
const validationInline = `### Milestone Validation\nSource: \`${validationRel}\`\n\n${validationContent.trim()}`;
|
|
3058
|
+
validationContext.push(validationInline);
|
|
3059
|
+
trackPromptContext(contextTelemetry, "milestone-validation", "inline", validationInline);
|
|
3060
|
+
} else {
|
|
3061
|
+
trackPromptContext(contextTelemetry, "milestone-validation", "skipped", null, "missing");
|
|
3062
|
+
}
|
|
3063
|
+
inlined.unshift(...validationContext);
|
|
3064
|
+
|
|
3065
|
+
// Inline compact requirement facts for standard closeout. Broader narrative
|
|
3066
|
+
// docs stay on-demand unless the caller explicitly asks for full context.
|
|
3067
|
+
if (inlineLevel === "full") {
|
|
3068
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
3069
|
+
if (requirementsInline) {
|
|
3070
|
+
inlined.push(requirementsInline);
|
|
3071
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
3072
|
+
}
|
|
3073
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
3074
|
+
if (decisionsInline) {
|
|
3075
|
+
inlined.push(decisionsInline);
|
|
3076
|
+
trackPromptContext(contextTelemetry, "decisions", "inline", decisionsInline);
|
|
3077
|
+
}
|
|
3078
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
3079
|
+
if (projectInline) {
|
|
3080
|
+
inlined.push(projectInline);
|
|
3081
|
+
trackPromptContext(contextTelemetry, "project", "inline", projectInline);
|
|
3082
|
+
}
|
|
3083
|
+
} else if (inlineLevel === "standard") {
|
|
3084
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
3085
|
+
if (requirementsInline) {
|
|
3086
|
+
inlined.push(requirementsInline);
|
|
3087
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
3088
|
+
}
|
|
3089
|
+
const decisionsOnDemand = onDemandDecisionsBlock("the slice summaries or validation artifact reference a decision that must be re-evaluated before closeout");
|
|
3090
|
+
inlined.push(decisionsOnDemand);
|
|
3091
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", decisionsOnDemand);
|
|
3092
|
+
const projectOnDemand = onDemandProjectBlock("the milestone summary needs product/domain wording that is not present in the roadmap, validation artifact, or slice summaries");
|
|
3093
|
+
inlined.push(projectOnDemand);
|
|
3094
|
+
trackPromptContext(contextTelemetry, "project", "on-demand", projectOnDemand);
|
|
3095
|
+
} else {
|
|
3096
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "minimal inline level");
|
|
3097
|
+
const decisionsOnDemand = onDemandDecisionsBlock("the closeout cannot be completed from the roadmap and slice summaries alone");
|
|
3098
|
+
inlined.push(decisionsOnDemand);
|
|
3099
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", decisionsOnDemand);
|
|
3100
|
+
const projectOnDemand = onDemandProjectBlock("the closeout cannot be completed from the roadmap and slice summaries alone");
|
|
3101
|
+
inlined.push(projectOnDemand);
|
|
3102
|
+
trackPromptContext(contextTelemetry, "project", "on-demand", projectOnDemand);
|
|
3103
|
+
}
|
|
3104
|
+
// Scoped + budgeted — see issue #4719
|
|
3105
|
+
const knowledgeInlineCM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
|
|
3106
|
+
if (knowledgeInlineCM) {
|
|
3107
|
+
inlined.push(knowledgeInlineCM);
|
|
3108
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInlineCM);
|
|
3109
|
+
}
|
|
3110
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
3111
|
+
const contextRel = relMilestoneFile(base, mid, "CONTEXT");
|
|
3112
|
+
const contextInline = inlineLevel === "full"
|
|
3113
|
+
? await inlineFileOptional(contextPath, contextRel, "Milestone Context")
|
|
3114
|
+
: null;
|
|
3115
|
+
if (contextInline) {
|
|
3116
|
+
inlined.push(contextInline);
|
|
3117
|
+
trackPromptContext(contextTelemetry, "milestone-context", "inline", contextInline);
|
|
3118
|
+
} else if (contextPath) {
|
|
3119
|
+
const contextOnDemand = onDemandMilestoneContextBlock(contextRel, "the roadmap, validation artifact, and slice summaries do not explain the milestone's intent clearly enough");
|
|
3120
|
+
inlined.push(contextOnDemand);
|
|
3121
|
+
trackPromptContext(contextTelemetry, "milestone-context", "on-demand", contextOnDemand);
|
|
3122
|
+
} else {
|
|
3123
|
+
trackPromptContext(contextTelemetry, "milestone-context", "skipped", null, "missing");
|
|
3124
|
+
}
|
|
3125
|
+
const templateInline = inlineTemplate("milestone-summary", "Milestone Summary");
|
|
3126
|
+
inlined.push(templateInline);
|
|
3127
|
+
trackPromptContext(contextTelemetry, "templates", "inline", templateInline);
|
|
3128
|
+
|
|
3129
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
3130
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
3131
|
+
trackPromptContext(
|
|
3132
|
+
contextTelemetry,
|
|
3133
|
+
"cap",
|
|
3134
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
3135
|
+
null,
|
|
3136
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
3137
|
+
);
|
|
3138
|
+
const inlinedContext = prependContextModeToBlock(
|
|
3139
|
+
"complete-milestone",
|
|
3140
|
+
base,
|
|
3141
|
+
cappedInlinedContext,
|
|
3142
|
+
);
|
|
3143
|
+
emitPromptContextTelemetry("complete-milestone", contextTelemetry, inlinedContext);
|
|
3144
|
+
|
|
3145
|
+
const milestoneSummaryPath = join(base, `${relMilestonePath(base, mid)}/${mid}-SUMMARY.md`);
|
|
3146
|
+
|
|
3147
|
+
const learningsRelPath = join(relMilestonePath(base, mid), `${mid}-LEARNINGS.md`);
|
|
3148
|
+
const learningsAbsPath = join(base, learningsRelPath);
|
|
3149
|
+
const extractLearningsSteps = buildExtractionStepsBlock({
|
|
3150
|
+
milestoneId: mid,
|
|
3151
|
+
outputPath: learningsAbsPath,
|
|
3152
|
+
relativeOutputPath: learningsRelPath,
|
|
3153
|
+
});
|
|
3154
|
+
|
|
3155
|
+
return loadPrompt("complete-milestone", {
|
|
3156
|
+
workingDirectory: base,
|
|
3157
|
+
milestoneId: mid,
|
|
3158
|
+
milestoneTitle: midTitle,
|
|
3159
|
+
roadmapPath: roadmapRel,
|
|
3160
|
+
inlinedContext,
|
|
3161
|
+
milestoneSummaryPath,
|
|
3162
|
+
extractLearningsSteps,
|
|
3163
|
+
skillActivation: buildSkillActivationBlock({
|
|
3164
|
+
base,
|
|
3165
|
+
milestoneId: mid,
|
|
3166
|
+
milestoneTitle: midTitle,
|
|
3167
|
+
extraContext: [inlinedContext],
|
|
3168
|
+
unitType: "complete-milestone",
|
|
3169
|
+
}),
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
export async function buildValidateMilestonePrompt(
|
|
3174
|
+
mid: string, midTitle: string, base: string, level?: InlineLevel,
|
|
3175
|
+
): Promise<string> {
|
|
3176
|
+
const inlineLevel = level ?? resolveInlineLevel();
|
|
3177
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
3178
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
3179
|
+
|
|
3180
|
+
const inlined: string[] = [];
|
|
3181
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
3182
|
+
const roadmapInline = await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap");
|
|
3183
|
+
inlined.push(roadmapInline);
|
|
3184
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", roadmapInline);
|
|
3185
|
+
|
|
3186
|
+
// Inline verification classes from planning (if available in DB)
|
|
3187
|
+
try {
|
|
3188
|
+
const { isDbAvailable, getMilestone } = await import("./gsd-db.js");
|
|
3189
|
+
if (isDbAvailable()) {
|
|
3190
|
+
const milestone = getMilestone(mid);
|
|
3191
|
+
if (milestone) {
|
|
3192
|
+
const classes: string[] = [];
|
|
3193
|
+
if (milestone.verification_contract) classes.push(`- **Contract:** ${milestone.verification_contract}`);
|
|
3194
|
+
if (milestone.verification_integration) classes.push(`- **Integration:** ${milestone.verification_integration}`);
|
|
3195
|
+
if (milestone.verification_operational) classes.push(`- **Operational:** ${milestone.verification_operational}`);
|
|
3196
|
+
if (milestone.verification_uat) classes.push(`- **UAT:** ${milestone.verification_uat}`);
|
|
3197
|
+
if (classes.length > 0) {
|
|
3198
|
+
const verificationClasses = `### Verification Classes (from planning)\n\nThese verification tiers were defined during milestone planning. Each non-empty class must be checked for evidence during validation.\n\n${classes.join("\n")}`;
|
|
3199
|
+
inlined.push(verificationClasses);
|
|
3200
|
+
trackPromptContext(contextTelemetry, "verification-classes", "inline", verificationClasses);
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
} catch (err) {
|
|
3205
|
+
logWarning("prompt", `buildValidateMilestonePrompt verification classes lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
// Validate from compact slice evidence first. Full slice summaries and
|
|
3209
|
+
// assessments stay on-demand so milestone validation does not rehydrate the
|
|
3210
|
+
// whole milestone on every closeout pass.
|
|
3211
|
+
let valSliceIds: string[] = [];
|
|
3212
|
+
try {
|
|
3213
|
+
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
3214
|
+
if (isDbAvailable()) {
|
|
3215
|
+
valSliceIds = getMilestoneSlices(mid)
|
|
3216
|
+
.filter(s => s.status !== "skipped")
|
|
3217
|
+
.map(s => s.id);
|
|
3218
|
+
}
|
|
3219
|
+
} catch (err) {
|
|
3220
|
+
logWarning("prompt", `buildValidateMilestonePrompt slice IDs lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3221
|
+
}
|
|
3222
|
+
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
3223
|
+
if (valSliceIds.length === 0 && roadmapPath) {
|
|
3224
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
3225
|
+
if (roadmapContent) {
|
|
3226
|
+
valSliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
const seenValSlices = new Set<string>();
|
|
3230
|
+
const onDemandValidationPaths: string[] = [];
|
|
3231
|
+
for (const sid of valSliceIds) {
|
|
3232
|
+
if (seenValSlices.has(sid)) continue;
|
|
3233
|
+
seenValSlices.add(sid);
|
|
3234
|
+
const summaryPath = resolveSliceFile(base, mid, sid, "SUMMARY");
|
|
3235
|
+
const summaryRel = relSliceFile(base, mid, sid, "SUMMARY");
|
|
3236
|
+
const summaryExcerpt = await buildSliceSummaryExcerpt(summaryPath, summaryRel, sid);
|
|
3237
|
+
inlined.push(summaryExcerpt);
|
|
3238
|
+
onDemandValidationPaths.push(summaryRel);
|
|
3239
|
+
trackPromptContext(contextTelemetry, "slice-summary", "excerpt", summaryExcerpt);
|
|
3240
|
+
|
|
3241
|
+
const assessmentPath = resolveSliceFile(base, mid, sid, "ASSESSMENT");
|
|
3242
|
+
const assessmentRel = relSliceFile(base, mid, sid, "ASSESSMENT");
|
|
3243
|
+
const assessmentExcerpt = await buildSliceAssessmentExcerpt(assessmentPath, assessmentRel, sid);
|
|
3244
|
+
if (assessmentExcerpt) {
|
|
3245
|
+
inlined.push(assessmentExcerpt);
|
|
3246
|
+
trackPromptContext(contextTelemetry, "slice-assessment", "excerpt", assessmentExcerpt);
|
|
3247
|
+
} else {
|
|
3248
|
+
trackPromptContext(contextTelemetry, "slice-assessment", "skipped", null, "missing");
|
|
3249
|
+
}
|
|
3250
|
+
onDemandValidationPaths.push(assessmentRel);
|
|
3251
|
+
}
|
|
3252
|
+
if (onDemandValidationPaths.length > 0) {
|
|
3253
|
+
const pathList = onDemandValidationPaths.map(p => `- \`${p}\``).join("\n");
|
|
3254
|
+
const onDemandBlock = [
|
|
3255
|
+
"### On-demand Validation Artifacts",
|
|
3256
|
+
"",
|
|
3257
|
+
"Slice summaries and assessments are excerpted above. Read full files only when an excerpt is missing, truncated, or internally inconsistent with validation evidence:",
|
|
3258
|
+
"",
|
|
3259
|
+
pathList,
|
|
3260
|
+
].join("\n");
|
|
3261
|
+
inlined.push(onDemandBlock);
|
|
3262
|
+
trackPromptContext(contextTelemetry, "slice-summary,slice-assessment", "on-demand", onDemandBlock);
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
// Aggregate unresolved follow-ups and known limitations across slices
|
|
3266
|
+
const outstandingItems: string[] = [];
|
|
3267
|
+
for (const sid of valSliceIds) {
|
|
3268
|
+
const summaryPath = resolveSliceFile(base, mid, sid, "SUMMARY");
|
|
3269
|
+
if (!summaryPath) continue;
|
|
3270
|
+
const content = await loadFile(summaryPath);
|
|
3271
|
+
if (!content) continue;
|
|
3272
|
+
const summary = parseSummary(content);
|
|
3273
|
+
if (summary.followUps) outstandingItems.push(`- **${sid} Follow-ups:** ${summary.followUps.trim()}`);
|
|
3274
|
+
if (summary.knownLimitations) outstandingItems.push(`- **${sid} Known Limitations:** ${summary.knownLimitations.trim()}`);
|
|
3275
|
+
}
|
|
3276
|
+
if (outstandingItems.length > 0) {
|
|
3277
|
+
const outstandingBlock = `### Outstanding Items (aggregated from slice summaries)\n\nThese follow-ups and known limitations were documented during slice completion but have not been resolved.\n\n${outstandingItems.join('\n')}`;
|
|
3278
|
+
inlined.push(outstandingBlock);
|
|
3279
|
+
trackPromptContext(contextTelemetry, "outstanding-items", "inline", outstandingBlock);
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
// Inline existing VALIDATION file if this is a re-validation round
|
|
3283
|
+
const validationPath = resolveMilestoneFile(base, mid, "VALIDATION");
|
|
3284
|
+
const validationRel = relMilestoneFile(base, mid, "VALIDATION");
|
|
3285
|
+
const validationContent = validationPath ? await loadFile(validationPath) : null;
|
|
3286
|
+
let remediationRound = 0;
|
|
3287
|
+
if (validationContent) {
|
|
3288
|
+
const roundMatch = validationContent.match(/remediation_round:\s*(\d+)/);
|
|
3289
|
+
remediationRound = roundMatch ? parseInt(roundMatch[1], 10) + 1 : 1;
|
|
3290
|
+
const previousValidation = `### Previous Validation (re-validation round ${remediationRound})\nSource: \`${validationRel}\`\n\n${validationContent.trim()}`;
|
|
3291
|
+
inlined.push(previousValidation);
|
|
3292
|
+
trackPromptContext(contextTelemetry, "milestone-validation", "inline", previousValidation);
|
|
3293
|
+
} else {
|
|
3294
|
+
trackPromptContext(contextTelemetry, "milestone-validation", "skipped", null, "missing");
|
|
3295
|
+
}
|
|
3296
|
+
|
|
3297
|
+
// Validation keeps compact requirements inline, but broad narrative docs are
|
|
3298
|
+
// on-demand in standard mode to avoid rehydrating full project context.
|
|
3299
|
+
if (inlineLevel === "full") {
|
|
3300
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
3301
|
+
if (requirementsInline) {
|
|
3302
|
+
inlined.push(requirementsInline);
|
|
3303
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
3304
|
+
}
|
|
3305
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
3306
|
+
if (decisionsInline) {
|
|
3307
|
+
inlined.push(decisionsInline);
|
|
3308
|
+
trackPromptContext(contextTelemetry, "decisions", "inline", decisionsInline);
|
|
3309
|
+
}
|
|
3310
|
+
const projectInline = await inlineProjectFromDb(base);
|
|
3311
|
+
if (projectInline) {
|
|
3312
|
+
inlined.push(projectInline);
|
|
3313
|
+
trackPromptContext(contextTelemetry, "project", "inline", projectInline);
|
|
3314
|
+
}
|
|
3315
|
+
} else if (inlineLevel === "standard") {
|
|
3316
|
+
const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
|
|
3317
|
+
if (requirementsInline) {
|
|
3318
|
+
inlined.push(requirementsInline);
|
|
3319
|
+
trackPromptContext(contextTelemetry, "requirements", "inline", requirementsInline);
|
|
3320
|
+
}
|
|
3321
|
+
const decisionsOnDemand = onDemandDecisionsBlock("a validation finding conflicts with an existing architectural decision");
|
|
3322
|
+
inlined.push(decisionsOnDemand);
|
|
3323
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", decisionsOnDemand);
|
|
3324
|
+
const projectOnDemand = onDemandProjectBlock("validation evidence needs product/domain context that is not present in the roadmap or slice artifacts");
|
|
3325
|
+
inlined.push(projectOnDemand);
|
|
3326
|
+
trackPromptContext(contextTelemetry, "project", "on-demand", projectOnDemand);
|
|
3327
|
+
} else {
|
|
3328
|
+
trackPromptContext(contextTelemetry, "requirements", "skipped", null, "minimal inline level");
|
|
3329
|
+
const decisionsOnDemand = onDemandDecisionsBlock("validation cannot determine the correct verdict from milestone artifacts alone");
|
|
3330
|
+
inlined.push(decisionsOnDemand);
|
|
3331
|
+
trackPromptContext(contextTelemetry, "decisions", "on-demand", decisionsOnDemand);
|
|
3332
|
+
const projectOnDemand = onDemandProjectBlock("validation cannot determine the correct verdict from milestone artifacts alone");
|
|
3333
|
+
inlined.push(projectOnDemand);
|
|
3334
|
+
trackPromptContext(contextTelemetry, "project", "on-demand", projectOnDemand);
|
|
3335
|
+
}
|
|
3336
|
+
// Scoped + budgeted — see issue #4719
|
|
3337
|
+
const knowledgeInline = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
|
|
3338
|
+
if (knowledgeInline) {
|
|
3339
|
+
inlined.push(knowledgeInline);
|
|
3340
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInline);
|
|
3341
|
+
}
|
|
3342
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
3343
|
+
const contextRel = relMilestoneFile(base, mid, "CONTEXT");
|
|
3344
|
+
const contextInline = inlineLevel === "full"
|
|
3345
|
+
? await inlineFileOptional(contextPath, contextRel, "Milestone Context")
|
|
3346
|
+
: null;
|
|
3347
|
+
if (contextInline) {
|
|
3348
|
+
inlined.push(contextInline);
|
|
3349
|
+
trackPromptContext(contextTelemetry, "milestone-context", "inline", contextInline);
|
|
3350
|
+
} else if (contextPath) {
|
|
3351
|
+
const contextOnDemand = onDemandMilestoneContextBlock(contextRel, "the roadmap and slice artifacts do not explain the intended outcome clearly enough");
|
|
3352
|
+
inlined.push(contextOnDemand);
|
|
3353
|
+
trackPromptContext(contextTelemetry, "milestone-context", "on-demand", contextOnDemand);
|
|
3354
|
+
} else {
|
|
3355
|
+
trackPromptContext(contextTelemetry, "milestone-context", "skipped", null, "missing");
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3358
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`;
|
|
3359
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
3360
|
+
trackPromptContext(
|
|
3361
|
+
contextTelemetry,
|
|
3362
|
+
"cap",
|
|
3363
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
3364
|
+
null,
|
|
3365
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
3366
|
+
);
|
|
3367
|
+
const inlinedContext = prependContextModeToBlock(
|
|
3368
|
+
"validate-milestone",
|
|
3369
|
+
base,
|
|
3370
|
+
cappedInlinedContext,
|
|
3371
|
+
);
|
|
3372
|
+
emitPromptContextTelemetry("validate-milestone", contextTelemetry, inlinedContext);
|
|
3373
|
+
|
|
3374
|
+
const validationOutputPath = join(base, `${relMilestonePath(base, mid)}/${mid}-VALIDATION.md`);
|
|
3375
|
+
const roadmapOutputPath = `${relMilestonePath(base, mid)}/${mid}-ROADMAP.md`;
|
|
3376
|
+
|
|
3377
|
+
// Every milestone validation turn owns MV01–MV04 unconditionally: the
|
|
3378
|
+
// registry is the source of truth for which gates the validator must
|
|
3379
|
+
// address, and the block below is what the template renders so the
|
|
3380
|
+
// assistant can never accidentally skip one.
|
|
3381
|
+
const mvGates = getGatesForTurn("validate-milestone");
|
|
3382
|
+
const gatesToEvaluate = renderGatesToCloseBlock(mvGates, {
|
|
3383
|
+
pending: new Set(mvGates.map((g) => g.id)),
|
|
3384
|
+
allowOmit: false,
|
|
3385
|
+
});
|
|
3386
|
+
|
|
3387
|
+
return loadPrompt("validate-milestone", {
|
|
3388
|
+
workingDirectory: base,
|
|
3389
|
+
milestoneId: mid,
|
|
3390
|
+
milestoneTitle: midTitle,
|
|
3391
|
+
roadmapPath: roadmapOutputPath,
|
|
3392
|
+
inlinedContext,
|
|
3393
|
+
validationPath: validationOutputPath,
|
|
3394
|
+
remediationRound: String(remediationRound),
|
|
3395
|
+
gatesToEvaluate,
|
|
3396
|
+
skillActivation: buildSkillActivationBlock({
|
|
3397
|
+
base,
|
|
3398
|
+
milestoneId: mid,
|
|
3399
|
+
milestoneTitle: midTitle,
|
|
3400
|
+
extraContext: [inlinedContext],
|
|
3401
|
+
unitType: "validate-milestone",
|
|
3402
|
+
}),
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
export async function buildReplanSlicePrompt(
|
|
3407
|
+
mid: string, midTitle: string, sid: string, sTitle: string, base: string,
|
|
3408
|
+
): Promise<string> {
|
|
3409
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
3410
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
3411
|
+
const slicePlanPath = resolveSliceFile(base, mid, sid, "PLAN");
|
|
3412
|
+
const slicePlanRel = relSliceFile(base, mid, sid, "PLAN");
|
|
3413
|
+
const sliceContextPath = resolveSliceFile(base, mid, sid, "CONTEXT");
|
|
3414
|
+
const sliceContextRel = relSliceFile(base, mid, sid, "CONTEXT");
|
|
3415
|
+
|
|
3416
|
+
const inlined: string[] = [];
|
|
3417
|
+
inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
|
|
3418
|
+
const sliceCtxInline = await inlineFileOptional(sliceContextPath, sliceContextRel, "Slice Context (from discussion)");
|
|
3419
|
+
if (sliceCtxInline) inlined.push(sliceCtxInline);
|
|
3420
|
+
inlined.push(await inlineFile(slicePlanPath, slicePlanRel, "Current Slice Plan"));
|
|
3421
|
+
|
|
3422
|
+
// Find the blocker task summary — the completed task with blocker_discovered: true
|
|
3423
|
+
let blockerTaskId = "";
|
|
3424
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
3425
|
+
if (tDir) {
|
|
3426
|
+
const summaryFiles = resolveTaskFiles(tDir, "SUMMARY").sort();
|
|
3427
|
+
for (const file of summaryFiles) {
|
|
3428
|
+
const absPath = join(tDir, file);
|
|
3429
|
+
const content = await loadFile(absPath);
|
|
3430
|
+
if (!content) continue;
|
|
3431
|
+
const summary = parseSummary(content);
|
|
3432
|
+
const sRel = relSlicePath(base, mid, sid);
|
|
3433
|
+
const relPath = `${sRel}/tasks/${file}`;
|
|
3434
|
+
if (summary.frontmatter.blocker_discovered) {
|
|
3435
|
+
blockerTaskId = summary.frontmatter.id || file.replace(/-SUMMARY\.md$/i, "");
|
|
3436
|
+
inlined.push(await buildTaskSummaryExcerpt(absPath, relPath, blockerTaskId, { blocker: true }));
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
}
|
|
3440
|
+
|
|
3441
|
+
// Inline decisions
|
|
3442
|
+
const decisionsInline = await inlineDecisionsFromDb(base, mid);
|
|
3443
|
+
if (decisionsInline) inlined.push(decisionsInline);
|
|
3444
|
+
const replanActiveOverrides = await loadActiveOverrides(base);
|
|
3445
|
+
const replanOverridesInline = formatOverridesSection(replanActiveOverrides);
|
|
3446
|
+
if (replanOverridesInline) inlined.unshift(replanOverridesInline);
|
|
3447
|
+
|
|
3448
|
+
const inlinedContext = prependContextModeToBlock(
|
|
3449
|
+
"replan-slice",
|
|
3450
|
+
base,
|
|
3451
|
+
capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`),
|
|
3452
|
+
);
|
|
3453
|
+
|
|
3454
|
+
const replanPath = join(base, `${relSlicePath(base, mid, sid)}/${sid}-REPLAN.md`);
|
|
3455
|
+
|
|
3456
|
+
// Build capture context for replan prompt (captures that triggered this replan)
|
|
3457
|
+
let captureContext = "(none)";
|
|
3458
|
+
try {
|
|
3459
|
+
const { loadReplanCaptures } = await import("./triage-resolution.js");
|
|
3460
|
+
const replanCaptures = loadReplanCaptures(base);
|
|
3461
|
+
if (replanCaptures.length > 0) {
|
|
3462
|
+
captureContext = replanCaptures.map(c =>
|
|
3463
|
+
`- **${c.id}**: "${c.text}" — ${c.rationale ?? "no rationale"}`
|
|
3464
|
+
).join("\n");
|
|
3465
|
+
}
|
|
3466
|
+
} catch (err) {
|
|
3467
|
+
logWarning("prompt", `loadReplanCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3470
|
+
return loadPrompt("replan-slice", {
|
|
3471
|
+
workingDirectory: base,
|
|
3472
|
+
milestoneId: mid,
|
|
3473
|
+
sliceId: sid,
|
|
3474
|
+
sliceTitle: sTitle,
|
|
3475
|
+
slicePath: relSlicePath(base, mid, sid),
|
|
3476
|
+
planPath: join(base, slicePlanRel),
|
|
3477
|
+
blockerTaskId,
|
|
3478
|
+
inlinedContext,
|
|
3479
|
+
replanPath,
|
|
3480
|
+
captureContext,
|
|
3481
|
+
skillActivation: buildSkillActivationBlock({
|
|
3482
|
+
base,
|
|
3483
|
+
milestoneId: mid,
|
|
3484
|
+
milestoneTitle: midTitle,
|
|
3485
|
+
sliceId: sid,
|
|
3486
|
+
sliceTitle: sTitle,
|
|
3487
|
+
extraContext: [inlinedContext, captureContext],
|
|
3488
|
+
unitType: "replan-slice",
|
|
3489
|
+
}),
|
|
3490
|
+
});
|
|
3491
|
+
}
|
|
3492
|
+
|
|
3493
|
+
export async function buildRunUatPrompt(
|
|
3494
|
+
mid: string, sliceId: string, uatPath: string, uatContent: string, base: string,
|
|
3495
|
+
): Promise<string> {
|
|
3496
|
+
// Run-UAT keeps only the UAT body inline. Prior slice/project context is
|
|
3497
|
+
// compact or on-demand so validation does not pay for full closeout context.
|
|
3498
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
3499
|
+
const resolveArtifact: ArtifactResolver = async (key) => {
|
|
3500
|
+
switch (key) {
|
|
3501
|
+
case "slice-uat": {
|
|
3502
|
+
// Use the in-memory snapshot the caller already loaded (#4925 review).
|
|
3503
|
+
// Re-reading from disk via inlineFile(p, uatPath, ...) would risk
|
|
3504
|
+
// drift between the inlined body and uatType (computed from
|
|
3505
|
+
// uatContent below) if the file changes mid-dispatch.
|
|
3506
|
+
const trimmed = uatContent.trim();
|
|
3507
|
+
if (!trimmed) {
|
|
3508
|
+
const body = `### ${sliceId} UAT\nSource: \`${uatPath}\`\n\n_(not found — file does not exist yet)_`;
|
|
3509
|
+
trackPromptContext(contextTelemetry, "slice-uat", "inline", body);
|
|
3510
|
+
return body;
|
|
3511
|
+
}
|
|
3512
|
+
const body = `### ${sliceId} UAT\nSource: \`${uatPath}\`\n\n${trimmed}`;
|
|
3513
|
+
trackPromptContext(contextTelemetry, "slice-uat", "inline", body);
|
|
3514
|
+
return body;
|
|
3515
|
+
}
|
|
3516
|
+
case "slice-summary": {
|
|
3517
|
+
trackPromptContext(contextTelemetry, "slice-summary", "skipped", null, "handled by excerpt resolver");
|
|
3518
|
+
return null;
|
|
3519
|
+
}
|
|
3520
|
+
case "project": {
|
|
3521
|
+
trackPromptContext(contextTelemetry, "project", "skipped", null, "handled as on-demand path");
|
|
3522
|
+
return null;
|
|
3523
|
+
}
|
|
3524
|
+
default:
|
|
3525
|
+
return null;
|
|
3526
|
+
}
|
|
3527
|
+
};
|
|
3528
|
+
const resolveExcerpt: ExcerptResolver = async (key) => {
|
|
3529
|
+
switch (key) {
|
|
3530
|
+
case "slice-summary": {
|
|
3531
|
+
const p = resolveSliceFile(base, mid, sliceId, "SUMMARY");
|
|
3532
|
+
const r = relSliceFile(base, mid, sliceId, "SUMMARY");
|
|
3533
|
+
if (!p) {
|
|
3534
|
+
trackPromptContext(contextTelemetry, "slice-summary", "skipped", null, "missing");
|
|
3535
|
+
return null;
|
|
3536
|
+
}
|
|
3537
|
+
const body = await buildSliceSummaryExcerpt(p, r, sliceId);
|
|
3538
|
+
trackPromptContext(contextTelemetry, "slice-summary", "excerpt", body);
|
|
3539
|
+
return body;
|
|
3540
|
+
}
|
|
3541
|
+
default:
|
|
3542
|
+
return null;
|
|
3543
|
+
}
|
|
3544
|
+
};
|
|
3545
|
+
|
|
3546
|
+
const composed = await composeUnitContext("run-uat", {
|
|
3547
|
+
base: { unitType: "run-uat", basePath: base, milestoneId: mid, sliceId },
|
|
3548
|
+
resolveArtifact,
|
|
3549
|
+
resolveExcerpt,
|
|
3550
|
+
});
|
|
3551
|
+
const parts: string[] = [];
|
|
3552
|
+
if (composed.prepend) parts.push(composed.prepend);
|
|
3553
|
+
if (composed.inline) parts.push(composed.inline);
|
|
3554
|
+
const projectOnDemand = [
|
|
3555
|
+
"### On-demand Project Context",
|
|
3556
|
+
"",
|
|
3557
|
+
`Project context is available at \`${relGsdRootFile("PROJECT")}\`. Read it only if the UAT spec or slice summary lacks enough product/domain context to assess the scenario.`,
|
|
3558
|
+
].join("\n");
|
|
3559
|
+
parts.push(projectOnDemand);
|
|
3560
|
+
trackPromptContext(contextTelemetry, "project", "on-demand", projectOnDemand);
|
|
3561
|
+
const composedBody = parts.join("\n\n---\n\n");
|
|
3562
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${composedBody}`;
|
|
3563
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
3564
|
+
trackPromptContext(
|
|
3565
|
+
contextTelemetry,
|
|
3566
|
+
"cap",
|
|
3567
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
3568
|
+
null,
|
|
3569
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
3570
|
+
);
|
|
3571
|
+
const inlinedContext = prependContextModeToBlock(
|
|
3572
|
+
"run-uat",
|
|
3573
|
+
base,
|
|
3574
|
+
cappedInlinedContext,
|
|
3575
|
+
);
|
|
3576
|
+
emitPromptContextTelemetry("run-uat", contextTelemetry, inlinedContext);
|
|
3577
|
+
|
|
3578
|
+
const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
|
|
3579
|
+
const uatType = resolveEffectiveUatType(uatContent);
|
|
3580
|
+
|
|
3581
|
+
return loadPrompt("run-uat", {
|
|
3582
|
+
workingDirectory: base,
|
|
3583
|
+
milestoneId: mid,
|
|
3584
|
+
sliceId,
|
|
3585
|
+
uatPath,
|
|
3586
|
+
uatResultPath,
|
|
3587
|
+
uatType,
|
|
3588
|
+
inlinedContext,
|
|
3589
|
+
skillActivation: buildSkillActivationBlock({
|
|
3590
|
+
base,
|
|
3591
|
+
milestoneId: mid,
|
|
3592
|
+
sliceId,
|
|
3593
|
+
extraContext: [inlinedContext],
|
|
3594
|
+
unitType: "run-uat",
|
|
3595
|
+
}),
|
|
3596
|
+
});
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3599
|
+
export async function buildReassessRoadmapPrompt(
|
|
3600
|
+
mid: string, midTitle: string, completedSliceId: string, base: string, level?: InlineLevel,
|
|
3601
|
+
): Promise<string> {
|
|
3602
|
+
void level;
|
|
3603
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
3604
|
+
|
|
3605
|
+
// Reassess-roadmap runs between slices, so keep only the roadmap and
|
|
3606
|
+
// completed-slice evidence in prompt. Broader project docs stay on-demand.
|
|
3607
|
+
const resolveArtifact: ArtifactResolver = async (key) => {
|
|
3608
|
+
switch (key) {
|
|
3609
|
+
case "roadmap": {
|
|
3610
|
+
const p = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
3611
|
+
const r = relMilestoneFile(base, mid, "ROADMAP");
|
|
3612
|
+
const body = await inlineFile(p, r, "Current Roadmap");
|
|
3613
|
+
trackPromptContext(contextTelemetry, "roadmap", "inline", body);
|
|
3614
|
+
return body;
|
|
3615
|
+
}
|
|
3616
|
+
case "slice-context": {
|
|
3617
|
+
const p = resolveSliceFile(base, mid, completedSliceId, "CONTEXT");
|
|
3618
|
+
const r = relSliceFile(base, mid, completedSliceId, "CONTEXT");
|
|
3619
|
+
const body = await inlineFileOptional(p, r, "Slice Context (from discussion)");
|
|
3620
|
+
trackPromptContext(contextTelemetry, "slice-context", body ? "inline" : "skipped", body, body ? undefined : "missing");
|
|
3621
|
+
return body;
|
|
3622
|
+
}
|
|
3623
|
+
case "slice-summary": {
|
|
3624
|
+
trackPromptContext(contextTelemetry, "slice-summary", "skipped", null, "handled by excerpt resolver");
|
|
3625
|
+
return null;
|
|
3626
|
+
}
|
|
3627
|
+
case "project":
|
|
3628
|
+
case "requirements":
|
|
3629
|
+
case "decisions":
|
|
3630
|
+
trackPromptContext(contextTelemetry, key, "skipped", null, "handled as on-demand path");
|
|
3631
|
+
return null;
|
|
3632
|
+
default:
|
|
3633
|
+
return null;
|
|
3634
|
+
}
|
|
3635
|
+
};
|
|
3636
|
+
const resolveExcerpt: ExcerptResolver = async (key) => {
|
|
3637
|
+
switch (key) {
|
|
3638
|
+
case "slice-summary": {
|
|
3639
|
+
const p = resolveSliceFile(base, mid, completedSliceId, "SUMMARY");
|
|
3640
|
+
const r = relSliceFile(base, mid, completedSliceId, "SUMMARY");
|
|
3641
|
+
const body = await buildSliceSummaryExcerpt(p, r, completedSliceId);
|
|
3642
|
+
trackPromptContext(contextTelemetry, "slice-summary", "excerpt", body);
|
|
3643
|
+
return body;
|
|
3644
|
+
}
|
|
3645
|
+
default:
|
|
3646
|
+
return null;
|
|
3647
|
+
}
|
|
3648
|
+
};
|
|
3649
|
+
|
|
3650
|
+
const composed = await composeUnitContext("reassess-roadmap", {
|
|
3651
|
+
base: { unitType: "reassess-roadmap", basePath: base, milestoneId: mid, sliceId: completedSliceId },
|
|
3652
|
+
resolveArtifact,
|
|
3653
|
+
resolveExcerpt,
|
|
3654
|
+
});
|
|
3655
|
+
const parts: string[] = [];
|
|
3656
|
+
if (composed.prepend) parts.push(composed.prepend);
|
|
3657
|
+
if (composed.inline) parts.push(composed.inline);
|
|
3658
|
+
const onDemandDocs = [
|
|
3659
|
+
"### On-demand Planning Context",
|
|
3660
|
+
"",
|
|
3661
|
+
"Broader project context is available if the roadmap update needs it. Read only the specific source that answers the reassessment question:",
|
|
3662
|
+
"",
|
|
3663
|
+
`- \`${relGsdRootFile("PROJECT")}\` — product/project narrative`,
|
|
3664
|
+
`- \`${relGsdRootFile("REQUIREMENTS")}\` — requirement status and acceptance criteria`,
|
|
3665
|
+
`- \`${relGsdRootFile("DECISIONS")}\` — active architecture/product decisions`,
|
|
3666
|
+
].join("\n");
|
|
3667
|
+
parts.push(onDemandDocs);
|
|
3668
|
+
trackPromptContext(contextTelemetry, "project,requirements,decisions", "on-demand", onDemandDocs);
|
|
3669
|
+
// Knowledge block stays outside the composer — budgeted, scoped via
|
|
3670
|
+
// keyword extraction (#4719). Future phase folds it in.
|
|
3671
|
+
const knowledgeInlineRA = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
|
|
3672
|
+
if (knowledgeInlineRA) {
|
|
3673
|
+
parts.push(knowledgeInlineRA);
|
|
3674
|
+
trackPromptContext(contextTelemetry, "knowledge", "inline", knowledgeInlineRA);
|
|
3675
|
+
} else {
|
|
3676
|
+
trackPromptContext(contextTelemetry, "knowledge", "skipped", null, "missing");
|
|
3677
|
+
}
|
|
3678
|
+
|
|
3679
|
+
const rawInlinedContext = `## Inlined Context (preloaded — do not re-read these files)\n\n${parts.join("\n\n---\n\n")}`;
|
|
3680
|
+
const cappedInlinedContext = capPreamble(rawInlinedContext);
|
|
3681
|
+
trackPromptContext(
|
|
3682
|
+
contextTelemetry,
|
|
3683
|
+
"cap",
|
|
3684
|
+
cappedInlinedContext.length < rawInlinedContext.length ? "skipped" : "inline",
|
|
3685
|
+
null,
|
|
3686
|
+
cappedInlinedContext.length < rawInlinedContext.length ? `dropped ${rawInlinedContext.length - cappedInlinedContext.length} chars` : "within budget",
|
|
3687
|
+
);
|
|
3688
|
+
const inlinedContext = prependContextModeToBlock(
|
|
3689
|
+
"reassess-roadmap",
|
|
3690
|
+
base,
|
|
3691
|
+
cappedInlinedContext,
|
|
3692
|
+
);
|
|
3693
|
+
emitPromptContextTelemetry("reassess-roadmap", contextTelemetry, inlinedContext);
|
|
3694
|
+
|
|
3695
|
+
const assessmentPath = join(base, relSliceFile(base, mid, completedSliceId, "ASSESSMENT"));
|
|
3696
|
+
|
|
3697
|
+
// Build deferred captures context for reassess prompt
|
|
3698
|
+
let deferredCaptures = "(none)";
|
|
3699
|
+
try {
|
|
3700
|
+
const { loadDeferredCaptures } = await import("./triage-resolution.js");
|
|
3701
|
+
const deferred = loadDeferredCaptures(base);
|
|
3702
|
+
if (deferred.length > 0) {
|
|
3703
|
+
deferredCaptures = deferred.map(c =>
|
|
3704
|
+
`- **${c.id}**: "${c.text}" — ${c.rationale ?? "deferred during triage"}`
|
|
3705
|
+
).join("\n");
|
|
3706
|
+
}
|
|
3707
|
+
} catch (err) {
|
|
3708
|
+
logWarning("prompt", `loadDeferredCaptures failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
const reassessCommitInstruction = "Do not commit — .gsd/ planning docs are managed externally and not tracked in git.";
|
|
3712
|
+
|
|
3713
|
+
return loadPrompt("reassess-roadmap", {
|
|
3714
|
+
workingDirectory: base,
|
|
3715
|
+
milestoneId: mid,
|
|
3716
|
+
milestoneTitle: midTitle,
|
|
3717
|
+
completedSliceId,
|
|
3718
|
+
roadmapPath: relMilestoneFile(base, mid, "ROADMAP"),
|
|
3719
|
+
assessmentPath,
|
|
3720
|
+
inlinedContext,
|
|
3721
|
+
deferredCaptures,
|
|
3722
|
+
commitInstruction: reassessCommitInstruction,
|
|
3723
|
+
skillActivation: buildSkillActivationBlock({
|
|
3724
|
+
base,
|
|
3725
|
+
milestoneId: mid,
|
|
3726
|
+
milestoneTitle: midTitle,
|
|
3727
|
+
extraContext: [inlinedContext, deferredCaptures],
|
|
3728
|
+
unitType: "reassess-roadmap",
|
|
3729
|
+
}),
|
|
3730
|
+
});
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
// ─── Reactive Execute Prompt ──────────────────────────────────────────────
|
|
3734
|
+
|
|
3735
|
+
export async function buildReactiveExecutePrompt(
|
|
3736
|
+
mid: string, midTitle: string, sid: string, sTitle: string,
|
|
3737
|
+
readyTaskIds: string[], base: string,
|
|
3738
|
+
subagentModel?: string,
|
|
3739
|
+
opts?: { sessionContextWindow?: number; modelRegistry?: MinimalModelRegistry; sessionProvider?: string },
|
|
3740
|
+
): Promise<string> {
|
|
3741
|
+
const { loadSliceTaskIO, deriveTaskGraph, graphMetrics } = await import("./reactive-graph.js");
|
|
3742
|
+
|
|
3743
|
+
// Build graph for context
|
|
3744
|
+
const taskIO = await loadSliceTaskIO(base, mid, sid);
|
|
3745
|
+
const graph = deriveTaskGraph(taskIO);
|
|
3746
|
+
const metrics = graphMetrics(graph);
|
|
3747
|
+
|
|
3748
|
+
// Build graph context section
|
|
3749
|
+
const graphLines: string[] = [];
|
|
3750
|
+
for (const node of graph) {
|
|
3751
|
+
const status = node.done ? "✅ done" : readyTaskIds.includes(node.id) ? "🟢 ready" : "⏳ waiting";
|
|
3752
|
+
const deps = node.dependsOn.length > 0 ? ` (depends on: ${node.dependsOn.join(", ")})` : "";
|
|
3753
|
+
graphLines.push(`- **${node.id}: ${node.title}** — ${status}${deps}`);
|
|
3754
|
+
if (node.outputFiles.length > 0) {
|
|
3755
|
+
graphLines.push(` - Outputs: ${node.outputFiles.map(f => `\`${f}\``).join(", ")}`);
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
const graphContext = [
|
|
3759
|
+
`Tasks: ${metrics.taskCount}, Edges: ${metrics.edgeCount}, Ready: ${metrics.readySetSize}`,
|
|
3760
|
+
"",
|
|
3761
|
+
...graphLines,
|
|
3762
|
+
].join("\n");
|
|
3763
|
+
|
|
3764
|
+
// Build individual subagent prompts for each ready task
|
|
3765
|
+
const subagentSections: string[] = [];
|
|
3766
|
+
const readyTaskListLines: string[] = [];
|
|
3767
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
3768
|
+
const contextWindow = resolveExecutorContextWindow(opts?.modelRegistry, prefs?.preferences, opts?.sessionContextWindow, opts?.sessionProvider);
|
|
3769
|
+
const budgets = computeBudgets(contextWindow);
|
|
3770
|
+
const perSubagentCarryForwardBudget = Math.max(
|
|
3771
|
+
1_000,
|
|
3772
|
+
Math.floor((budgets.inlineContextBudgetChars * 0.4) / Math.max(1, readyTaskIds.length)),
|
|
3773
|
+
);
|
|
3774
|
+
const contextTelemetry: PromptContextTelemetryEntry[] = [];
|
|
3775
|
+
trackPromptContext(contextTelemetry, "graph-context", "inline", graphContext);
|
|
3776
|
+
|
|
3777
|
+
for (const tid of readyTaskIds) {
|
|
3778
|
+
const node = graph.find((n) => n.id === tid);
|
|
3779
|
+
const tTitle = node?.title ?? tid;
|
|
3780
|
+
readyTaskListLines.push(`- **${tid}: ${tTitle}**`);
|
|
3781
|
+
|
|
3782
|
+
// Build dependency-scoped carry-forward paths for this task
|
|
3783
|
+
const depPaths = await getDependencyTaskSummaryPaths(
|
|
3784
|
+
mid, sid, tid, node?.dependsOn ?? [], base,
|
|
3785
|
+
);
|
|
3786
|
+
|
|
3787
|
+
const taskPlanPath = resolveTaskFile(base, mid, sid, tid, "PLAN");
|
|
3788
|
+
const taskPlanContent = taskPlanPath ? await loadFile(taskPlanPath) : null;
|
|
3789
|
+
const taskPlanRelPath = `${relSlicePath(base, mid, sid)}/tasks/${tid}-PLAN.md`;
|
|
3790
|
+
const taskPlanInline = taskPlanContent
|
|
3791
|
+
? [
|
|
3792
|
+
"## Inlined Task Plan (authoritative local execution contract)",
|
|
3793
|
+
`Source: \`${taskPlanRelPath}\``,
|
|
3794
|
+
"",
|
|
3795
|
+
taskPlanContent.trim(),
|
|
3796
|
+
].join("\n")
|
|
3797
|
+
: [
|
|
3798
|
+
"## Inlined Task Plan (authoritative local execution contract)",
|
|
3799
|
+
`Task plan not found at dispatch time. Read \`${taskPlanRelPath}\` before executing.`,
|
|
3800
|
+
].join("\n");
|
|
3801
|
+
const carryForwardSection = await buildCarryForwardSection(depPaths, base);
|
|
3802
|
+
const finalCarryForwardSection = carryForwardSection.length > perSubagentCarryForwardBudget
|
|
3803
|
+
? truncateAtSectionBoundary(carryForwardSection, perSubagentCarryForwardBudget).content
|
|
3804
|
+
: carryForwardSection;
|
|
3805
|
+
trackPromptContext(
|
|
3806
|
+
contextTelemetry,
|
|
3807
|
+
"prior-task-summaries",
|
|
3808
|
+
finalCarryForwardSection.trim() ? "excerpt" : "skipped",
|
|
3809
|
+
finalCarryForwardSection,
|
|
3810
|
+
finalCarryForwardSection.length < carryForwardSection.length ? `truncated from ${carryForwardSection.length} chars for ${tid}` : tid,
|
|
3811
|
+
);
|
|
3812
|
+
const taskSummaryPath = `${relSlicePath(base, mid, sid)}/tasks/${tid}-SUMMARY.md`;
|
|
3813
|
+
const taskPrompt = [
|
|
3814
|
+
`## UNIT: Execute Task ${tid} ("${tTitle}")`,
|
|
3815
|
+
"",
|
|
3816
|
+
"Work only in the repository root.",
|
|
3817
|
+
"Implement from the inlined task plan below. Verify changes, then call `gsd_task_complete`.",
|
|
3818
|
+
"Do not run git commands.",
|
|
3819
|
+
"",
|
|
3820
|
+
finalCarryForwardSection,
|
|
3821
|
+
"",
|
|
3822
|
+
taskPlanInline,
|
|
3823
|
+
"",
|
|
3824
|
+
"## Completion Contract",
|
|
3825
|
+
`- Call \`gsd_task_complete\` with camelCase fields: \`milestoneId\`, \`sliceId\`, \`taskId\`, \`oneLiner\`, \`narrative\`, \`verification\`, and \`verificationEvidence\`.`,
|
|
3826
|
+
`- Do not manually write \`${taskSummaryPath}\` or edit PLAN checkboxes; the completion tool is canonical.`,
|
|
3827
|
+
`- Use \`blocker_discovered: true\` only if the task cannot be completed due to a real blocker.`,
|
|
3828
|
+
"",
|
|
3829
|
+
`When done, say: "Task ${tid} complete."`,
|
|
3830
|
+
].join("\n");
|
|
3831
|
+
|
|
3832
|
+
const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
|
|
3833
|
+
subagentSections.push([
|
|
3834
|
+
`### ${tid}: ${tTitle}`,
|
|
3835
|
+
"",
|
|
3836
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix}:`,
|
|
3837
|
+
"",
|
|
3838
|
+
"```",
|
|
3839
|
+
taskPrompt,
|
|
3840
|
+
"```",
|
|
3841
|
+
].join("\n"));
|
|
3842
|
+
}
|
|
3843
|
+
|
|
3844
|
+
const inlinedTemplates = inlineTemplate("task-summary", "Task Summary");
|
|
3845
|
+
trackPromptContext(contextTelemetry, "templates", "inline", inlinedTemplates);
|
|
3846
|
+
|
|
3847
|
+
const prompt = loadPrompt("reactive-execute", {
|
|
3848
|
+
workingDirectory: base,
|
|
3849
|
+
milestoneId: mid,
|
|
3850
|
+
milestoneTitle: midTitle,
|
|
3851
|
+
sliceId: sid,
|
|
3852
|
+
sliceTitle: sTitle,
|
|
3853
|
+
graphContext: prependContextModeToBlock("reactive-execute", base, graphContext),
|
|
3854
|
+
readyTaskCount: String(readyTaskIds.length),
|
|
3855
|
+
readyTaskList: readyTaskListLines.join("\n"),
|
|
3856
|
+
subagentPrompts: subagentSections.join("\n\n---\n\n"),
|
|
3857
|
+
inlinedTemplates,
|
|
3858
|
+
});
|
|
3859
|
+
emitPromptContextTelemetry("reactive-execute", contextTelemetry, prompt);
|
|
3860
|
+
return prompt;
|
|
3861
|
+
}
|
|
3862
|
+
|
|
3863
|
+
// ─── Gate Evaluation ──────────────────────────────────────────────────────
|
|
3864
|
+
//
|
|
3865
|
+
// Gate definitions (question, guidance, owner turn) now live in
|
|
3866
|
+
// gate-registry.ts so that prompt builders, dispatch rules, state
|
|
3867
|
+
// derivation, and tool handlers all consult the same source of truth.
|
|
3868
|
+
// See gate-registry.ts for the full ownership map.
|
|
3869
|
+
|
|
3870
|
+
/**
|
|
3871
|
+
* Render a "Gates to Close" block for turns like `complete-slice` and
|
|
3872
|
+
* `validate-milestone` that own gates which are closed as a side-effect
|
|
3873
|
+
* of writing artifact sections (not via a dedicated gate-evaluate
|
|
3874
|
+
* subagent loop).
|
|
3875
|
+
*
|
|
3876
|
+
* Returns a plain-text block or an empty string if there are no gates to
|
|
3877
|
+
* close, so callers can drop it straight into a template variable.
|
|
3878
|
+
*/
|
|
3879
|
+
function renderGatesToCloseBlock(
|
|
3880
|
+
gates: ReadonlyArray<GateDefinition>,
|
|
3881
|
+
opts: { pending: ReadonlySet<string>; allowOmit: boolean },
|
|
3882
|
+
): string {
|
|
3883
|
+
const applicable = gates.filter((g) => opts.pending.has(g.id));
|
|
3884
|
+
if (applicable.length === 0) return "";
|
|
3885
|
+
|
|
3886
|
+
const lines: string[] = [];
|
|
3887
|
+
lines.push("## Gates to Close");
|
|
3888
|
+
lines.push("");
|
|
3889
|
+
lines.push(
|
|
3890
|
+
"These quality gates are still pending for this unit. You MUST address every one before calling the closing tool — the handler closes the DB row based on whether the corresponding artifact section is present.",
|
|
3891
|
+
);
|
|
3892
|
+
lines.push("");
|
|
3893
|
+
for (const def of applicable) {
|
|
3894
|
+
lines.push(`### ${def.id} — ${def.promptSection}`);
|
|
3895
|
+
lines.push("");
|
|
3896
|
+
lines.push(`**Question:** ${def.question}`);
|
|
3897
|
+
lines.push("");
|
|
3898
|
+
lines.push(def.guidance);
|
|
3899
|
+
if (opts.allowOmit) {
|
|
3900
|
+
lines.push("");
|
|
3901
|
+
lines.push(
|
|
3902
|
+
`If this gate genuinely does not apply to this unit, leave the **${def.promptSection}** section empty and the handler will record it as \`omitted\`. Otherwise, fill the section with concrete evidence.`,
|
|
3903
|
+
);
|
|
3904
|
+
}
|
|
3905
|
+
lines.push("");
|
|
3906
|
+
}
|
|
3907
|
+
return lines.join("\n").trimEnd();
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
export async function buildParallelResearchSlicesPrompt(
|
|
3911
|
+
mid: string,
|
|
3912
|
+
midTitle: string,
|
|
3913
|
+
slices: Array<{ id: string; title: string }>,
|
|
3914
|
+
basePath: string,
|
|
3915
|
+
subagentModel?: string,
|
|
3916
|
+
): Promise<string> {
|
|
3917
|
+
// Build individual research-slice prompts for each slice
|
|
3918
|
+
const subagentSections: string[] = [];
|
|
3919
|
+
const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
|
|
3920
|
+
for (const slice of slices) {
|
|
3921
|
+
const slicePrompt = await buildResearchSlicePrompt(mid, midTitle, slice.id, slice.title, basePath, { contextModeRenderMode: "nested" });
|
|
3922
|
+
subagentSections.push([
|
|
3923
|
+
`### ${slice.id}: ${slice.title}`,
|
|
3924
|
+
"",
|
|
3925
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`scout\`):`,
|
|
3926
|
+
"",
|
|
3927
|
+
"```",
|
|
3928
|
+
slicePrompt,
|
|
3929
|
+
"```",
|
|
3930
|
+
].join("\n"));
|
|
3931
|
+
}
|
|
3932
|
+
|
|
3933
|
+
return loadPrompt("parallel-research-slices", {
|
|
3934
|
+
workingDirectory: basePath,
|
|
3935
|
+
mid,
|
|
3936
|
+
midTitle,
|
|
3937
|
+
sliceCount: String(slices.length),
|
|
3938
|
+
sliceList: slices.map((s) => `- **${s.id}**: ${s.title}`).join("\n"),
|
|
3939
|
+
subagentPrompts: subagentSections.join("\n\n---\n\n"),
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
|
|
3943
|
+
export async function buildGateEvaluatePrompt(
|
|
3944
|
+
mid: string, midTitle: string, sid: string, sTitle: string,
|
|
3945
|
+
base: string,
|
|
3946
|
+
subagentModel?: string,
|
|
3947
|
+
): Promise<string> {
|
|
3948
|
+
// Pull only the gates this turn actually owns (Q3/Q4). Filter via the
|
|
3949
|
+
// registry so that scope:"slice" gates owned by other turns (Q8) can't
|
|
3950
|
+
// leak into this prompt and can't block dispatch via silent skip.
|
|
3951
|
+
const pending = getPendingGatesForTurn(mid, sid, "gate-evaluate");
|
|
3952
|
+
|
|
3953
|
+
// Fails loudly if the pending list contains a gate id the registry
|
|
3954
|
+
// doesn't own for this turn. Missing owned gates is allowed here —
|
|
3955
|
+
// `gate-evaluate` is dispatched whenever *any* of its owned gates are
|
|
3956
|
+
// pending, not only when all of them are.
|
|
3957
|
+
assertGateCoverage(pending, "gate-evaluate", { requireAll: false });
|
|
3958
|
+
|
|
3959
|
+
// Load the slice plan for context
|
|
3960
|
+
const planFile = resolveSliceFile(base, mid, sid, "PLAN");
|
|
3961
|
+
const planContent = planFile ? (await loadFile(planFile)) ?? "(plan file empty)" : "(plan file not found)";
|
|
3962
|
+
|
|
3963
|
+
// Build per-gate subagent prompts from the pending rows. Because the
|
|
3964
|
+
// registry has already validated every row, `getGateDefinition` cannot
|
|
3965
|
+
// return undefined here.
|
|
3966
|
+
const pendingIds = new Set(pending.map((g) => g.gate_id));
|
|
3967
|
+
const gateDefs = getGatesForTurn("gate-evaluate").filter((def) => pendingIds.has(def.id));
|
|
3968
|
+
|
|
3969
|
+
const subagentSections: string[] = [];
|
|
3970
|
+
const gateListLines: string[] = [];
|
|
3971
|
+
const normalizedBase = base.replaceAll("\\", "/");
|
|
3972
|
+
|
|
3973
|
+
for (const def of gateDefs) {
|
|
3974
|
+
gateListLines.push(`- **${def.id}**: ${def.question}`);
|
|
3975
|
+
|
|
3976
|
+
const subPrompt = [
|
|
3977
|
+
renderContextModeForPrompt("gate-evaluate", base, "nested"),
|
|
3978
|
+
"",
|
|
3979
|
+
`You are evaluating quality gate **${def.id}** for slice ${sid} (${sTitle}).`,
|
|
3980
|
+
"",
|
|
3981
|
+
`**Working directory:** \`${normalizedBase}\`. All file reads, writes, and shell commands MUST operate relative to this directory. Do NOT \`cd\` to any other directory.`,
|
|
3982
|
+
"",
|
|
3983
|
+
`## Question: ${def.question}`,
|
|
3984
|
+
"",
|
|
3985
|
+
def.guidance,
|
|
3986
|
+
"",
|
|
3987
|
+
"## Slice Plan",
|
|
3988
|
+
"",
|
|
3989
|
+
planContent,
|
|
3990
|
+
"",
|
|
3991
|
+
"## Instructions",
|
|
3992
|
+
"",
|
|
3993
|
+
"Analyze the slice plan above and answer the gate question.",
|
|
3994
|
+
`Call the \`gsd_save_gate_result\` tool with:`,
|
|
3995
|
+
`- \`milestoneId\`: "${mid}"`,
|
|
3996
|
+
`- \`sliceId\`: "${sid}"`,
|
|
3997
|
+
`- \`gateId\`: "${def.id}"`,
|
|
3998
|
+
"- `verdict`: \"pass\" (no concerns), \"flag\" (concerns found), or \"omitted\" (not applicable)",
|
|
3999
|
+
"- `rationale`: one-sentence justification",
|
|
4000
|
+
"- `findings`: detailed markdown findings (or empty if omitted)",
|
|
4001
|
+
].join("\n");
|
|
4002
|
+
|
|
4003
|
+
const modelSuffix = subagentModel ? ` with model: "${subagentModel}"` : "";
|
|
4004
|
+
subagentSections.push([
|
|
4005
|
+
`### ${def.id}: ${def.question}`,
|
|
4006
|
+
"",
|
|
4007
|
+
`Use this as the prompt for a \`subagent\` call${modelSuffix} (agent: \`tester\`):`,
|
|
4008
|
+
"",
|
|
4009
|
+
"```",
|
|
4010
|
+
subPrompt,
|
|
4011
|
+
"```",
|
|
4012
|
+
].join("\n"));
|
|
4013
|
+
}
|
|
4014
|
+
|
|
4015
|
+
return loadPrompt("gate-evaluate", {
|
|
4016
|
+
workingDirectory: base,
|
|
4017
|
+
milestoneId: mid,
|
|
4018
|
+
milestoneTitle: midTitle,
|
|
4019
|
+
sliceId: sid,
|
|
4020
|
+
sliceTitle: sTitle,
|
|
4021
|
+
slicePlanContent: prependContextModeToBlock("gate-evaluate", base, planContent),
|
|
4022
|
+
gateCount: String(pending.length),
|
|
4023
|
+
gateList: gateListLines.join("\n"),
|
|
4024
|
+
subagentPrompts: subagentSections.join("\n\n---\n\n"),
|
|
4025
|
+
});
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
export async function buildRewriteDocsPrompt(
|
|
4029
|
+
mid: string, midTitle: string,
|
|
4030
|
+
activeSlice: { id: string; title: string } | null,
|
|
4031
|
+
base: string,
|
|
4032
|
+
overrides: Override[],
|
|
4033
|
+
): Promise<string> {
|
|
4034
|
+
const sid = activeSlice?.id;
|
|
4035
|
+
const sTitle = activeSlice?.title ?? "";
|
|
4036
|
+
const docList: string[] = [];
|
|
4037
|
+
|
|
4038
|
+
if (sid) {
|
|
4039
|
+
const slicePlanPath = resolveSliceFile(base, mid, sid, "PLAN");
|
|
4040
|
+
const slicePlanRel = relSliceFile(base, mid, sid, "PLAN");
|
|
4041
|
+
if (slicePlanPath) {
|
|
4042
|
+
docList.push(`- Slice plan: \`${slicePlanRel}\``);
|
|
4043
|
+
const tDir = resolveTasksDir(base, mid, sid);
|
|
4044
|
+
if (tDir) {
|
|
4045
|
+
// DB primary path — get incomplete tasks
|
|
4046
|
+
let incompleteTasks: { id: string }[] | null = null;
|
|
4047
|
+
try {
|
|
4048
|
+
const { isDbAvailable, getSliceTasks } = await import("./gsd-db.js");
|
|
4049
|
+
if (isDbAvailable()) {
|
|
4050
|
+
incompleteTasks = getSliceTasks(mid, sid)
|
|
4051
|
+
.filter(t => t.status !== "complete" && t.status !== "done")
|
|
4052
|
+
.map(t => ({ id: t.id }));
|
|
4053
|
+
}
|
|
4054
|
+
} catch (err) {
|
|
4055
|
+
logWarning("prompt", `buildRewriteDocsPrompt DB task lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4056
|
+
}
|
|
4057
|
+
|
|
4058
|
+
if (!incompleteTasks) {
|
|
4059
|
+
// DB unavailable — no task data to inline
|
|
4060
|
+
incompleteTasks = [];
|
|
4061
|
+
}
|
|
4062
|
+
|
|
4063
|
+
if (incompleteTasks) {
|
|
4064
|
+
for (const task of incompleteTasks) {
|
|
4065
|
+
const taskPlanPath = resolveTaskFile(base, mid, sid, task.id, "PLAN");
|
|
4066
|
+
if (taskPlanPath) {
|
|
4067
|
+
const taskRelPath = `${relSlicePath(base, mid, sid)}/tasks/${task.id}-PLAN.md`;
|
|
4068
|
+
docList.push(`- Task plan: \`${taskRelPath}\``);
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4076
|
+
const decisionsPath = resolveGsdRootFile(base, "DECISIONS");
|
|
4077
|
+
if (existsSync(decisionsPath)) docList.push(`- Decisions: \`${relGsdRootFile("DECISIONS")}\``);
|
|
4078
|
+
const requirementsPath = resolveGsdRootFile(base, "REQUIREMENTS");
|
|
4079
|
+
if (existsSync(requirementsPath)) docList.push(`- Requirements: \`${relGsdRootFile("REQUIREMENTS")}\``);
|
|
4080
|
+
const projectPath = resolveGsdRootFile(base, "PROJECT");
|
|
4081
|
+
if (existsSync(projectPath)) docList.push(`- Project: \`${relGsdRootFile("PROJECT")}\``);
|
|
4082
|
+
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
4083
|
+
const contextRel = relMilestoneFile(base, mid, "CONTEXT");
|
|
4084
|
+
if (contextPath) docList.push(`- Milestone context (reference only): \`${contextRel}\``);
|
|
4085
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
4086
|
+
const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
|
|
4087
|
+
if (roadmapPath) docList.push(`- Roadmap: \`${roadmapRel}\``);
|
|
4088
|
+
|
|
4089
|
+
const overrideContent = overrides.map((o, i) => [
|
|
4090
|
+
`### Override ${i + 1}`,
|
|
4091
|
+
`**Change:** ${o.change}`,
|
|
4092
|
+
`**Issued:** ${o.timestamp}`,
|
|
4093
|
+
`**During:** ${o.appliedAt}`,
|
|
4094
|
+
].join("\n")).join("\n\n");
|
|
4095
|
+
|
|
4096
|
+
const documentList = docList.length > 0 ? docList.join("\n") : "- No active plan documents found.";
|
|
4097
|
+
|
|
4098
|
+
return prependContextModeToBlock("rewrite-docs", base, loadPrompt("rewrite-docs", {
|
|
4099
|
+
workingDirectory: base,
|
|
4100
|
+
milestoneId: mid,
|
|
4101
|
+
milestoneTitle: midTitle,
|
|
4102
|
+
sliceId: sid ?? "none",
|
|
4103
|
+
sliceTitle: sTitle,
|
|
4104
|
+
overrideContent,
|
|
4105
|
+
documentList,
|
|
4106
|
+
overridesPath: relGsdRootFile("OVERRIDES"),
|
|
4107
|
+
}));
|
|
4108
|
+
}
|