@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.
Files changed (2880) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/package.json +171 -0
  4. package/packages/contracts/dist/index.d.ts +3 -0
  5. package/packages/contracts/dist/index.d.ts.map +1 -0
  6. package/packages/contracts/dist/index.js +5 -0
  7. package/packages/contracts/dist/index.js.map +1 -0
  8. package/packages/contracts/dist/rpc.d.ts +549 -0
  9. package/packages/contracts/dist/rpc.d.ts.map +1 -0
  10. package/packages/contracts/dist/rpc.js +53 -0
  11. package/packages/contracts/dist/rpc.js.map +1 -0
  12. package/packages/contracts/dist/rpc.test.d.ts +2 -0
  13. package/packages/contracts/dist/rpc.test.d.ts.map +1 -0
  14. package/packages/contracts/dist/rpc.test.js +54 -0
  15. package/packages/contracts/dist/rpc.test.js.map +1 -0
  16. package/packages/contracts/dist/workflow.d.ts +201 -0
  17. package/packages/contracts/dist/workflow.d.ts.map +1 -0
  18. package/packages/contracts/dist/workflow.js +225 -0
  19. package/packages/contracts/dist/workflow.js.map +1 -0
  20. package/packages/contracts/package.json +39 -0
  21. package/packages/contracts/src/index.ts +5 -0
  22. package/packages/contracts/src/rpc.test.ts +80 -0
  23. package/packages/contracts/src/rpc.ts +286 -0
  24. package/packages/contracts/src/workflow.ts +237 -0
  25. package/packages/contracts/tsconfig.json +25 -0
  26. package/packages/daemon/package.json +49 -0
  27. package/packages/daemon/src/channel-manager.ts +223 -0
  28. package/packages/daemon/src/cli.ts +96 -0
  29. package/packages/daemon/src/commands.ts +110 -0
  30. package/packages/daemon/src/config.ts +137 -0
  31. package/packages/daemon/src/daemon.test.ts +763 -0
  32. package/packages/daemon/src/daemon.ts +199 -0
  33. package/packages/daemon/src/discord-bot.test.ts +792 -0
  34. package/packages/daemon/src/discord-bot.ts +491 -0
  35. package/packages/daemon/src/event-bridge.test.ts +620 -0
  36. package/packages/daemon/src/event-bridge.ts +494 -0
  37. package/packages/daemon/src/event-formatter.test.ts +401 -0
  38. package/packages/daemon/src/event-formatter.ts +413 -0
  39. package/packages/daemon/src/index.ts +55 -0
  40. package/packages/daemon/src/launchd.test.ts +356 -0
  41. package/packages/daemon/src/launchd.ts +242 -0
  42. package/packages/daemon/src/logger.ts +89 -0
  43. package/packages/daemon/src/message-batcher.test.ts +308 -0
  44. package/packages/daemon/src/message-batcher.ts +216 -0
  45. package/packages/daemon/src/orchestrator.test.ts +584 -0
  46. package/packages/daemon/src/orchestrator.ts +469 -0
  47. package/packages/daemon/src/project-scanner.test.ts +235 -0
  48. package/packages/daemon/src/project-scanner.ts +99 -0
  49. package/packages/daemon/src/session-manager.test.ts +822 -0
  50. package/packages/daemon/src/session-manager.ts +400 -0
  51. package/packages/daemon/src/types.ts +184 -0
  52. package/packages/daemon/src/verbosity.test.ts +171 -0
  53. package/packages/daemon/src/verbosity.ts +101 -0
  54. package/packages/daemon/tsconfig.json +24 -0
  55. package/packages/mcp-server/README.md +275 -0
  56. package/packages/mcp-server/package.json +53 -0
  57. package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
  58. package/packages/mcp-server/src/alias-telemetry.ts +30 -0
  59. package/packages/mcp-server/src/cli.ts +70 -0
  60. package/packages/mcp-server/src/env-writer.test.ts +433 -0
  61. package/packages/mcp-server/src/env-writer.ts +292 -0
  62. package/packages/mcp-server/src/import-candidates.test.ts +53 -0
  63. package/packages/mcp-server/src/index.ts +43 -0
  64. package/packages/mcp-server/src/mcp-server.test.ts +1395 -0
  65. package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
  66. package/packages/mcp-server/src/readers/captures.ts +119 -0
  67. package/packages/mcp-server/src/readers/doctor-lite.ts +225 -0
  68. package/packages/mcp-server/src/readers/graph.test.ts +679 -0
  69. package/packages/mcp-server/src/readers/graph.ts +863 -0
  70. package/packages/mcp-server/src/readers/index.ts +28 -0
  71. package/packages/mcp-server/src/readers/knowledge.ts +111 -0
  72. package/packages/mcp-server/src/readers/metrics.ts +118 -0
  73. package/packages/mcp-server/src/readers/paths.test.ts +67 -0
  74. package/packages/mcp-server/src/readers/paths.ts +334 -0
  75. package/packages/mcp-server/src/readers/readers.test.ts +513 -0
  76. package/packages/mcp-server/src/readers/roadmap.ts +263 -0
  77. package/packages/mcp-server/src/readers/state.ts +223 -0
  78. package/packages/mcp-server/src/remote-questions.test.ts +397 -0
  79. package/packages/mcp-server/src/remote-questions.ts +967 -0
  80. package/packages/mcp-server/src/secure-env-collect.test.ts +260 -0
  81. package/packages/mcp-server/src/server.ts +1342 -0
  82. package/packages/mcp-server/src/session-manager.ts +404 -0
  83. package/packages/mcp-server/src/tool-credentials.test.ts +95 -0
  84. package/packages/mcp-server/src/tool-credentials.ts +97 -0
  85. package/packages/mcp-server/src/types.ts +96 -0
  86. package/packages/mcp-server/src/workflow-tools-parity.test.ts +257 -0
  87. package/packages/mcp-server/src/workflow-tools.test.ts +2350 -0
  88. package/packages/mcp-server/src/workflow-tools.ts +2257 -0
  89. package/packages/mcp-server/tsconfig.json +25 -0
  90. package/packages/mcp-server/tsconfig.test.json +19 -0
  91. package/packages/native/dist/ast/index.d.ts +4 -0
  92. package/packages/native/dist/ast/index.js +11 -0
  93. package/packages/native/dist/ast/types.d.ts +69 -0
  94. package/packages/native/dist/ast/types.js +2 -0
  95. package/packages/native/dist/clipboard/index.d.ts +28 -0
  96. package/packages/native/dist/clipboard/index.js +38 -0
  97. package/packages/native/dist/clipboard/types.d.ts +7 -0
  98. package/packages/native/dist/clipboard/types.js +2 -0
  99. package/packages/native/dist/diff/index.d.ts +33 -0
  100. package/packages/native/dist/diff/index.js +43 -0
  101. package/packages/native/dist/diff/types.d.ts +23 -0
  102. package/packages/native/dist/diff/types.js +2 -0
  103. package/packages/native/dist/fd/index.d.ts +26 -0
  104. package/packages/native/dist/fd/index.js +30 -0
  105. package/packages/native/dist/fd/types.d.ts +29 -0
  106. package/packages/native/dist/fd/types.js +2 -0
  107. package/packages/native/dist/glob/index.d.ts +28 -0
  108. package/packages/native/dist/glob/index.js +35 -0
  109. package/packages/native/dist/glob/types.d.ts +50 -0
  110. package/packages/native/dist/glob/types.js +2 -0
  111. package/packages/native/dist/grep/index.d.ts +21 -0
  112. package/packages/native/dist/grep/index.js +28 -0
  113. package/packages/native/dist/grep/types.d.ts +99 -0
  114. package/packages/native/dist/grep/types.js +2 -0
  115. package/packages/native/dist/gsd-parser/index.d.ts +45 -0
  116. package/packages/native/dist/gsd-parser/index.js +61 -0
  117. package/packages/native/dist/gsd-parser/types.d.ts +55 -0
  118. package/packages/native/dist/gsd-parser/types.js +8 -0
  119. package/packages/native/dist/highlight/index.d.ts +28 -0
  120. package/packages/native/dist/highlight/index.js +38 -0
  121. package/packages/native/dist/highlight/types.d.ts +25 -0
  122. package/packages/native/dist/highlight/types.js +2 -0
  123. package/packages/native/dist/html/index.d.ts +15 -0
  124. package/packages/native/dist/html/index.js +19 -0
  125. package/packages/native/dist/html/types.d.ts +7 -0
  126. package/packages/native/dist/html/types.js +2 -0
  127. package/packages/native/dist/image/index.d.ts +15 -0
  128. package/packages/native/dist/image/index.js +23 -0
  129. package/packages/native/dist/image/types.d.ts +35 -0
  130. package/packages/native/dist/image/types.js +29 -0
  131. package/packages/native/dist/index.d.ts +46 -0
  132. package/packages/native/dist/index.js +85 -0
  133. package/packages/native/dist/json-parse/index.d.ts +23 -0
  134. package/packages/native/dist/json-parse/index.js +78 -0
  135. package/packages/native/dist/native.d.ts +57 -0
  136. package/packages/native/dist/native.js +113 -0
  137. package/packages/native/dist/ps/index.d.ts +38 -0
  138. package/packages/native/dist/ps/index.js +53 -0
  139. package/packages/native/dist/stream-process/index.d.ts +35 -0
  140. package/packages/native/dist/stream-process/index.js +254 -0
  141. package/packages/native/dist/text/index.d.ts +55 -0
  142. package/packages/native/dist/text/index.js +76 -0
  143. package/packages/native/dist/text/types.d.ts +27 -0
  144. package/packages/native/dist/text/types.js +13 -0
  145. package/packages/native/dist/truncate/index.d.ts +29 -0
  146. package/packages/native/dist/truncate/index.js +30 -0
  147. package/packages/native/dist/ttsr/index.d.ts +27 -0
  148. package/packages/native/dist/ttsr/index.js +37 -0
  149. package/packages/native/dist/ttsr/types.d.ts +9 -0
  150. package/packages/native/dist/ttsr/types.js +2 -0
  151. package/packages/native/dist/xxhash/index.d.ts +22 -0
  152. package/packages/native/dist/xxhash/index.js +89 -0
  153. package/packages/native/package.json +97 -0
  154. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  155. package/packages/native/src/__tests__/clipboard.test.mjs +126 -0
  156. package/packages/native/src/__tests__/diff.test.mjs +189 -0
  157. package/packages/native/src/__tests__/fd.test.mjs +199 -0
  158. package/packages/native/src/__tests__/glob.test.mjs +237 -0
  159. package/packages/native/src/__tests__/grep.test.mjs +179 -0
  160. package/packages/native/src/__tests__/highlight.test.mjs +156 -0
  161. package/packages/native/src/__tests__/html.test.mjs +98 -0
  162. package/packages/native/src/__tests__/image.test.mjs +137 -0
  163. package/packages/native/src/__tests__/json-parse.test.mjs +158 -0
  164. package/packages/native/src/__tests__/module-compat.test.mjs +123 -0
  165. package/packages/native/src/__tests__/ps.test.mjs +115 -0
  166. package/packages/native/src/__tests__/stream-process.test.mjs +108 -0
  167. package/packages/native/src/__tests__/text.test.mjs +295 -0
  168. package/packages/native/src/__tests__/truncate.test.mjs +160 -0
  169. package/packages/native/src/__tests__/ttsr.test.mjs +135 -0
  170. package/packages/native/src/__tests__/xxhash.test.mjs +122 -0
  171. package/packages/native/src/ast/index.ts +12 -0
  172. package/packages/native/src/ast/types.ts +75 -0
  173. package/packages/native/src/clipboard/index.ts +40 -0
  174. package/packages/native/src/clipboard/types.ts +7 -0
  175. package/packages/native/src/diff/index.ts +61 -0
  176. package/packages/native/src/diff/types.ts +24 -0
  177. package/packages/native/src/fd/index.ts +36 -0
  178. package/packages/native/src/fd/types.ts +31 -0
  179. package/packages/native/src/glob/index.ts +44 -0
  180. package/packages/native/src/glob/types.ts +53 -0
  181. package/packages/native/src/grep/index.ts +49 -0
  182. package/packages/native/src/grep/types.ts +105 -0
  183. package/packages/native/src/gsd-parser/index.ts +98 -0
  184. package/packages/native/src/gsd-parser/types.ts +62 -0
  185. package/packages/native/src/highlight/index.ts +44 -0
  186. package/packages/native/src/highlight/types.ts +25 -0
  187. package/packages/native/src/html/index.ts +24 -0
  188. package/packages/native/src/html/types.ts +7 -0
  189. package/packages/native/src/image/index.ts +28 -0
  190. package/packages/native/src/image/types.ts +41 -0
  191. package/packages/native/src/index.ts +128 -0
  192. package/packages/native/src/json-parse/index.ts +76 -0
  193. package/packages/native/src/native.ts +154 -0
  194. package/packages/native/src/ps/index.ts +52 -0
  195. package/packages/native/src/stream-process/index.ts +313 -0
  196. package/packages/native/src/text/index.ts +125 -0
  197. package/packages/native/src/text/types.ts +29 -0
  198. package/packages/native/src/truncate/index.ts +50 -0
  199. package/packages/native/src/ttsr/index.ts +39 -0
  200. package/packages/native/src/ttsr/types.ts +10 -0
  201. package/packages/native/src/xxhash/index.ts +98 -0
  202. package/packages/native/tsconfig.json +9 -0
  203. package/packages/native/tsconfig.tsbuildinfo +1 -0
  204. package/packages/pi-agent-core/package.json +23 -0
  205. package/packages/pi-agent-core/src/agent-loop.test.ts +733 -0
  206. package/packages/pi-agent-core/src/agent-loop.ts +851 -0
  207. package/packages/pi-agent-core/src/agent.test.ts +129 -0
  208. package/packages/pi-agent-core/src/agent.ts +668 -0
  209. package/packages/pi-agent-core/src/index.ts +10 -0
  210. package/packages/pi-agent-core/src/proxy.ts +334 -0
  211. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  212. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  213. package/packages/pi-agent-core/src/types.ts +358 -0
  214. package/packages/pi-agent-core/tsconfig.json +28 -0
  215. package/packages/pi-ai/bedrock-provider.d.ts +1 -0
  216. package/packages/pi-ai/bedrock-provider.js +1 -0
  217. package/packages/pi-ai/package.json +48 -0
  218. package/packages/pi-ai/scripts/generate-models.ts +1671 -0
  219. package/packages/pi-ai/src/api-registry.ts +86 -0
  220. package/packages/pi-ai/src/bedrock-provider.ts +6 -0
  221. package/packages/pi-ai/src/cli.ts +133 -0
  222. package/packages/pi-ai/src/env-api-keys.ts +148 -0
  223. package/packages/pi-ai/src/index.ts +36 -0
  224. package/packages/pi-ai/src/models/capability-patches.ts +51 -0
  225. package/packages/pi-ai/src/models/custom.ts +337 -0
  226. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  227. package/packages/pi-ai/src/models/generated/amazon-bedrock.ts +1554 -0
  228. package/packages/pi-ai/src/models/generated/anthropic.ts +398 -0
  229. package/packages/pi-ai/src/models/generated/azure-openai-responses.ts +704 -0
  230. package/packages/pi-ai/src/models/generated/cerebras.ts +75 -0
  231. package/packages/pi-ai/src/models/generated/github-copilot.ts +446 -0
  232. package/packages/pi-ai/src/models/generated/google-antigravity.ts +177 -0
  233. package/packages/pi-ai/src/models/generated/google-gemini-cli.ts +109 -0
  234. package/packages/pi-ai/src/models/generated/google-vertex.ts +211 -0
  235. package/packages/pi-ai/src/models/generated/google.ts +466 -0
  236. package/packages/pi-ai/src/models/generated/groq.ts +160 -0
  237. package/packages/pi-ai/src/models/generated/huggingface.ts +349 -0
  238. package/packages/pi-ai/src/models/generated/index.ts +52 -0
  239. package/packages/pi-ai/src/models/generated/kimi-coding.ts +41 -0
  240. package/packages/pi-ai/src/models/generated/minimax-cn.ts +109 -0
  241. package/packages/pi-ai/src/models/generated/minimax.ts +109 -0
  242. package/packages/pi-ai/src/models/generated/mistral.ts +449 -0
  243. package/packages/pi-ai/src/models/generated/openai-codex.ts +177 -0
  244. package/packages/pi-ai/src/models/generated/openai.ts +721 -0
  245. package/packages/pi-ai/src/models/generated/opencode-go.ts +126 -0
  246. package/packages/pi-ai/src/models/generated/opencode.ts +534 -0
  247. package/packages/pi-ai/src/models/generated/openrouter.ts +4291 -0
  248. package/packages/pi-ai/src/models/generated/vercel-ai-gateway.ts +2608 -0
  249. package/packages/pi-ai/src/models/generated/xai.ts +415 -0
  250. package/packages/pi-ai/src/models/generated/zai.ts +241 -0
  251. package/packages/pi-ai/src/models/index.ts +115 -0
  252. package/packages/pi-ai/src/models.generated.test.ts +362 -0
  253. package/packages/pi-ai/src/models.test.ts +404 -0
  254. package/packages/pi-ai/src/models.ts +3 -0
  255. package/packages/pi-ai/src/oauth.ts +1 -0
  256. package/packages/pi-ai/src/providers/amazon-bedrock.test.ts +164 -0
  257. package/packages/pi-ai/src/providers/amazon-bedrock.ts +797 -0
  258. package/packages/pi-ai/src/providers/anthropic-auth.test.ts +92 -0
  259. package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +36 -0
  260. package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
  261. package/packages/pi-ai/src/providers/anthropic-shared.test.ts +134 -0
  262. package/packages/pi-ai/src/providers/anthropic-shared.ts +899 -0
  263. package/packages/pi-ai/src/providers/anthropic-vertex.ts +130 -0
  264. package/packages/pi-ai/src/providers/anthropic.ts +240 -0
  265. package/packages/pi-ai/src/providers/api-family.test.ts +129 -0
  266. package/packages/pi-ai/src/providers/api-family.ts +57 -0
  267. package/packages/pi-ai/src/providers/azure-openai-responses.ts +248 -0
  268. package/packages/pi-ai/src/providers/fake.ts +376 -0
  269. package/packages/pi-ai/src/providers/github-copilot-headers.ts +37 -0
  270. package/packages/pi-ai/src/providers/google-gemini-cli.test.ts +90 -0
  271. package/packages/pi-ai/src/providers/google-gemini-cli.ts +982 -0
  272. package/packages/pi-ai/src/providers/google-shared.test.ts +137 -0
  273. package/packages/pi-ai/src/providers/google-shared.ts +364 -0
  274. package/packages/pi-ai/src/providers/google-vertex.ts +500 -0
  275. package/packages/pi-ai/src/providers/google.ts +467 -0
  276. package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +118 -0
  277. package/packages/pi-ai/src/providers/mistral.ts +597 -0
  278. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  279. package/packages/pi-ai/src/providers/openai-codex-responses.ts +1007 -0
  280. package/packages/pi-ai/src/providers/openai-completions.test.ts +75 -0
  281. package/packages/pi-ai/src/providers/openai-completions.ts +830 -0
  282. package/packages/pi-ai/src/providers/openai-responses-shared.ts +496 -0
  283. package/packages/pi-ai/src/providers/openai-responses.ts +205 -0
  284. package/packages/pi-ai/src/providers/openai-shared.ts +193 -0
  285. package/packages/pi-ai/src/providers/provider-capabilities.test.ts +174 -0
  286. package/packages/pi-ai/src/providers/provider-capabilities.ts +215 -0
  287. package/packages/pi-ai/src/providers/register-builtins.ts +216 -0
  288. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  289. package/packages/pi-ai/src/providers/simple-options.ts +61 -0
  290. package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
  291. package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
  292. package/packages/pi-ai/src/providers/transform-messages-report.test.ts +189 -0
  293. package/packages/pi-ai/src/providers/transform-messages.ts +289 -0
  294. package/packages/pi-ai/src/stream.ts +59 -0
  295. package/packages/pi-ai/src/types.ts +413 -0
  296. package/packages/pi-ai/src/utils/event-stream.ts +87 -0
  297. package/packages/pi-ai/src/utils/hash.ts +13 -0
  298. package/packages/pi-ai/src/utils/json-parse.ts +51 -0
  299. package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +282 -0
  300. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +470 -0
  301. package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +80 -0
  302. package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +323 -0
  303. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +80 -0
  304. package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +468 -0
  305. package/packages/pi-ai/src/utils/oauth/google-oauth-utils.ts +201 -0
  306. package/packages/pi-ai/src/utils/oauth/index.ts +134 -0
  307. package/packages/pi-ai/src/utils/oauth/openai-codex.ts +472 -0
  308. package/packages/pi-ai/src/utils/oauth/pkce.ts +34 -0
  309. package/packages/pi-ai/src/utils/oauth/types.ts +49 -0
  310. package/packages/pi-ai/src/utils/overflow.ts +129 -0
  311. package/packages/pi-ai/src/utils/repair-tool-json.ts +241 -0
  312. package/packages/pi-ai/src/utils/sanitize-unicode.ts +25 -0
  313. package/packages/pi-ai/src/utils/tests/json-parse.test.ts +17 -0
  314. package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
  315. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +240 -0
  316. package/packages/pi-ai/src/utils/typebox-helpers.ts +24 -0
  317. package/packages/pi-ai/src/utils/validation.ts +69 -0
  318. package/packages/pi-ai/src/web-runtime-env-api-keys.ts +86 -0
  319. package/packages/pi-ai/src/web-runtime-oauth.ts +9 -0
  320. package/packages/pi-ai/tsconfig.json +28 -0
  321. package/packages/pi-coding-agent/package.json +52 -0
  322. package/packages/pi-coding-agent/scripts/copy-assets.cjs +55 -0
  323. package/packages/pi-coding-agent/src/cli/abort-signal-timeout.test.ts +73 -0
  324. package/packages/pi-coding-agent/src/cli/abort-signal-timeout.ts +18 -0
  325. package/packages/pi-coding-agent/src/cli/args.test.ts +44 -0
  326. package/packages/pi-coding-agent/src/cli/args.ts +357 -0
  327. package/packages/pi-coding-agent/src/cli/config-selector.ts +52 -0
  328. package/packages/pi-coding-agent/src/cli/file-processor.ts +96 -0
  329. package/packages/pi-coding-agent/src/cli/list-models.ts +164 -0
  330. package/packages/pi-coding-agent/src/cli/session-picker.ts +51 -0
  331. package/packages/pi-coding-agent/src/cli.ts +20 -0
  332. package/packages/pi-coding-agent/src/config.ts +245 -0
  333. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +491 -0
  334. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +93 -0
  335. package/packages/pi-coding-agent/src/core/agent-session-renderable-tools.test.ts +70 -0
  336. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  337. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +172 -0
  338. package/packages/pi-coding-agent/src/core/agent-session.ts +3150 -0
  339. package/packages/pi-coding-agent/src/core/artifact-manager.ts +125 -0
  340. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +654 -0
  341. package/packages/pi-coding-agent/src/core/auth-storage.ts +925 -0
  342. package/packages/pi-coding-agent/src/core/bash-executor.ts +316 -0
  343. package/packages/pi-coding-agent/src/core/blob-store.ts +154 -0
  344. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +1571 -0
  345. package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +307 -0
  346. package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +598 -0
  347. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +986 -0
  348. package/packages/pi-coding-agent/src/core/compaction/index.ts +7 -0
  349. package/packages/pi-coding-agent/src/core/compaction/utils.ts +368 -0
  350. package/packages/pi-coding-agent/src/core/compaction-orchestrator.test.ts +154 -0
  351. package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +440 -0
  352. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  353. package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +117 -0
  354. package/packages/pi-coding-agent/src/core/constants.ts +59 -0
  355. package/packages/pi-coding-agent/src/core/contextual-tips.test.ts +259 -0
  356. package/packages/pi-coding-agent/src/core/contextual-tips.ts +232 -0
  357. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  358. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  359. package/packages/pi-coding-agent/src/core/defaults.ts +3 -0
  360. package/packages/pi-coding-agent/src/core/diagnostics.ts +15 -0
  361. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +163 -0
  362. package/packages/pi-coding-agent/src/core/discovery-cache.ts +104 -0
  363. package/packages/pi-coding-agent/src/core/event-bus.ts +33 -0
  364. package/packages/pi-coding-agent/src/core/exec.ts +106 -0
  365. package/packages/pi-coding-agent/src/core/export-html/ansi-to-html.ts +258 -0
  366. package/packages/pi-coding-agent/src/core/export-html/index.ts +306 -0
  367. package/packages/pi-coding-agent/src/core/export-html/template.css +971 -0
  368. package/packages/pi-coding-agent/src/core/export-html/template.html +54 -0
  369. package/packages/pi-coding-agent/src/core/export-html/template.js +1583 -0
  370. package/packages/pi-coding-agent/src/core/export-html/tool-renderer.ts +114 -0
  371. package/packages/pi-coding-agent/src/core/export-html/vendor/highlight.min.js +1213 -0
  372. package/packages/pi-coding-agent/src/core/export-html/vendor/marked.min.js +6 -0
  373. package/packages/pi-coding-agent/src/core/extensions/extension-discovery.ts +119 -0
  374. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
  375. package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
  376. package/packages/pi-coding-agent/src/core/extensions/extension-registry.ts +222 -0
  377. package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
  378. package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
  379. package/packages/pi-coding-agent/src/core/extensions/index.ts +186 -0
  380. package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +275 -0
  381. package/packages/pi-coding-agent/src/core/extensions/loader.ts +1139 -0
  382. package/packages/pi-coding-agent/src/core/extensions/project-trust.ts +51 -0
  383. package/packages/pi-coding-agent/src/core/extensions/provider-registration.test.ts +81 -0
  384. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +282 -0
  385. package/packages/pi-coding-agent/src/core/extensions/runner.ts +1241 -0
  386. package/packages/pi-coding-agent/src/core/extensions/types.ts +1872 -0
  387. package/packages/pi-coding-agent/src/core/extensions/wrapper.ts +127 -0
  388. package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +242 -0
  389. package/packages/pi-coding-agent/src/core/fallback-resolver.ts +164 -0
  390. package/packages/pi-coding-agent/src/core/footer-data-provider.ts +144 -0
  391. package/packages/pi-coding-agent/src/core/fs-utils.test.ts +54 -0
  392. package/packages/pi-coding-agent/src/core/fs-utils.ts +12 -0
  393. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +271 -0
  394. package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
  395. package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
  396. package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
  397. package/packages/pi-coding-agent/src/core/index.ts +80 -0
  398. package/packages/pi-coding-agent/src/core/keybindings.ts +211 -0
  399. package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
  400. package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +280 -0
  401. package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
  402. package/packages/pi-coding-agent/src/core/lock-utils.ts +113 -0
  403. package/packages/pi-coding-agent/src/core/lsp/client.ts +968 -0
  404. package/packages/pi-coding-agent/src/core/lsp/config.ts +356 -0
  405. package/packages/pi-coding-agent/src/core/lsp/defaults.json +456 -0
  406. package/packages/pi-coding-agent/src/core/lsp/edits.ts +109 -0
  407. package/packages/pi-coding-agent/src/core/lsp/helpers.ts +54 -0
  408. package/packages/pi-coding-agent/src/core/lsp/index.ts +1065 -0
  409. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +451 -0
  410. package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +70 -0
  411. package/packages/pi-coding-agent/src/core/lsp/lsp.md +39 -0
  412. package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +190 -0
  413. package/packages/pi-coding-agent/src/core/lsp/types.ts +445 -0
  414. package/packages/pi-coding-agent/src/core/lsp/utils.ts +706 -0
  415. package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
  416. package/packages/pi-coding-agent/src/core/messages.ts +226 -0
  417. package/packages/pi-coding-agent/src/core/model-discovery.test.ts +144 -0
  418. package/packages/pi-coding-agent/src/core/model-discovery.ts +318 -0
  419. package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
  420. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +730 -0
  421. package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
  422. package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +210 -0
  423. package/packages/pi-coding-agent/src/core/model-registry-env-fallback.test.ts +59 -0
  424. package/packages/pi-coding-agent/src/core/model-registry.ts +1053 -0
  425. package/packages/pi-coding-agent/src/core/model-resolver-initial-model-auth.test.ts +78 -0
  426. package/packages/pi-coding-agent/src/core/model-resolver.test.ts +85 -0
  427. package/packages/pi-coding-agent/src/core/model-resolver.ts +511 -0
  428. package/packages/pi-coding-agent/src/core/models-json-writer.test.ts +145 -0
  429. package/packages/pi-coding-agent/src/core/models-json-writer.ts +188 -0
  430. package/packages/pi-coding-agent/src/core/package-commands.test.ts +262 -0
  431. package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
  432. package/packages/pi-coding-agent/src/core/package-manager.ts +1845 -0
  433. package/packages/pi-coding-agent/src/core/prompt-templates.ts +299 -0
  434. package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
  435. package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
  436. package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +295 -0
  437. package/packages/pi-coding-agent/src/core/resolve-config-value.ts +118 -0
  438. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +107 -0
  439. package/packages/pi-coding-agent/src/core/resource-loader.ts +929 -0
  440. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +518 -0
  441. package/packages/pi-coding-agent/src/core/retry-handler.ts +576 -0
  442. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  443. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  444. package/packages/pi-coding-agent/src/core/sdk.test.ts +113 -0
  445. package/packages/pi-coding-agent/src/core/sdk.ts +688 -0
  446. package/packages/pi-coding-agent/src/core/session-manager.test.ts +129 -0
  447. package/packages/pi-coding-agent/src/core/session-manager.ts +1646 -0
  448. package/packages/pi-coding-agent/src/core/settings-manager-security.test.ts +102 -0
  449. package/packages/pi-coding-agent/src/core/settings-manager.ts +1247 -0
  450. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +117 -0
  451. package/packages/pi-coding-agent/src/core/skills.ts +490 -0
  452. package/packages/pi-coding-agent/src/core/slash-commands.ts +43 -0
  453. package/packages/pi-coding-agent/src/core/system-prompt.ts +296 -0
  454. package/packages/pi-coding-agent/src/core/timings.ts +25 -0
  455. package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
  456. package/packages/pi-coding-agent/src/core/tools/bash-background.test.ts +91 -0
  457. package/packages/pi-coding-agent/src/core/tools/bash-interceptor.test.ts +198 -0
  458. package/packages/pi-coding-agent/src/core/tools/bash-interceptor.ts +115 -0
  459. package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +77 -0
  460. package/packages/pi-coding-agent/src/core/tools/bash.ts +478 -0
  461. package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +85 -0
  462. package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +402 -0
  463. package/packages/pi-coding-agent/src/core/tools/edit.ts +242 -0
  464. package/packages/pi-coding-agent/src/core/tools/find.ts +209 -0
  465. package/packages/pi-coding-agent/src/core/tools/grep.ts +356 -0
  466. package/packages/pi-coding-agent/src/core/tools/hashline-edit.ts +318 -0
  467. package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +207 -0
  468. package/packages/pi-coding-agent/src/core/tools/hashline.test.ts +456 -0
  469. package/packages/pi-coding-agent/src/core/tools/hashline.ts +525 -0
  470. package/packages/pi-coding-agent/src/core/tools/index.ts +226 -0
  471. package/packages/pi-coding-agent/src/core/tools/ls.ts +178 -0
  472. package/packages/pi-coding-agent/src/core/tools/path-utils.test.ts +67 -0
  473. package/packages/pi-coding-agent/src/core/tools/path-utils.ts +106 -0
  474. package/packages/pi-coding-agent/src/core/tools/read.ts +235 -0
  475. package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +31 -0
  476. package/packages/pi-coding-agent/src/core/tools/tool-compatibility-registry.ts +83 -0
  477. package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
  478. package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
  479. package/packages/pi-coding-agent/src/core/tools/truncate.ts +267 -0
  480. package/packages/pi-coding-agent/src/core/tools/write.ts +133 -0
  481. package/packages/pi-coding-agent/src/index.ts +422 -0
  482. package/packages/pi-coding-agent/src/main.ts +649 -0
  483. package/packages/pi-coding-agent/src/migrations.ts +295 -0
  484. package/packages/pi-coding-agent/src/modes/index.ts +16 -0
  485. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/assistant-message-design.test.ts +128 -0
  486. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +93 -0
  487. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/collapsible-message.test.ts +111 -0
  488. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/login-dialog.test.ts +24 -0
  489. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +28 -0
  490. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +41 -0
  491. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +512 -0
  492. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/user-message-design.test.ts +139 -0
  493. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +66 -0
  494. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +161 -0
  495. package/packages/pi-coding-agent/src/modes/interactive/components/animated-component.test.ts +115 -0
  496. package/packages/pi-coding-agent/src/modes/interactive/components/animated-component.ts +107 -0
  497. package/packages/pi-coding-agent/src/modes/interactive/components/armin.ts +360 -0
  498. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +200 -0
  499. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.test.ts +35 -0
  500. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +287 -0
  501. package/packages/pi-coding-agent/src/modes/interactive/components/bordered-loader.ts +66 -0
  502. package/packages/pi-coding-agent/src/modes/interactive/components/branch-summary-message.ts +54 -0
  503. package/packages/pi-coding-agent/src/modes/interactive/components/collapsible-message.ts +45 -0
  504. package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +73 -0
  505. package/packages/pi-coding-agent/src/modes/interactive/components/config-selector.ts +599 -0
  506. package/packages/pi-coding-agent/src/modes/interactive/components/countdown-timer.ts +43 -0
  507. package/packages/pi-coding-agent/src/modes/interactive/components/custom-editor.ts +97 -0
  508. package/packages/pi-coding-agent/src/modes/interactive/components/custom-message.ts +89 -0
  509. package/packages/pi-coding-agent/src/modes/interactive/components/daxnuts.test.ts +68 -0
  510. package/packages/pi-coding-agent/src/modes/interactive/components/daxnuts.ts +159 -0
  511. package/packages/pi-coding-agent/src/modes/interactive/components/diff.ts +153 -0
  512. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +99 -0
  513. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +97 -0
  514. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +150 -0
  515. package/packages/pi-coding-agent/src/modes/interactive/components/extension-input.ts +92 -0
  516. package/packages/pi-coding-agent/src/modes/interactive/components/extension-selector.ts +152 -0
  517. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +266 -0
  518. package/packages/pi-coding-agent/src/modes/interactive/components/index.ts +33 -0
  519. package/packages/pi-coding-agent/src/modes/interactive/components/interactive-key-handling.test.ts +122 -0
  520. package/packages/pi-coding-agent/src/modes/interactive/components/keybinding-hints.ts +84 -0
  521. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +256 -0
  522. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +693 -0
  523. package/packages/pi-coding-agent/src/modes/interactive/components/oauth-selector.ts +127 -0
  524. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +231 -0
  525. package/packages/pi-coding-agent/src/modes/interactive/components/render-cache.ts +22 -0
  526. package/packages/pi-coding-agent/src/modes/interactive/components/scoped-models-selector.ts +342 -0
  527. package/packages/pi-coding-agent/src/modes/interactive/components/selector-footers.test.ts +63 -0
  528. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector-search.ts +194 -0
  529. package/packages/pi-coding-agent/src/modes/interactive/components/session-selector.ts +1015 -0
  530. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +466 -0
  531. package/packages/pi-coding-agent/src/modes/interactive/components/show-images-selector.ts +47 -0
  532. package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +61 -0
  533. package/packages/pi-coding-agent/src/modes/interactive/components/theme-selector.test.ts +27 -0
  534. package/packages/pi-coding-agent/src/modes/interactive/components/theme-selector.ts +67 -0
  535. package/packages/pi-coding-agent/src/modes/interactive/components/thinking-selector.ts +66 -0
  536. package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +49 -0
  537. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +303 -0
  538. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +1457 -0
  539. package/packages/pi-coding-agent/src/modes/interactive/components/transcript-design.ts +345 -0
  540. package/packages/pi-coding-agent/src/modes/interactive/components/tree-render-utils.ts +84 -0
  541. package/packages/pi-coding-agent/src/modes/interactive/components/tree-selector.ts +1125 -0
  542. package/packages/pi-coding-agent/src/modes/interactive/components/user-message-selector.test.ts +28 -0
  543. package/packages/pi-coding-agent/src/modes/interactive/components/user-message-selector.ts +154 -0
  544. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +76 -0
  545. package/packages/pi-coding-agent/src/modes/interactive/components/visual-truncate.ts +50 -0
  546. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +230 -0
  547. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +1066 -0
  548. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +68 -0
  549. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +373 -0
  550. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +157 -0
  551. package/packages/pi-coding-agent/src/modes/interactive/controllers/model-controller.ts +76 -0
  552. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-lifecycle.test.ts +63 -0
  553. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-ordering.test.ts +73 -0
  554. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +40 -0
  555. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4418 -0
  556. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  557. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +695 -0
  558. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-highlight.test.ts +23 -0
  559. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +96 -0
  560. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +1130 -0
  561. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +388 -0
  562. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +68 -0
  563. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  564. package/packages/pi-coding-agent/src/modes/interactive/utils/shorten-path.ts +15 -0
  565. package/packages/pi-coding-agent/src/modes/interactive/utils/tool-call-summary.test.ts +39 -0
  566. package/packages/pi-coding-agent/src/modes/interactive/utils/tool-call-summary.ts +56 -0
  567. package/packages/pi-coding-agent/src/modes/print-mode.ts +106 -0
  568. package/packages/pi-coding-agent/src/modes/rpc/jsonl.ts +64 -0
  569. package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +109 -0
  570. package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +574 -0
  571. package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +891 -0
  572. package/packages/pi-coding-agent/src/modes/rpc/rpc-protocol-v2.test.ts +971 -0
  573. package/packages/pi-coding-agent/src/modes/rpc/rpc-types.ts +4 -0
  574. package/packages/pi-coding-agent/src/modes/shared/command-context-actions.ts +53 -0
  575. package/packages/pi-coding-agent/src/resources/extensions/memory/index.ts +270 -0
  576. package/packages/pi-coding-agent/src/resources/extensions/memory/pipeline.ts +567 -0
  577. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +31 -0
  578. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +98 -0
  579. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +479 -0
  580. package/packages/pi-coding-agent/src/tests/path-display.test.ts +85 -0
  581. package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
  582. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  583. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  584. package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
  585. package/packages/pi-coding-agent/src/types/ambient-modules.d.ts +69 -0
  586. package/packages/pi-coding-agent/src/utils/changelog.ts +99 -0
  587. package/packages/pi-coding-agent/src/utils/clipboard-image.ts +227 -0
  588. package/packages/pi-coding-agent/src/utils/clipboard-native.ts +11 -0
  589. package/packages/pi-coding-agent/src/utils/clipboard.ts +14 -0
  590. package/packages/pi-coding-agent/src/utils/error.ts +6 -0
  591. package/packages/pi-coding-agent/src/utils/frontmatter.ts +39 -0
  592. package/packages/pi-coding-agent/src/utils/git.ts +192 -0
  593. package/packages/pi-coding-agent/src/utils/image-convert.ts +28 -0
  594. package/packages/pi-coding-agent/src/utils/image-resize.ts +225 -0
  595. package/packages/pi-coding-agent/src/utils/mime.ts +30 -0
  596. package/packages/pi-coding-agent/src/utils/path-display.ts +36 -0
  597. package/packages/pi-coding-agent/src/utils/photon.ts +2 -0
  598. package/packages/pi-coding-agent/src/utils/shell.ts +212 -0
  599. package/packages/pi-coding-agent/src/utils/sleep.ts +18 -0
  600. package/packages/pi-coding-agent/src/utils/tools-manager.ts +286 -0
  601. package/packages/pi-coding-agent/tsconfig.json +28 -0
  602. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts +2 -0
  603. package/packages/pi-tui/dist/__tests__/autocomplete.test.d.ts.map +1 -0
  604. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +206 -0
  605. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -0
  606. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts +2 -0
  607. package/packages/pi-tui/dist/__tests__/fuzzy.test.d.ts.map +1 -0
  608. package/packages/pi-tui/dist/__tests__/fuzzy.test.js +100 -0
  609. package/packages/pi-tui/dist/__tests__/fuzzy.test.js.map +1 -0
  610. package/packages/pi-tui/dist/__tests__/keys.test.d.ts +2 -0
  611. package/packages/pi-tui/dist/__tests__/keys.test.d.ts.map +1 -0
  612. package/packages/pi-tui/dist/__tests__/keys.test.js +18 -0
  613. package/packages/pi-tui/dist/__tests__/keys.test.js.map +1 -0
  614. package/packages/pi-tui/dist/__tests__/loader.test.d.ts +2 -0
  615. package/packages/pi-tui/dist/__tests__/loader.test.d.ts.map +1 -0
  616. package/packages/pi-tui/dist/__tests__/loader.test.js +24 -0
  617. package/packages/pi-tui/dist/__tests__/loader.test.js.map +1 -0
  618. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts +2 -0
  619. package/packages/pi-tui/dist/__tests__/overlay-layout.test.d.ts.map +1 -0
  620. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +227 -0
  621. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -0
  622. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts +2 -0
  623. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts.map +1 -0
  624. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +80 -0
  625. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -0
  626. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  627. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  628. package/packages/pi-tui/dist/__tests__/style.test.js +129 -0
  629. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  630. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts +2 -0
  631. package/packages/pi-tui/dist/__tests__/terminal.test.d.ts.map +1 -0
  632. package/packages/pi-tui/dist/__tests__/terminal.test.js +103 -0
  633. package/packages/pi-tui/dist/__tests__/terminal.test.js.map +1 -0
  634. package/packages/pi-tui/dist/__tests__/tui.test.d.ts +2 -0
  635. package/packages/pi-tui/dist/__tests__/tui.test.d.ts.map +1 -0
  636. package/packages/pi-tui/dist/__tests__/tui.test.js +315 -0
  637. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -0
  638. package/packages/pi-tui/dist/__tests__/utils.test.d.ts +2 -0
  639. package/packages/pi-tui/dist/__tests__/utils.test.d.ts.map +1 -0
  640. package/packages/pi-tui/dist/__tests__/utils.test.js +17 -0
  641. package/packages/pi-tui/dist/__tests__/utils.test.js.map +1 -0
  642. package/packages/pi-tui/dist/autocomplete.d.ts +55 -0
  643. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -0
  644. package/packages/pi-tui/dist/autocomplete.js +540 -0
  645. package/packages/pi-tui/dist/autocomplete.js.map +1 -0
  646. package/packages/pi-tui/dist/components/__tests__/box.test.d.ts +2 -0
  647. package/packages/pi-tui/dist/components/__tests__/box.test.d.ts.map +1 -0
  648. package/packages/pi-tui/dist/components/__tests__/box.test.js +20 -0
  649. package/packages/pi-tui/dist/components/__tests__/box.test.js.map +1 -0
  650. package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.d.ts +2 -0
  651. package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.d.ts.map +1 -0
  652. package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.js +38 -0
  653. package/packages/pi-tui/dist/components/__tests__/cancellable-loader.test.js.map +1 -0
  654. package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts +2 -0
  655. package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts.map +1 -0
  656. package/packages/pi-tui/dist/components/__tests__/editor.test.js +89 -0
  657. package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -0
  658. package/packages/pi-tui/dist/components/__tests__/input.test.d.ts +2 -0
  659. package/packages/pi-tui/dist/components/__tests__/input.test.d.ts.map +1 -0
  660. package/packages/pi-tui/dist/components/__tests__/input.test.js +81 -0
  661. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -0
  662. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
  663. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
  664. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
  665. package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
  666. package/packages/pi-tui/dist/components/__tests__/loader.test.d.ts +2 -0
  667. package/packages/pi-tui/dist/components/__tests__/loader.test.d.ts.map +1 -0
  668. package/packages/pi-tui/dist/components/__tests__/loader.test.js +81 -0
  669. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -0
  670. package/packages/pi-tui/dist/components/__tests__/markdown-list.test.d.ts +2 -0
  671. package/packages/pi-tui/dist/components/__tests__/markdown-list.test.d.ts.map +1 -0
  672. package/packages/pi-tui/dist/components/__tests__/markdown-list.test.js +36 -0
  673. package/packages/pi-tui/dist/components/__tests__/markdown-list.test.js.map +1 -0
  674. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts +2 -0
  675. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.d.ts.map +1 -0
  676. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +70 -0
  677. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -0
  678. package/packages/pi-tui/dist/components/__tests__/select-list.test.d.ts +2 -0
  679. package/packages/pi-tui/dist/components/__tests__/select-list.test.d.ts.map +1 -0
  680. package/packages/pi-tui/dist/components/__tests__/select-list.test.js +42 -0
  681. package/packages/pi-tui/dist/components/__tests__/select-list.test.js.map +1 -0
  682. package/packages/pi-tui/dist/components/__tests__/truncated-text.test.d.ts +2 -0
  683. package/packages/pi-tui/dist/components/__tests__/truncated-text.test.d.ts.map +1 -0
  684. package/packages/pi-tui/dist/components/__tests__/truncated-text.test.js +14 -0
  685. package/packages/pi-tui/dist/components/__tests__/truncated-text.test.js.map +1 -0
  686. package/packages/pi-tui/dist/components/box.d.ts +23 -0
  687. package/packages/pi-tui/dist/components/box.d.ts.map +1 -0
  688. package/packages/pi-tui/dist/components/box.js +111 -0
  689. package/packages/pi-tui/dist/components/box.js.map +1 -0
  690. package/packages/pi-tui/dist/components/cancellable-loader.d.ts +22 -0
  691. package/packages/pi-tui/dist/components/cancellable-loader.d.ts.map +1 -0
  692. package/packages/pi-tui/dist/components/cancellable-loader.js +38 -0
  693. package/packages/pi-tui/dist/components/cancellable-loader.js.map +1 -0
  694. package/packages/pi-tui/dist/components/editor.d.ts +245 -0
  695. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -0
  696. package/packages/pi-tui/dist/components/editor.js +1825 -0
  697. package/packages/pi-tui/dist/components/editor.js.map +1 -0
  698. package/packages/pi-tui/dist/components/image.d.ts +37 -0
  699. package/packages/pi-tui/dist/components/image.d.ts.map +1 -0
  700. package/packages/pi-tui/dist/components/image.js +84 -0
  701. package/packages/pi-tui/dist/components/image.js.map +1 -0
  702. package/packages/pi-tui/dist/components/image.test.d.ts +6 -0
  703. package/packages/pi-tui/dist/components/image.test.d.ts.map +1 -0
  704. package/packages/pi-tui/dist/components/image.test.js +33 -0
  705. package/packages/pi-tui/dist/components/image.test.js.map +1 -0
  706. package/packages/pi-tui/dist/components/input.d.ts +42 -0
  707. package/packages/pi-tui/dist/components/input.d.ts.map +1 -0
  708. package/packages/pi-tui/dist/components/input.js +479 -0
  709. package/packages/pi-tui/dist/components/input.js.map +1 -0
  710. package/packages/pi-tui/dist/components/loader.d.ts +24 -0
  711. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -0
  712. package/packages/pi-tui/dist/components/loader.js +74 -0
  713. package/packages/pi-tui/dist/components/loader.js.map +1 -0
  714. package/packages/pi-tui/dist/components/markdown.d.ts +106 -0
  715. package/packages/pi-tui/dist/components/markdown.d.ts.map +1 -0
  716. package/packages/pi-tui/dist/components/markdown.js +668 -0
  717. package/packages/pi-tui/dist/components/markdown.js.map +1 -0
  718. package/packages/pi-tui/dist/components/select-list.d.ts +32 -0
  719. package/packages/pi-tui/dist/components/select-list.d.ts.map +1 -0
  720. package/packages/pi-tui/dist/components/select-list.js +155 -0
  721. package/packages/pi-tui/dist/components/select-list.js.map +1 -0
  722. package/packages/pi-tui/dist/components/settings-list.d.ts +50 -0
  723. package/packages/pi-tui/dist/components/settings-list.d.ts.map +1 -0
  724. package/packages/pi-tui/dist/components/settings-list.js +179 -0
  725. package/packages/pi-tui/dist/components/settings-list.js.map +1 -0
  726. package/packages/pi-tui/dist/components/spacer.d.ts +12 -0
  727. package/packages/pi-tui/dist/components/spacer.d.ts.map +1 -0
  728. package/packages/pi-tui/dist/components/spacer.js +22 -0
  729. package/packages/pi-tui/dist/components/spacer.js.map +1 -0
  730. package/packages/pi-tui/dist/components/text.d.ts +19 -0
  731. package/packages/pi-tui/dist/components/text.d.ts.map +1 -0
  732. package/packages/pi-tui/dist/components/text.js +83 -0
  733. package/packages/pi-tui/dist/components/text.js.map +1 -0
  734. package/packages/pi-tui/dist/components/truncated-text.d.ts +13 -0
  735. package/packages/pi-tui/dist/components/truncated-text.d.ts.map +1 -0
  736. package/packages/pi-tui/dist/components/truncated-text.js +54 -0
  737. package/packages/pi-tui/dist/components/truncated-text.js.map +1 -0
  738. package/packages/pi-tui/dist/editor-component.d.ts +41 -0
  739. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -0
  740. package/packages/pi-tui/dist/editor-component.js +2 -0
  741. package/packages/pi-tui/dist/editor-component.js.map +1 -0
  742. package/packages/pi-tui/dist/fuzzy.d.ts +16 -0
  743. package/packages/pi-tui/dist/fuzzy.d.ts.map +1 -0
  744. package/packages/pi-tui/dist/fuzzy.js +111 -0
  745. package/packages/pi-tui/dist/fuzzy.js.map +1 -0
  746. package/packages/pi-tui/dist/index.d.ts +24 -0
  747. package/packages/pi-tui/dist/index.d.ts.map +1 -0
  748. package/packages/pi-tui/dist/index.js +35 -0
  749. package/packages/pi-tui/dist/index.js.map +1 -0
  750. package/packages/pi-tui/dist/keybindings.d.ts +39 -0
  751. package/packages/pi-tui/dist/keybindings.d.ts.map +1 -0
  752. package/packages/pi-tui/dist/keybindings.js +116 -0
  753. package/packages/pi-tui/dist/keybindings.js.map +1 -0
  754. package/packages/pi-tui/dist/keys.d.ts +142 -0
  755. package/packages/pi-tui/dist/keys.d.ts.map +1 -0
  756. package/packages/pi-tui/dist/keys.js +994 -0
  757. package/packages/pi-tui/dist/keys.js.map +1 -0
  758. package/packages/pi-tui/dist/kill-ring.d.ts +28 -0
  759. package/packages/pi-tui/dist/kill-ring.d.ts.map +1 -0
  760. package/packages/pi-tui/dist/kill-ring.js +46 -0
  761. package/packages/pi-tui/dist/kill-ring.js.map +1 -0
  762. package/packages/pi-tui/dist/overlay-layout.d.ts +55 -0
  763. package/packages/pi-tui/dist/overlay-layout.d.ts.map +1 -0
  764. package/packages/pi-tui/dist/overlay-layout.js +314 -0
  765. package/packages/pi-tui/dist/overlay-layout.js.map +1 -0
  766. package/packages/pi-tui/dist/stdin-buffer.d.ts +55 -0
  767. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -0
  768. package/packages/pi-tui/dist/stdin-buffer.js +342 -0
  769. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -0
  770. package/packages/pi-tui/dist/style.d.ts +52 -0
  771. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  772. package/packages/pi-tui/dist/style.js +219 -0
  773. package/packages/pi-tui/dist/style.js.map +1 -0
  774. package/packages/pi-tui/dist/terminal-image.d.ts +68 -0
  775. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -0
  776. package/packages/pi-tui/dist/terminal-image.js +181 -0
  777. package/packages/pi-tui/dist/terminal-image.js.map +1 -0
  778. package/packages/pi-tui/dist/terminal.d.ts +89 -0
  779. package/packages/pi-tui/dist/terminal.d.ts.map +1 -0
  780. package/packages/pi-tui/dist/terminal.js +295 -0
  781. package/packages/pi-tui/dist/terminal.js.map +1 -0
  782. package/packages/pi-tui/dist/tui.d.ts +213 -0
  783. package/packages/pi-tui/dist/tui.d.ts.map +1 -0
  784. package/packages/pi-tui/dist/tui.js +978 -0
  785. package/packages/pi-tui/dist/tui.js.map +1 -0
  786. package/packages/pi-tui/dist/undo-stack.d.ts +17 -0
  787. package/packages/pi-tui/dist/undo-stack.d.ts.map +1 -0
  788. package/packages/pi-tui/dist/undo-stack.js +27 -0
  789. package/packages/pi-tui/dist/undo-stack.js.map +1 -0
  790. package/packages/pi-tui/dist/utils.d.ts +72 -0
  791. package/packages/pi-tui/dist/utils.d.ts.map +1 -0
  792. package/packages/pi-tui/dist/utils.js +120 -0
  793. package/packages/pi-tui/dist/utils.js.map +1 -0
  794. package/packages/pi-tui/package.json +35 -0
  795. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +264 -0
  796. package/packages/pi-tui/src/__tests__/fuzzy.test.ts +120 -0
  797. package/packages/pi-tui/src/__tests__/keys.test.ts +21 -0
  798. package/packages/pi-tui/src/__tests__/loader.test.ts +30 -0
  799. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +266 -0
  800. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +99 -0
  801. package/packages/pi-tui/src/__tests__/style.test.ts +156 -0
  802. package/packages/pi-tui/src/__tests__/terminal.test.ts +121 -0
  803. package/packages/pi-tui/src/__tests__/tui.test.ts +377 -0
  804. package/packages/pi-tui/src/__tests__/utils.test.ts +22 -0
  805. package/packages/pi-tui/src/autocomplete.ts +675 -0
  806. package/packages/pi-tui/src/components/__tests__/box.test.ts +25 -0
  807. package/packages/pi-tui/src/components/__tests__/cancellable-loader.test.ts +45 -0
  808. package/packages/pi-tui/src/components/__tests__/editor.test.ts +119 -0
  809. package/packages/pi-tui/src/components/__tests__/input.test.ts +111 -0
  810. package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
  811. package/packages/pi-tui/src/components/__tests__/loader.test.ts +122 -0
  812. package/packages/pi-tui/src/components/__tests__/markdown-list.test.ts +40 -0
  813. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +82 -0
  814. package/packages/pi-tui/src/components/__tests__/select-list.test.ts +70 -0
  815. package/packages/pi-tui/src/components/__tests__/truncated-text.test.ts +17 -0
  816. package/packages/pi-tui/src/components/box.ts +150 -0
  817. package/packages/pi-tui/src/components/cancellable-loader.ts +42 -0
  818. package/packages/pi-tui/src/components/editor.ts +2196 -0
  819. package/packages/pi-tui/src/components/image.test.ts +41 -0
  820. package/packages/pi-tui/src/components/image.ts +131 -0
  821. package/packages/pi-tui/src/components/input.ts +558 -0
  822. package/packages/pi-tui/src/components/loader.ts +83 -0
  823. package/packages/pi-tui/src/components/markdown.ts +842 -0
  824. package/packages/pi-tui/src/components/select-list.ts +194 -0
  825. package/packages/pi-tui/src/components/settings-list.ts +251 -0
  826. package/packages/pi-tui/src/components/spacer.ts +28 -0
  827. package/packages/pi-tui/src/components/text.ts +107 -0
  828. package/packages/pi-tui/src/components/truncated-text.ts +72 -0
  829. package/packages/pi-tui/src/editor-component.ts +77 -0
  830. package/packages/pi-tui/src/fuzzy.ts +138 -0
  831. package/packages/pi-tui/src/index.ts +98 -0
  832. package/packages/pi-tui/src/keybindings.ts +189 -0
  833. package/packages/pi-tui/src/keys.ts +1196 -0
  834. package/packages/pi-tui/src/kill-ring.ts +46 -0
  835. package/packages/pi-tui/src/overlay-layout.ts +408 -0
  836. package/packages/pi-tui/src/stdin-buffer.ts +419 -0
  837. package/packages/pi-tui/src/style.ts +295 -0
  838. package/packages/pi-tui/src/terminal-image.ts +260 -0
  839. package/packages/pi-tui/src/terminal.ts +377 -0
  840. package/packages/pi-tui/src/tui.ts +1182 -0
  841. package/packages/pi-tui/src/undo-stack.ts +28 -0
  842. package/packages/pi-tui/src/utils.ts +154 -0
  843. package/packages/pi-tui/tsconfig.json +28 -0
  844. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -0
  845. package/packages/rpc-client/README.md +132 -0
  846. package/packages/rpc-client/examples/basic-usage.ts +13 -0
  847. package/packages/rpc-client/package.json +42 -0
  848. package/packages/rpc-client/src/index.ts +10 -0
  849. package/packages/rpc-client/src/jsonl.ts +64 -0
  850. package/packages/rpc-client/src/rpc-client.test.ts +625 -0
  851. package/packages/rpc-client/src/rpc-client.ts +663 -0
  852. package/packages/rpc-client/src/rpc-types.ts +4 -0
  853. package/packages/rpc-client/tsconfig.examples.json +17 -0
  854. package/packages/rpc-client/tsconfig.json +25 -0
  855. package/pkg/dist/core/export-html/template.css +971 -0
  856. package/pkg/dist/core/export-html/template.html +54 -0
  857. package/pkg/dist/core/export-html/template.js +1583 -0
  858. package/pkg/dist/core/export-html/vendor/highlight.min.js +1213 -0
  859. package/pkg/dist/core/export-html/vendor/marked.min.js +6 -0
  860. package/pkg/package.json +8 -0
  861. package/scripts/ensure-workspace-builds.cjs +123 -0
  862. package/scripts/install.js +526 -0
  863. package/scripts/lib/workspace-manifest.cjs +86 -0
  864. package/scripts/link-workspace-packages.cjs +82 -0
  865. package/scripts/postinstall.js +11 -0
  866. package/src/resources/GSD-WORKFLOW.md +664 -0
  867. package/src/resources/agents/debugger.md +58 -0
  868. package/src/resources/agents/doc-writer.md +43 -0
  869. package/src/resources/agents/git-ops.md +56 -0
  870. package/src/resources/agents/javascript-pro.md +55 -0
  871. package/src/resources/agents/planner.md +55 -0
  872. package/src/resources/agents/refactorer.md +47 -0
  873. package/src/resources/agents/researcher.md +29 -0
  874. package/src/resources/agents/reviewer.md +48 -0
  875. package/src/resources/agents/scout.md +56 -0
  876. package/src/resources/agents/security.md +59 -0
  877. package/src/resources/agents/tester.md +50 -0
  878. package/src/resources/agents/typescript-pro.md +61 -0
  879. package/src/resources/agents/worker.md +31 -0
  880. package/src/resources/extensions/ask-user-questions.ts +478 -0
  881. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  882. package/src/resources/extensions/async-jobs/async-bash-tool.ts +263 -0
  883. package/src/resources/extensions/async-jobs/await-tool.test.ts +200 -0
  884. package/src/resources/extensions/async-jobs/await-tool.ts +136 -0
  885. package/src/resources/extensions/async-jobs/cancel-job-tool.ts +35 -0
  886. package/src/resources/extensions/async-jobs/extension-manifest.json +13 -0
  887. package/src/resources/extensions/async-jobs/index.ts +153 -0
  888. package/src/resources/extensions/async-jobs/job-manager.ts +242 -0
  889. package/src/resources/extensions/aws-auth/index.ts +144 -0
  890. package/src/resources/extensions/bg-shell/bg-shell-command.ts +219 -0
  891. package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +413 -0
  892. package/src/resources/extensions/bg-shell/bg-shell-tool.ts +985 -0
  893. package/src/resources/extensions/bg-shell/extension-manifest.json +14 -0
  894. package/src/resources/extensions/bg-shell/index.ts +54 -0
  895. package/src/resources/extensions/bg-shell/interaction.ts +200 -0
  896. package/src/resources/extensions/bg-shell/output-formatter.ts +262 -0
  897. package/src/resources/extensions/bg-shell/overlay.ts +441 -0
  898. package/src/resources/extensions/bg-shell/process-manager.ts +469 -0
  899. package/src/resources/extensions/bg-shell/readiness-detector.ts +126 -0
  900. package/src/resources/extensions/bg-shell/types.ts +291 -0
  901. package/src/resources/extensions/bg-shell/utilities.ts +93 -0
  902. package/src/resources/extensions/browser-tools/BROWSER-TOOLS-V2-PROPOSAL.md +1277 -0
  903. package/src/resources/extensions/browser-tools/capture.ts +229 -0
  904. package/src/resources/extensions/browser-tools/core.ts +1196 -0
  905. package/src/resources/extensions/browser-tools/evaluate-helpers.ts +184 -0
  906. package/src/resources/extensions/browser-tools/extension-manifest.json +37 -0
  907. package/src/resources/extensions/browser-tools/index.ts +163 -0
  908. package/src/resources/extensions/browser-tools/lifecycle.ts +270 -0
  909. package/src/resources/extensions/browser-tools/package.json +24 -0
  910. package/src/resources/extensions/browser-tools/refs.ts +264 -0
  911. package/src/resources/extensions/browser-tools/settle.ts +197 -0
  912. package/src/resources/extensions/browser-tools/state.ts +408 -0
  913. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +601 -0
  914. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +651 -0
  915. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +91 -0
  916. package/src/resources/extensions/browser-tools/tools/action-cache.ts +216 -0
  917. package/src/resources/extensions/browser-tools/tools/assertions.ts +342 -0
  918. package/src/resources/extensions/browser-tools/tools/codegen.ts +274 -0
  919. package/src/resources/extensions/browser-tools/tools/device.ts +183 -0
  920. package/src/resources/extensions/browser-tools/tools/extract.ts +229 -0
  921. package/src/resources/extensions/browser-tools/tools/forms.ts +805 -0
  922. package/src/resources/extensions/browser-tools/tools/injection-detect.ts +221 -0
  923. package/src/resources/extensions/browser-tools/tools/inspection.ts +492 -0
  924. package/src/resources/extensions/browser-tools/tools/intent.ts +629 -0
  925. package/src/resources/extensions/browser-tools/tools/interaction.ts +865 -0
  926. package/src/resources/extensions/browser-tools/tools/navigation.ts +232 -0
  927. package/src/resources/extensions/browser-tools/tools/network-mock.ts +244 -0
  928. package/src/resources/extensions/browser-tools/tools/pages.ts +303 -0
  929. package/src/resources/extensions/browser-tools/tools/pdf.ts +92 -0
  930. package/src/resources/extensions/browser-tools/tools/refs.ts +541 -0
  931. package/src/resources/extensions/browser-tools/tools/screenshot.ts +102 -0
  932. package/src/resources/extensions/browser-tools/tools/session.ts +400 -0
  933. package/src/resources/extensions/browser-tools/tools/state-persistence.ts +202 -0
  934. package/src/resources/extensions/browser-tools/tools/verify.ts +117 -0
  935. package/src/resources/extensions/browser-tools/tools/visual-diff.ts +209 -0
  936. package/src/resources/extensions/browser-tools/tools/wait.ts +247 -0
  937. package/src/resources/extensions/browser-tools/tools/zoom.ts +105 -0
  938. package/src/resources/extensions/browser-tools/utils.ts +660 -0
  939. package/src/resources/extensions/claude-code-cli/index.ts +28 -0
  940. package/src/resources/extensions/claude-code-cli/models.ts +51 -0
  941. package/src/resources/extensions/claude-code-cli/package.json +11 -0
  942. package/src/resources/extensions/claude-code-cli/partial-builder.ts +305 -0
  943. package/src/resources/extensions/claude-code-cli/readiness.ts +242 -0
  944. package/src/resources/extensions/claude-code-cli/sdk-types.ts +149 -0
  945. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +1981 -0
  946. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +256 -0
  947. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +2380 -0
  948. package/src/resources/extensions/cmux/index.ts +479 -0
  949. package/src/resources/extensions/cmux/package.json +7 -0
  950. package/src/resources/extensions/context7/extension-manifest.json +12 -0
  951. package/src/resources/extensions/context7/index.ts +435 -0
  952. package/src/resources/extensions/context7/package.json +11 -0
  953. package/src/resources/extensions/get-secrets-from-user.ts +608 -0
  954. package/src/resources/extensions/github-sync/cli.ts +367 -0
  955. package/src/resources/extensions/github-sync/index.ts +93 -0
  956. package/src/resources/extensions/github-sync/mapping.ts +81 -0
  957. package/src/resources/extensions/github-sync/sync.ts +594 -0
  958. package/src/resources/extensions/github-sync/templates.ts +339 -0
  959. package/src/resources/extensions/github-sync/tests/cli.test.ts +89 -0
  960. package/src/resources/extensions/github-sync/tests/commit-linking.test.ts +43 -0
  961. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  962. package/src/resources/extensions/github-sync/tests/mapping.test.ts +104 -0
  963. package/src/resources/extensions/github-sync/tests/sync-source.test.ts +14 -0
  964. package/src/resources/extensions/github-sync/tests/templates.test.ts +209 -0
  965. package/src/resources/extensions/github-sync/types.ts +47 -0
  966. package/src/resources/extensions/google-search/extension-manifest.json +13 -0
  967. package/src/resources/extensions/google-search/index.ts +6 -0
  968. package/src/resources/extensions/google-search/package.json +9 -0
  969. package/src/resources/extensions/gsd/abandon-detect.ts +62 -0
  970. package/src/resources/extensions/gsd/activity-log.ts +184 -0
  971. package/src/resources/extensions/gsd/atomic-write.ts +185 -0
  972. package/src/resources/extensions/gsd/auto/contracts.ts +159 -0
  973. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +72 -0
  974. package/src/resources/extensions/gsd/auto/detect-stuck.ts +138 -0
  975. package/src/resources/extensions/gsd/auto/finalize-timeout.ts +49 -0
  976. package/src/resources/extensions/gsd/auto/infra-errors.ts +92 -0
  977. package/src/resources/extensions/gsd/auto/lease-conflict-notice.ts +62 -0
  978. package/src/resources/extensions/gsd/auto/loop-deps.ts +302 -0
  979. package/src/resources/extensions/gsd/auto/loop.ts +1448 -0
  980. package/src/resources/extensions/gsd/auto/orchestrator.ts +417 -0
  981. package/src/resources/extensions/gsd/auto/phases.ts +3014 -0
  982. package/src/resources/extensions/gsd/auto/resolve.ts +176 -0
  983. package/src/resources/extensions/gsd/auto/run-unit.ts +306 -0
  984. package/src/resources/extensions/gsd/auto/session.ts +427 -0
  985. package/src/resources/extensions/gsd/auto/turn-epoch.ts +108 -0
  986. package/src/resources/extensions/gsd/auto/types.ts +130 -0
  987. package/src/resources/extensions/gsd/auto/unit-runner-events.ts +19 -0
  988. package/src/resources/extensions/gsd/auto/verification-retry-policy.ts +82 -0
  989. package/src/resources/extensions/gsd/auto/workflow-custom-engine-dispatch-outcome.ts +28 -0
  990. package/src/resources/extensions/gsd/auto/workflow-custom-engine-iteration.ts +52 -0
  991. package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile-outcome.ts +58 -0
  992. package/src/resources/extensions/gsd/auto/workflow-custom-engine-reconcile.ts +71 -0
  993. package/src/resources/extensions/gsd/auto/workflow-custom-engine-retry.ts +90 -0
  994. package/src/resources/extensions/gsd/auto/workflow-custom-engine-verify-outcome.ts +50 -0
  995. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +179 -0
  996. package/src/resources/extensions/gsd/auto/workflow-dispatch-ledger.ts +45 -0
  997. package/src/resources/extensions/gsd/auto/workflow-iteration-completion.ts +26 -0
  998. package/src/resources/extensions/gsd/auto/workflow-journal-reporter.ts +33 -0
  999. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +542 -0
  1000. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +71 -0
  1001. package/src/resources/extensions/gsd/auto/workflow-phase-reporter.ts +22 -0
  1002. package/src/resources/extensions/gsd/auto/workflow-session-lock.ts +68 -0
  1003. package/src/resources/extensions/gsd/auto/workflow-sidecar-iteration.ts +46 -0
  1004. package/src/resources/extensions/gsd/auto/workflow-sidecar-queue.ts +46 -0
  1005. package/src/resources/extensions/gsd/auto/workflow-turn-reporter.ts +68 -0
  1006. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +89 -0
  1007. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +51 -0
  1008. package/src/resources/extensions/gsd/auto-artifact-paths.ts +218 -0
  1009. package/src/resources/extensions/gsd/auto-budget.ts +57 -0
  1010. package/src/resources/extensions/gsd/auto-dashboard.ts +1239 -0
  1011. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +311 -0
  1012. package/src/resources/extensions/gsd/auto-dispatch.ts +1827 -0
  1013. package/src/resources/extensions/gsd/auto-model-selection.ts +755 -0
  1014. package/src/resources/extensions/gsd/auto-post-unit.ts +2375 -0
  1015. package/src/resources/extensions/gsd/auto-prompts.ts +4108 -0
  1016. package/src/resources/extensions/gsd/auto-recovery.ts +1217 -0
  1017. package/src/resources/extensions/gsd/auto-runtime-state.ts +63 -0
  1018. package/src/resources/extensions/gsd/auto-start.ts +1561 -0
  1019. package/src/resources/extensions/gsd/auto-status-message.ts +45 -0
  1020. package/src/resources/extensions/gsd/auto-supervisor.ts +86 -0
  1021. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +308 -0
  1022. package/src/resources/extensions/gsd/auto-timers.ts +366 -0
  1023. package/src/resources/extensions/gsd/auto-tool-tracking.ts +156 -0
  1024. package/src/resources/extensions/gsd/auto-unit-closeout.ts +138 -0
  1025. package/src/resources/extensions/gsd/auto-utils.ts +25 -0
  1026. package/src/resources/extensions/gsd/auto-verification.ts +955 -0
  1027. package/src/resources/extensions/gsd/auto-worktree-repair.ts +194 -0
  1028. package/src/resources/extensions/gsd/auto-worktree.ts +2570 -0
  1029. package/src/resources/extensions/gsd/auto.ts +3167 -0
  1030. package/src/resources/extensions/gsd/blocked-models.ts +98 -0
  1031. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +685 -0
  1032. package/src/resources/extensions/gsd/bootstrap/crash-log.ts +32 -0
  1033. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1408 -0
  1034. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +144 -0
  1035. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +123 -0
  1036. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +67 -0
  1037. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +166 -0
  1038. package/src/resources/extensions/gsd/bootstrap/notify-interceptor.ts +34 -0
  1039. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +61 -0
  1040. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +68 -0
  1041. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +154 -0
  1042. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +1203 -0
  1043. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +101 -0
  1044. package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +61 -0
  1045. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +32 -0
  1046. package/src/resources/extensions/gsd/bootstrap/system-context.ts +770 -0
  1047. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
  1048. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-shouldblock-basepath.test.ts +97 -0
  1049. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +103 -0
  1050. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +1059 -0
  1051. package/src/resources/extensions/gsd/branch-patterns.ts +16 -0
  1052. package/src/resources/extensions/gsd/browser-evidence.ts +29 -0
  1053. package/src/resources/extensions/gsd/cache.ts +40 -0
  1054. package/src/resources/extensions/gsd/captures.ts +571 -0
  1055. package/src/resources/extensions/gsd/changelog.ts +213 -0
  1056. package/src/resources/extensions/gsd/claude-import.ts +705 -0
  1057. package/src/resources/extensions/gsd/clean-root-preflight.ts +564 -0
  1058. package/src/resources/extensions/gsd/closeout-recovery.ts +290 -0
  1059. package/src/resources/extensions/gsd/codebase-generator.ts +616 -0
  1060. package/src/resources/extensions/gsd/collision-diagnostics.ts +332 -0
  1061. package/src/resources/extensions/gsd/commands/catalog.ts +577 -0
  1062. package/src/resources/extensions/gsd/commands/context.ts +159 -0
  1063. package/src/resources/extensions/gsd/commands/dispatcher.ts +101 -0
  1064. package/src/resources/extensions/gsd/commands/handlers/auto.ts +179 -0
  1065. package/src/resources/extensions/gsd/commands/handlers/core.ts +597 -0
  1066. package/src/resources/extensions/gsd/commands/handlers/escalate.ts +216 -0
  1067. package/src/resources/extensions/gsd/commands/handlers/notifications-handler.ts +144 -0
  1068. package/src/resources/extensions/gsd/commands/handlers/onboarding.ts +196 -0
  1069. package/src/resources/extensions/gsd/commands/handlers/ops.ts +359 -0
  1070. package/src/resources/extensions/gsd/commands/handlers/parallel.ts +147 -0
  1071. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +691 -0
  1072. package/src/resources/extensions/gsd/commands/index.ts +20 -0
  1073. package/src/resources/extensions/gsd/commands-add-tests.ts +137 -0
  1074. package/src/resources/extensions/gsd/commands-backlog.ts +182 -0
  1075. package/src/resources/extensions/gsd/commands-bootstrap.ts +280 -0
  1076. package/src/resources/extensions/gsd/commands-closeout.ts +109 -0
  1077. package/src/resources/extensions/gsd/commands-cmux.ts +182 -0
  1078. package/src/resources/extensions/gsd/commands-codebase.ts +198 -0
  1079. package/src/resources/extensions/gsd/commands-config.ts +119 -0
  1080. package/src/resources/extensions/gsd/commands-debug.ts +510 -0
  1081. package/src/resources/extensions/gsd/commands-do.ts +110 -0
  1082. package/src/resources/extensions/gsd/commands-eval-review.ts +716 -0
  1083. package/src/resources/extensions/gsd/commands-extensions.ts +1088 -0
  1084. package/src/resources/extensions/gsd/commands-extract-learnings.ts +493 -0
  1085. package/src/resources/extensions/gsd/commands-handlers.ts +510 -0
  1086. package/src/resources/extensions/gsd/commands-inspect.ts +99 -0
  1087. package/src/resources/extensions/gsd/commands-logs.ts +537 -0
  1088. package/src/resources/extensions/gsd/commands-maintenance.ts +544 -0
  1089. package/src/resources/extensions/gsd/commands-mcp-status.ts +402 -0
  1090. package/src/resources/extensions/gsd/commands-memory.ts +551 -0
  1091. package/src/resources/extensions/gsd/commands-pr-branch.ts +234 -0
  1092. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +1848 -0
  1093. package/src/resources/extensions/gsd/commands-rate.ts +55 -0
  1094. package/src/resources/extensions/gsd/commands-scan.ts +126 -0
  1095. package/src/resources/extensions/gsd/commands-session-report.ts +101 -0
  1096. package/src/resources/extensions/gsd/commands-ship.ts +292 -0
  1097. package/src/resources/extensions/gsd/commands-verdict.ts +229 -0
  1098. package/src/resources/extensions/gsd/commands-workflow-templates.ts +684 -0
  1099. package/src/resources/extensions/gsd/commands-worktree.ts +383 -0
  1100. package/src/resources/extensions/gsd/commands.ts +17 -0
  1101. package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
  1102. package/src/resources/extensions/gsd/complexity-classifier.ts +331 -0
  1103. package/src/resources/extensions/gsd/component-loader.ts +592 -0
  1104. package/src/resources/extensions/gsd/component-types.ts +362 -0
  1105. package/src/resources/extensions/gsd/config-overlay.ts +331 -0
  1106. package/src/resources/extensions/gsd/constants.ts +69 -0
  1107. package/src/resources/extensions/gsd/context-budget.ts +309 -0
  1108. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  1109. package/src/resources/extensions/gsd/context-masker.ts +74 -0
  1110. package/src/resources/extensions/gsd/context-store.ts +497 -0
  1111. package/src/resources/extensions/gsd/crash-recovery.ts +427 -0
  1112. package/src/resources/extensions/gsd/custom-execution-policy.ts +74 -0
  1113. package/src/resources/extensions/gsd/custom-verification.ts +183 -0
  1114. package/src/resources/extensions/gsd/custom-workflow-engine.ts +274 -0
  1115. package/src/resources/extensions/gsd/dashboard-overlay.ts +684 -0
  1116. package/src/resources/extensions/gsd/db/auto-workers.ts +310 -0
  1117. package/src/resources/extensions/gsd/db/command-queue.ts +149 -0
  1118. package/src/resources/extensions/gsd/db/milestone-leases.ts +300 -0
  1119. package/src/resources/extensions/gsd/db/runtime-kv.ts +127 -0
  1120. package/src/resources/extensions/gsd/db/unit-dispatches.ts +554 -0
  1121. package/src/resources/extensions/gsd/db-adapter.ts +75 -0
  1122. package/src/resources/extensions/gsd/db-base-schema.ts +387 -0
  1123. package/src/resources/extensions/gsd/db-connection-cache.ts +45 -0
  1124. package/src/resources/extensions/gsd/db-coordination-schema.ts +109 -0
  1125. package/src/resources/extensions/gsd/db-decision-requirement-rows.ts +77 -0
  1126. package/src/resources/extensions/gsd/db-gate-rows.ts +19 -0
  1127. package/src/resources/extensions/gsd/db-lightweight-query-rows.ts +50 -0
  1128. package/src/resources/extensions/gsd/db-memory-fts-schema.ts +66 -0
  1129. package/src/resources/extensions/gsd/db-migration-backup.ts +34 -0
  1130. package/src/resources/extensions/gsd/db-migration-steps.ts +464 -0
  1131. package/src/resources/extensions/gsd/db-milestone-artifact-rows.ts +70 -0
  1132. package/src/resources/extensions/gsd/db-open-state.ts +47 -0
  1133. package/src/resources/extensions/gsd/db-provider.ts +148 -0
  1134. package/src/resources/extensions/gsd/db-runtime-kv-schema.ts +30 -0
  1135. package/src/resources/extensions/gsd/db-schema-metadata.ts +33 -0
  1136. package/src/resources/extensions/gsd/db-task-slice-rows.ts +150 -0
  1137. package/src/resources/extensions/gsd/db-transaction.ts +76 -0
  1138. package/src/resources/extensions/gsd/db-verification-evidence-rows.ts +14 -0
  1139. package/src/resources/extensions/gsd/db-verification-evidence-schema.ts +22 -0
  1140. package/src/resources/extensions/gsd/db-writer.ts +966 -0
  1141. package/src/resources/extensions/gsd/debug-logger.ts +178 -0
  1142. package/src/resources/extensions/gsd/debug-session-store.ts +377 -0
  1143. package/src/resources/extensions/gsd/deep-project-setup-policy.ts +257 -0
  1144. package/src/resources/extensions/gsd/definition-io.ts +18 -0
  1145. package/src/resources/extensions/gsd/definition-loader.ts +469 -0
  1146. package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
  1147. package/src/resources/extensions/gsd/detection.ts +1339 -0
  1148. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  1149. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  1150. package/src/resources/extensions/gsd/diff-context.ts +214 -0
  1151. package/src/resources/extensions/gsd/dispatch-guard.ts +211 -0
  1152. package/src/resources/extensions/gsd/docs/COORDINATION.md +42 -0
  1153. package/src/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
  1154. package/src/resources/extensions/gsd/docs/preferences-reference.md +755 -0
  1155. package/src/resources/extensions/gsd/doctor-checks.ts +5 -0
  1156. package/src/resources/extensions/gsd/doctor-engine-checks.ts +196 -0
  1157. package/src/resources/extensions/gsd/doctor-environment.ts +643 -0
  1158. package/src/resources/extensions/gsd/doctor-format.ts +99 -0
  1159. package/src/resources/extensions/gsd/doctor-git-checks.ts +622 -0
  1160. package/src/resources/extensions/gsd/doctor-global-checks.ts +84 -0
  1161. package/src/resources/extensions/gsd/doctor-proactive.ts +488 -0
  1162. package/src/resources/extensions/gsd/doctor-providers.ts +523 -0
  1163. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +793 -0
  1164. package/src/resources/extensions/gsd/doctor-types.ts +134 -0
  1165. package/src/resources/extensions/gsd/doctor.ts +802 -0
  1166. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +233 -0
  1167. package/src/resources/extensions/gsd/ecosystem/loader.ts +201 -0
  1168. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  1169. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  1170. package/src/resources/extensions/gsd/env-utils.ts +31 -0
  1171. package/src/resources/extensions/gsd/error-classifier.ts +188 -0
  1172. package/src/resources/extensions/gsd/error-utils.ts +6 -0
  1173. package/src/resources/extensions/gsd/errors.ts +29 -0
  1174. package/src/resources/extensions/gsd/escalation.ts +369 -0
  1175. package/src/resources/extensions/gsd/eval-review-schema.ts +243 -0
  1176. package/src/resources/extensions/gsd/exec-history.ts +153 -0
  1177. package/src/resources/extensions/gsd/exec-sandbox.ts +333 -0
  1178. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  1179. package/src/resources/extensions/gsd/exit-command.ts +30 -0
  1180. package/src/resources/extensions/gsd/export-html.ts +1008 -0
  1181. package/src/resources/extensions/gsd/export.ts +318 -0
  1182. package/src/resources/extensions/gsd/extension-manifest.json +33 -0
  1183. package/src/resources/extensions/gsd/file-lock.ts +132 -0
  1184. package/src/resources/extensions/gsd/files.ts +1009 -0
  1185. package/src/resources/extensions/gsd/forensics.ts +1342 -0
  1186. package/src/resources/extensions/gsd/fresh-run-ui.ts +43 -0
  1187. package/src/resources/extensions/gsd/gate-registry.ts +251 -0
  1188. package/src/resources/extensions/gsd/git-conflict-state.ts +23 -0
  1189. package/src/resources/extensions/gsd/git-constants.ts +41 -0
  1190. package/src/resources/extensions/gsd/git-self-heal.ts +158 -0
  1191. package/src/resources/extensions/gsd/git-service.ts +1412 -0
  1192. package/src/resources/extensions/gsd/gitignore.ts +336 -0
  1193. package/src/resources/extensions/gsd/graph-context.ts +212 -0
  1194. package/src/resources/extensions/gsd/graph.ts +349 -0
  1195. package/src/resources/extensions/gsd/gsd-command-home.ts +209 -0
  1196. package/src/resources/extensions/gsd/gsd-db.ts +3190 -0
  1197. package/src/resources/extensions/gsd/gsd-home.ts +30 -0
  1198. package/src/resources/extensions/gsd/guided-flow-queue.ts +443 -0
  1199. package/src/resources/extensions/gsd/guided-flow.ts +2887 -0
  1200. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  1201. package/src/resources/extensions/gsd/health-widget-core.ts +140 -0
  1202. package/src/resources/extensions/gsd/health-widget.ts +148 -0
  1203. package/src/resources/extensions/gsd/history.ts +144 -0
  1204. package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
  1205. package/src/resources/extensions/gsd/index.ts +37 -0
  1206. package/src/resources/extensions/gsd/init-wizard.ts +704 -0
  1207. package/src/resources/extensions/gsd/interrupted-session.ts +269 -0
  1208. package/src/resources/extensions/gsd/journal.ts +218 -0
  1209. package/src/resources/extensions/gsd/json-persistence.ts +78 -0
  1210. package/src/resources/extensions/gsd/jsonl-utils.ts +21 -0
  1211. package/src/resources/extensions/gsd/key-manager.ts +1018 -0
  1212. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  1213. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  1214. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  1215. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  1216. package/src/resources/extensions/gsd/legacy-telemetry.ts +99 -0
  1217. package/src/resources/extensions/gsd/markdown-renderer.ts +982 -0
  1218. package/src/resources/extensions/gsd/marketplace-discovery.ts +508 -0
  1219. package/src/resources/extensions/gsd/mcp-filter.ts +80 -0
  1220. package/src/resources/extensions/gsd/mcp-project-config.ts +128 -0
  1221. package/src/resources/extensions/gsd/md-importer.ts +748 -0
  1222. package/src/resources/extensions/gsd/memory-backfill.ts +212 -0
  1223. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  1224. package/src/resources/extensions/gsd/memory-embeddings.ts +235 -0
  1225. package/src/resources/extensions/gsd/memory-extractor.ts +434 -0
  1226. package/src/resources/extensions/gsd/memory-ingest.ts +286 -0
  1227. package/src/resources/extensions/gsd/memory-relations.ts +240 -0
  1228. package/src/resources/extensions/gsd/memory-source-store.ts +138 -0
  1229. package/src/resources/extensions/gsd/memory-store.ts +909 -0
  1230. package/src/resources/extensions/gsd/metrics.ts +1040 -0
  1231. package/src/resources/extensions/gsd/migrate/audit.ts +219 -0
  1232. package/src/resources/extensions/gsd/migrate/command.ts +341 -0
  1233. package/src/resources/extensions/gsd/migrate/index.ts +44 -0
  1234. package/src/resources/extensions/gsd/migrate/parser.ts +323 -0
  1235. package/src/resources/extensions/gsd/migrate/parsers.ts +676 -0
  1236. package/src/resources/extensions/gsd/migrate/preview.ts +58 -0
  1237. package/src/resources/extensions/gsd/migrate/safety.ts +149 -0
  1238. package/src/resources/extensions/gsd/migrate/transformer.ts +411 -0
  1239. package/src/resources/extensions/gsd/migrate/types.ts +370 -0
  1240. package/src/resources/extensions/gsd/migrate/validator.ts +55 -0
  1241. package/src/resources/extensions/gsd/migrate/writer.ts +592 -0
  1242. package/src/resources/extensions/gsd/migrate-external.ts +215 -0
  1243. package/src/resources/extensions/gsd/migration-auto-check.ts +121 -0
  1244. package/src/resources/extensions/gsd/milestone-actions.ts +193 -0
  1245. package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
  1246. package/src/resources/extensions/gsd/milestone-id-utils.ts +32 -0
  1247. package/src/resources/extensions/gsd/milestone-ids.ts +136 -0
  1248. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +373 -0
  1249. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  1250. package/src/resources/extensions/gsd/milestone-validation-gates.ts +53 -0
  1251. package/src/resources/extensions/gsd/model-cost-table.ts +89 -0
  1252. package/src/resources/extensions/gsd/model-router.ts +844 -0
  1253. package/src/resources/extensions/gsd/namespaced-registry.ts +467 -0
  1254. package/src/resources/extensions/gsd/namespaced-resolver.ts +307 -0
  1255. package/src/resources/extensions/gsd/native-git-bridge.ts +1447 -0
  1256. package/src/resources/extensions/gsd/native-parser-bridge.ts +267 -0
  1257. package/src/resources/extensions/gsd/notification-overlay.ts +322 -0
  1258. package/src/resources/extensions/gsd/notification-store.ts +342 -0
  1259. package/src/resources/extensions/gsd/notification-widget.ts +69 -0
  1260. package/src/resources/extensions/gsd/notifications.ts +153 -0
  1261. package/src/resources/extensions/gsd/observability-validator.ts +456 -0
  1262. package/src/resources/extensions/gsd/onboarding-state.ts +146 -0
  1263. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  1264. package/src/resources/extensions/gsd/package.json +11 -0
  1265. package/src/resources/extensions/gsd/parallel-eligibility.ts +248 -0
  1266. package/src/resources/extensions/gsd/parallel-merge.ts +270 -0
  1267. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +507 -0
  1268. package/src/resources/extensions/gsd/parallel-orchestrator.ts +1077 -0
  1269. package/src/resources/extensions/gsd/parsers-legacy.ts +292 -0
  1270. package/src/resources/extensions/gsd/paths.ts +722 -0
  1271. package/src/resources/extensions/gsd/pending-auto-start.ts +81 -0
  1272. package/src/resources/extensions/gsd/phase-anchor.ts +71 -0
  1273. package/src/resources/extensions/gsd/planning-depth.ts +137 -0
  1274. package/src/resources/extensions/gsd/planning-path-scope.ts +45 -0
  1275. package/src/resources/extensions/gsd/plugin-importer.ts +411 -0
  1276. package/src/resources/extensions/gsd/post-execution-checks.ts +665 -0
  1277. package/src/resources/extensions/gsd/post-unit-hooks.ts +86 -0
  1278. package/src/resources/extensions/gsd/pr-evidence.ts +182 -0
  1279. package/src/resources/extensions/gsd/pre-execution-checks.ts +890 -0
  1280. package/src/resources/extensions/gsd/preferences-mcp.ts +27 -0
  1281. package/src/resources/extensions/gsd/preferences-models.ts +572 -0
  1282. package/src/resources/extensions/gsd/preferences-skills.ts +147 -0
  1283. package/src/resources/extensions/gsd/preferences-types.ts +579 -0
  1284. package/src/resources/extensions/gsd/preferences-validation.ts +1453 -0
  1285. package/src/resources/extensions/gsd/preferences.ts +697 -0
  1286. package/src/resources/extensions/gsd/preparation.ts +1419 -0
  1287. package/src/resources/extensions/gsd/process-task-path.ts +81 -0
  1288. package/src/resources/extensions/gsd/progress-score.ts +161 -0
  1289. package/src/resources/extensions/gsd/project-research-policy.ts +259 -0
  1290. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +217 -0
  1291. package/src/resources/extensions/gsd/prompt-loader.ts +248 -0
  1292. package/src/resources/extensions/gsd/prompt-ordering.ts +200 -0
  1293. package/src/resources/extensions/gsd/prompt-validation.ts +157 -0
  1294. package/src/resources/extensions/gsd/prompts/add-tests.md +36 -0
  1295. package/src/resources/extensions/gsd/prompts/complete-milestone.md +91 -0
  1296. package/src/resources/extensions/gsd/prompts/complete-slice.md +49 -0
  1297. package/src/resources/extensions/gsd/prompts/debug-diagnose.md +27 -0
  1298. package/src/resources/extensions/gsd/prompts/debug-session-manager.md +80 -0
  1299. package/src/resources/extensions/gsd/prompts/discuss-headless.md +252 -0
  1300. package/src/resources/extensions/gsd/prompts/discuss.md +368 -0
  1301. package/src/resources/extensions/gsd/prompts/doctor-heal.md +31 -0
  1302. package/src/resources/extensions/gsd/prompts/execute-task.md +73 -0
  1303. package/src/resources/extensions/gsd/prompts/forensics.md +155 -0
  1304. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +32 -0
  1305. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +116 -0
  1306. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +113 -0
  1307. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +99 -0
  1308. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +74 -0
  1309. package/src/resources/extensions/gsd/prompts/guided-research-decision.md +70 -0
  1310. package/src/resources/extensions/gsd/prompts/guided-research-project.md +102 -0
  1311. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +15 -0
  1312. package/src/resources/extensions/gsd/prompts/guided-resume-task.md +1 -0
  1313. package/src/resources/extensions/gsd/prompts/guided-workflow-preferences.md +68 -0
  1314. package/src/resources/extensions/gsd/prompts/heal-skill.md +45 -0
  1315. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +28 -0
  1316. package/src/resources/extensions/gsd/prompts/plan-milestone.md +114 -0
  1317. package/src/resources/extensions/gsd/prompts/plan-slice.md +55 -0
  1318. package/src/resources/extensions/gsd/prompts/queue.md +128 -0
  1319. package/src/resources/extensions/gsd/prompts/quick-task.md +40 -0
  1320. package/src/resources/extensions/gsd/prompts/reactive-execute.md +44 -0
  1321. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +68 -0
  1322. package/src/resources/extensions/gsd/prompts/refine-slice.md +79 -0
  1323. package/src/resources/extensions/gsd/prompts/replan-slice.md +39 -0
  1324. package/src/resources/extensions/gsd/prompts/research-milestone.md +47 -0
  1325. package/src/resources/extensions/gsd/prompts/research-slice.md +58 -0
  1326. package/src/resources/extensions/gsd/prompts/rethink.md +95 -0
  1327. package/src/resources/extensions/gsd/prompts/review-migration.md +66 -0
  1328. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +33 -0
  1329. package/src/resources/extensions/gsd/prompts/run-uat.md +89 -0
  1330. package/src/resources/extensions/gsd/prompts/scan.md +79 -0
  1331. package/src/resources/extensions/gsd/prompts/system.md +180 -0
  1332. package/src/resources/extensions/gsd/prompts/triage-captures.md +68 -0
  1333. package/src/resources/extensions/gsd/prompts/validate-milestone.md +88 -0
  1334. package/src/resources/extensions/gsd/prompts/workflow-oneshot.md +26 -0
  1335. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  1336. package/src/resources/extensions/gsd/prompts/worktree-merge.md +125 -0
  1337. package/src/resources/extensions/gsd/provider-error-pause.ts +49 -0
  1338. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  1339. package/src/resources/extensions/gsd/python-resolver.ts +76 -0
  1340. package/src/resources/extensions/gsd/queue-order.ts +235 -0
  1341. package/src/resources/extensions/gsd/queue-reorder-ui.ts +295 -0
  1342. package/src/resources/extensions/gsd/quick.ts +297 -0
  1343. package/src/resources/extensions/gsd/reactive-graph.ts +337 -0
  1344. package/src/resources/extensions/gsd/recovery-classification.ts +139 -0
  1345. package/src/resources/extensions/gsd/repo-identity.ts +683 -0
  1346. package/src/resources/extensions/gsd/reports.ts +505 -0
  1347. package/src/resources/extensions/gsd/repository-registry.ts +108 -0
  1348. package/src/resources/extensions/gsd/rethink.ts +164 -0
  1349. package/src/resources/extensions/gsd/roadmap-mutations.ts +134 -0
  1350. package/src/resources/extensions/gsd/roadmap-slices.ts +294 -0
  1351. package/src/resources/extensions/gsd/root-write-leak-guard.ts +101 -0
  1352. package/src/resources/extensions/gsd/routing-history.ts +286 -0
  1353. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  1354. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  1355. package/src/resources/extensions/gsd/run-manager.ts +214 -0
  1356. package/src/resources/extensions/gsd/safe-fs.ts +48 -0
  1357. package/src/resources/extensions/gsd/safety/content-validator.ts +98 -0
  1358. package/src/resources/extensions/gsd/safety/destructive-guard.ts +49 -0
  1359. package/src/resources/extensions/gsd/safety/evidence-collector.ts +265 -0
  1360. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +155 -0
  1361. package/src/resources/extensions/gsd/safety/file-change-validator.ts +124 -0
  1362. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +130 -0
  1363. package/src/resources/extensions/gsd/safety/safety-harness.ts +114 -0
  1364. package/src/resources/extensions/gsd/schemas/__fixtures__/valid-project.md +26 -0
  1365. package/src/resources/extensions/gsd/schemas/__fixtures__/valid-requirements.md +57 -0
  1366. package/src/resources/extensions/gsd/schemas/__fixtures__/valid-roadmap.md +19 -0
  1367. package/src/resources/extensions/gsd/schemas/parsers.ts +346 -0
  1368. package/src/resources/extensions/gsd/schemas/validate.ts +452 -0
  1369. package/src/resources/extensions/gsd/service-tier.ts +199 -0
  1370. package/src/resources/extensions/gsd/session-forensics.ts +580 -0
  1371. package/src/resources/extensions/gsd/session-lock.ts +732 -0
  1372. package/src/resources/extensions/gsd/session-model-override.ts +36 -0
  1373. package/src/resources/extensions/gsd/session-status-io.ts +179 -0
  1374. package/src/resources/extensions/gsd/setup-catalog.ts +105 -0
  1375. package/src/resources/extensions/gsd/shortcut-defs.ts +56 -0
  1376. package/src/resources/extensions/gsd/skill-catalog.ts +1088 -0
  1377. package/src/resources/extensions/gsd/skill-discovery.ts +157 -0
  1378. package/src/resources/extensions/gsd/skill-health.ts +422 -0
  1379. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  1380. package/src/resources/extensions/gsd/skill-telemetry.ts +141 -0
  1381. package/src/resources/extensions/gsd/skills/gsd-headless/SKILL.md +242 -0
  1382. package/src/resources/extensions/gsd/skills/gsd-headless/references/answer-injection.md +83 -0
  1383. package/src/resources/extensions/gsd/skills/gsd-headless/references/commands.md +64 -0
  1384. package/src/resources/extensions/gsd/skills/gsd-headless/references/multi-session.md +176 -0
  1385. package/src/resources/extensions/gsd/slice-cadence.ts +411 -0
  1386. package/src/resources/extensions/gsd/slice-parallel-conflict.ts +86 -0
  1387. package/src/resources/extensions/gsd/slice-parallel-eligibility.ts +73 -0
  1388. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +913 -0
  1389. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  1390. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +172 -0
  1391. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +417 -0
  1392. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +66 -0
  1393. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +101 -0
  1394. package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +68 -0
  1395. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +185 -0
  1396. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +46 -0
  1397. package/src/resources/extensions/gsd/state-reconciliation/errors.ts +67 -0
  1398. package/src/resources/extensions/gsd/state-reconciliation/index.ts +142 -0
  1399. package/src/resources/extensions/gsd/state-reconciliation/registry.ts +27 -0
  1400. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +65 -0
  1401. package/src/resources/extensions/gsd/state-reconciliation/types.ts +83 -0
  1402. package/src/resources/extensions/gsd/state-reconciliation.ts +25 -0
  1403. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  1404. package/src/resources/extensions/gsd/state.ts +1730 -0
  1405. package/src/resources/extensions/gsd/status-guards.ts +41 -0
  1406. package/src/resources/extensions/gsd/structured-data-formatter.ts +146 -0
  1407. package/src/resources/extensions/gsd/sync-lock.ts +152 -0
  1408. package/src/resources/extensions/gsd/templates/PREFERENCES.md +101 -0
  1409. package/src/resources/extensions/gsd/templates/context.md +108 -0
  1410. package/src/resources/extensions/gsd/templates/decisions.md +8 -0
  1411. package/src/resources/extensions/gsd/templates/knowledge.md +19 -0
  1412. package/src/resources/extensions/gsd/templates/milestone-summary.md +81 -0
  1413. package/src/resources/extensions/gsd/templates/milestone-validation.md +74 -0
  1414. package/src/resources/extensions/gsd/templates/plan.md +152 -0
  1415. package/src/resources/extensions/gsd/templates/project.md +41 -0
  1416. package/src/resources/extensions/gsd/templates/reassessment.md +29 -0
  1417. package/src/resources/extensions/gsd/templates/requirements.md +81 -0
  1418. package/src/resources/extensions/gsd/templates/research.md +79 -0
  1419. package/src/resources/extensions/gsd/templates/roadmap.md +131 -0
  1420. package/src/resources/extensions/gsd/templates/runtime.md +21 -0
  1421. package/src/resources/extensions/gsd/templates/secrets-manifest.md +22 -0
  1422. package/src/resources/extensions/gsd/templates/slice-context.md +58 -0
  1423. package/src/resources/extensions/gsd/templates/slice-summary.md +108 -0
  1424. package/src/resources/extensions/gsd/templates/state.md +17 -0
  1425. package/src/resources/extensions/gsd/templates/task-plan.md +95 -0
  1426. package/src/resources/extensions/gsd/templates/task-summary.md +66 -0
  1427. package/src/resources/extensions/gsd/templates/uat.md +54 -0
  1428. package/src/resources/extensions/gsd/tests/active-milestone-id-guard.test.ts +91 -0
  1429. package/src/resources/extensions/gsd/tests/activity-log.test.ts +175 -0
  1430. package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +80 -0
  1431. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +296 -0
  1432. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +145 -0
  1433. package/src/resources/extensions/gsd/tests/artifact-validators.test.ts +524 -0
  1434. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +143 -0
  1435. package/src/resources/extensions/gsd/tests/ask-user-questions-dedup.test.ts +120 -0
  1436. package/src/resources/extensions/gsd/tests/atomic-write.test.ts +144 -0
  1437. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +47 -0
  1438. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +89 -0
  1439. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +62 -0
  1440. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +807 -0
  1441. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +457 -0
  1442. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +289 -0
  1443. package/src/resources/extensions/gsd/tests/auto-loop-no-copy-artifacts.test.ts +72 -0
  1444. package/src/resources/extensions/gsd/tests/auto-loop-symlink-worktree.test.ts +190 -0
  1445. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +5503 -0
  1446. package/src/resources/extensions/gsd/tests/auto-migrating-recovery.test.ts +63 -0
  1447. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +61 -0
  1448. package/src/resources/extensions/gsd/tests/auto-mode-guards.test.ts +79 -0
  1449. package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
  1450. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  1451. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +479 -0
  1452. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +1300 -0
  1453. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +76 -0
  1454. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +103 -0
  1455. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +759 -0
  1456. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +390 -0
  1457. package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +32 -0
  1458. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +60 -0
  1459. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +218 -0
  1460. package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +66 -0
  1461. package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +74 -0
  1462. package/src/resources/extensions/gsd/tests/auto-prompts-fallback.test.ts +35 -0
  1463. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +1773 -0
  1464. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +48 -0
  1465. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +64 -0
  1466. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +98 -0
  1467. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +59 -0
  1468. package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +277 -0
  1469. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +348 -0
  1470. package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +45 -0
  1471. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +61 -0
  1472. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +27 -0
  1473. package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +26 -0
  1474. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +175 -0
  1475. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +161 -0
  1476. package/src/resources/extensions/gsd/tests/auto-start-project-milestone-reconcile.test.ts +49 -0
  1477. package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +32 -0
  1478. package/src/resources/extensions/gsd/tests/auto-start-validation-block.test.ts +52 -0
  1479. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +19 -0
  1480. package/src/resources/extensions/gsd/tests/auto-status-message.test.ts +46 -0
  1481. package/src/resources/extensions/gsd/tests/auto-stop-notification.test.ts +31 -0
  1482. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +70 -0
  1483. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +54 -0
  1484. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +68 -0
  1485. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +106 -0
  1486. package/src/resources/extensions/gsd/tests/auto-workers.test.ts +134 -0
  1487. package/src/resources/extensions/gsd/tests/auto-worktree-auto-resolve.test.ts +80 -0
  1488. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +244 -0
  1489. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +199 -0
  1490. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +171 -0
  1491. package/src/resources/extensions/gsd/tests/autocomplete-regressions-1675.test.ts +143 -0
  1492. package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
  1493. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
  1494. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +23 -0
  1495. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  1496. package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +92 -0
  1497. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  1498. package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +147 -0
  1499. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +77 -0
  1500. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  1501. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +290 -0
  1502. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  1503. package/src/resources/extensions/gsd/tests/capability-router.test.ts +371 -0
  1504. package/src/resources/extensions/gsd/tests/captures.test.ts +524 -0
  1505. package/src/resources/extensions/gsd/tests/check-auto-start-pending-gate.test.ts +203 -0
  1506. package/src/resources/extensions/gsd/tests/check-auto-start-ready-guard.test.ts +148 -0
  1507. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +87 -0
  1508. package/src/resources/extensions/gsd/tests/claude-import-marketplace-discovery.test.ts +191 -0
  1509. package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +350 -0
  1510. package/src/resources/extensions/gsd/tests/claude-skill-dirs.test.ts +51 -0
  1511. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +509 -0
  1512. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +76 -0
  1513. package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
  1514. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  1515. package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +101 -0
  1516. package/src/resources/extensions/gsd/tests/cmux.test.ts +333 -0
  1517. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +669 -0
  1518. package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +43 -0
  1519. package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +506 -0
  1520. package/src/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
  1521. package/src/resources/extensions/gsd/tests/command-queue.test.ts +141 -0
  1522. package/src/resources/extensions/gsd/tests/commands-backlog.test.ts +158 -0
  1523. package/src/resources/extensions/gsd/tests/commands-config.test.ts +31 -0
  1524. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +188 -0
  1525. package/src/resources/extensions/gsd/tests/commands-dispatcher-validation-block.test.ts +178 -0
  1526. package/src/resources/extensions/gsd/tests/commands-do.test.ts +175 -0
  1527. package/src/resources/extensions/gsd/tests/commands-eval-review.test.ts +612 -0
  1528. package/src/resources/extensions/gsd/tests/commands-extensions-version-compare.test.ts +58 -0
  1529. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +663 -0
  1530. package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +46 -0
  1531. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  1532. package/src/resources/extensions/gsd/tests/commands-pr-branch.test.ts +68 -0
  1533. package/src/resources/extensions/gsd/tests/commands-scan.test.ts +351 -0
  1534. package/src/resources/extensions/gsd/tests/commands-session-report.test.ts +82 -0
  1535. package/src/resources/extensions/gsd/tests/commands-ship-eval-warn.test.ts +156 -0
  1536. package/src/resources/extensions/gsd/tests/commands-ship.test.ts +71 -0
  1537. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +439 -0
  1538. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +311 -0
  1539. package/src/resources/extensions/gsd/tests/commands-worktree-clean.test.ts +48 -0
  1540. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +136 -0
  1541. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +366 -0
  1542. package/src/resources/extensions/gsd/tests/complete-milestone-prompt-rendering.test.ts +47 -0
  1543. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +743 -0
  1544. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +193 -0
  1545. package/src/resources/extensions/gsd/tests/complete-slice-gate-closure.test.ts +167 -0
  1546. package/src/resources/extensions/gsd/tests/complete-slice-prompt-task-summary-layout.test.ts +18 -0
  1547. package/src/resources/extensions/gsd/tests/complete-slice-string-coercion.test.ts +247 -0
  1548. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +156 -0
  1549. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +556 -0
  1550. package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +50 -0
  1551. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +105 -0
  1552. package/src/resources/extensions/gsd/tests/complete-task.test.ts +513 -0
  1553. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +84 -0
  1554. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +61 -0
  1555. package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
  1556. package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +206 -0
  1557. package/src/resources/extensions/gsd/tests/component-loader.test.ts +582 -0
  1558. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  1559. package/src/resources/extensions/gsd/tests/context-budget.test.ts +389 -0
  1560. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  1561. package/src/resources/extensions/gsd/tests/context-masker.test.ts +122 -0
  1562. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  1563. package/src/resources/extensions/gsd/tests/context-store.test.ts +715 -0
  1564. package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +185 -0
  1565. package/src/resources/extensions/gsd/tests/cost-projection.test.ts +120 -0
  1566. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +294 -0
  1567. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +331 -0
  1568. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +709 -0
  1569. package/src/resources/extensions/gsd/tests/current-directory-root-homedir-fallback.test.ts +63 -0
  1570. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +902 -0
  1571. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +415 -0
  1572. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +139 -0
  1573. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +483 -0
  1574. package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
  1575. package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +360 -0
  1576. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +23 -0
  1577. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +110 -0
  1578. package/src/resources/extensions/gsd/tests/db-adapter.test.ts +82 -0
  1579. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  1580. package/src/resources/extensions/gsd/tests/db-base-schema.test.ts +62 -0
  1581. package/src/resources/extensions/gsd/tests/db-connection-cache.test.ts +60 -0
  1582. package/src/resources/extensions/gsd/tests/db-coordination-schema.test.ts +39 -0
  1583. package/src/resources/extensions/gsd/tests/db-decision-requirement-rows.test.ts +135 -0
  1584. package/src/resources/extensions/gsd/tests/db-gate-rows.test.ts +53 -0
  1585. package/src/resources/extensions/gsd/tests/db-lightweight-query-rows.test.ts +45 -0
  1586. package/src/resources/extensions/gsd/tests/db-memory-fts-schema.test.ts +86 -0
  1587. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +105 -0
  1588. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  1589. package/src/resources/extensions/gsd/tests/db-migration-steps.test.ts +159 -0
  1590. package/src/resources/extensions/gsd/tests/db-milestone-artifact-rows.test.ts +53 -0
  1591. package/src/resources/extensions/gsd/tests/db-open-state.test.ts +56 -0
  1592. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +95 -0
  1593. package/src/resources/extensions/gsd/tests/db-provider.test.ts +105 -0
  1594. package/src/resources/extensions/gsd/tests/db-runtime-kv-schema.test.ts +37 -0
  1595. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +115 -0
  1596. package/src/resources/extensions/gsd/tests/db-task-slice-rows.test.ts +130 -0
  1597. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +110 -0
  1598. package/src/resources/extensions/gsd/tests/db-verification-evidence-schema.test.ts +76 -0
  1599. package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
  1600. package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
  1601. package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
  1602. package/src/resources/extensions/gsd/tests/db-writer.test.ts +980 -0
  1603. package/src/resources/extensions/gsd/tests/debug-command-handler.test.ts +942 -0
  1604. package/src/resources/extensions/gsd/tests/debug-command-lifecycle.integration.test.ts +1229 -0
  1605. package/src/resources/extensions/gsd/tests/debug-logger.test.ts +187 -0
  1606. package/src/resources/extensions/gsd/tests/debug-session-store.test.ts +565 -0
  1607. package/src/resources/extensions/gsd/tests/decision-scope-cascade.test.ts +370 -0
  1608. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  1609. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  1610. package/src/resources/extensions/gsd/tests/deep-mode-integration.test.ts +406 -0
  1611. package/src/resources/extensions/gsd/tests/deep-planning-mode-dispatch.test.ts +923 -0
  1612. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +1705 -0
  1613. package/src/resources/extensions/gsd/tests/deep-project-setup-policy.test.ts +193 -0
  1614. package/src/resources/extensions/gsd/tests/defer-milestone-stamp.test.ts +30 -0
  1615. package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +65 -0
  1616. package/src/resources/extensions/gsd/tests/deferred-slice-dispatch.test.ts +203 -0
  1617. package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
  1618. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +762 -0
  1619. package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
  1620. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +514 -0
  1621. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +133 -0
  1622. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +1388 -0
  1623. package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +641 -0
  1624. package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +313 -0
  1625. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +558 -0
  1626. package/src/resources/extensions/gsd/tests/derive-state.test.ts +1049 -0
  1627. package/src/resources/extensions/gsd/tests/detect-stuck-respects-retry.test.ts +173 -0
  1628. package/src/resources/extensions/gsd/tests/detection.test.ts +1367 -0
  1629. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +314 -0
  1630. package/src/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
  1631. package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
  1632. package/src/resources/extensions/gsd/tests/discuss-cold-start-db-open.test.ts +71 -0
  1633. package/src/resources/extensions/gsd/tests/discuss-command-targeting-5471.test.ts +125 -0
  1634. package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +62 -0
  1635. package/src/resources/extensions/gsd/tests/discuss-headless-rendering.test.ts +37 -0
  1636. package/src/resources/extensions/gsd/tests/discuss-incremental-persistence.test.ts +45 -0
  1637. package/src/resources/extensions/gsd/tests/discuss-milestone-structured-questions.test.ts +115 -0
  1638. package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +15 -0
  1639. package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +170 -0
  1640. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +35 -0
  1641. package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +138 -0
  1642. package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
  1643. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +276 -0
  1644. package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +43 -0
  1645. package/src/resources/extensions/gsd/tests/dispatch-guard-summary-db-mismatch.test.ts +77 -0
  1646. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +446 -0
  1647. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +279 -0
  1648. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +358 -0
  1649. package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +206 -0
  1650. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +55 -0
  1651. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +112 -0
  1652. package/src/resources/extensions/gsd/tests/doctor-empty-worktree.test.ts +65 -0
  1653. package/src/resources/extensions/gsd/tests/doctor-fix-flag.test.ts +92 -0
  1654. package/src/resources/extensions/gsd/tests/doctor-forensics-db-open-regression.test.ts +50 -0
  1655. package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
  1656. package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
  1657. package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +828 -0
  1658. package/src/resources/extensions/gsd/tests/doctor-runtime-checks.test.ts +47 -0
  1659. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +43 -0
  1660. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +36 -0
  1661. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +149 -0
  1662. package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
  1663. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  1664. package/src/resources/extensions/gsd/tests/enhanced-verification-integration.test.ts +531 -0
  1665. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +530 -0
  1666. package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
  1667. package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +32 -0
  1668. package/src/resources/extensions/gsd/tests/escalation.test.ts +819 -0
  1669. package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +53 -0
  1670. package/src/resources/extensions/gsd/tests/eval-review-schema.test.ts +282 -0
  1671. package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
  1672. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +121 -0
  1673. package/src/resources/extensions/gsd/tests/exec-history.test.ts +252 -0
  1674. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +407 -0
  1675. package/src/resources/extensions/gsd/tests/execute-summary-save-empty-project.test.ts +109 -0
  1676. package/src/resources/extensions/gsd/tests/execute-task-prompt-existing-artifact-guard.test.ts +33 -0
  1677. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +62 -0
  1678. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +187 -0
  1679. package/src/resources/extensions/gsd/tests/exit-command.test.ts +101 -0
  1680. package/src/resources/extensions/gsd/tests/export-html-all.test.ts +116 -0
  1681. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +387 -0
  1682. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +164 -0
  1683. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +144 -0
  1684. package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +43 -0
  1685. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  1686. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +108 -0
  1687. package/src/resources/extensions/gsd/tests/file-lock.test.ts +177 -0
  1688. package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +18 -0
  1689. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +151 -0
  1690. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +103 -0
  1691. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
  1692. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  1693. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  1694. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  1695. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  1696. package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +278 -0
  1697. package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +305 -0
  1698. package/src/resources/extensions/gsd/tests/forensics-error-filter.test.ts +121 -0
  1699. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  1700. package/src/resources/extensions/gsd/tests/forensics-prompt-rendering.test.ts +36 -0
  1701. package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +215 -0
  1702. package/src/resources/extensions/gsd/tests/format-shortcut.test.ts +100 -0
  1703. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +298 -0
  1704. package/src/resources/extensions/gsd/tests/fresh-run-ui.test.ts +65 -0
  1705. package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +34 -0
  1706. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
  1707. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
  1708. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
  1709. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +216 -0
  1710. package/src/resources/extensions/gsd/tests/gate-registry.test.ts +140 -0
  1711. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  1712. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +156 -0
  1713. package/src/resources/extensions/gsd/tests/git-checkpoint.test.ts +103 -0
  1714. package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +77 -0
  1715. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +91 -0
  1716. package/src/resources/extensions/gsd/tests/graph-context.test.ts +337 -0
  1717. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  1718. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +134 -0
  1719. package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
  1720. package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
  1721. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1210 -0
  1722. package/src/resources/extensions/gsd/tests/gsd-home.test.ts +43 -0
  1723. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +114 -0
  1724. package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +95 -0
  1725. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +440 -0
  1726. package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
  1727. package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +149 -0
  1728. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +445 -0
  1729. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +146 -0
  1730. package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +43 -0
  1731. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +43 -0
  1732. package/src/resources/extensions/gsd/tests/guided-discuss-requirements-prompt-rendering.test.ts +45 -0
  1733. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  1734. package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
  1735. package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +147 -0
  1736. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +219 -0
  1737. package/src/resources/extensions/gsd/tests/guided-flow-state-rebuild.test.ts +140 -0
  1738. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  1739. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  1740. package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
  1741. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +130 -0
  1742. package/src/resources/extensions/gsd/tests/header-renderer.test.ts +40 -0
  1743. package/src/resources/extensions/gsd/tests/headless-answers.test.ts +350 -0
  1744. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +127 -0
  1745. package/src/resources/extensions/gsd/tests/headless-query.test.ts +184 -0
  1746. package/src/resources/extensions/gsd/tests/health-widget.test.ts +251 -0
  1747. package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
  1748. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +56 -0
  1749. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +103 -0
  1750. package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
  1751. package/src/resources/extensions/gsd/tests/in-flight-tool-tracking.test.ts +32 -0
  1752. package/src/resources/extensions/gsd/tests/infra-error.test.ts +129 -0
  1753. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +189 -0
  1754. package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +275 -0
  1755. package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +16 -0
  1756. package/src/resources/extensions/gsd/tests/init-wizard.test.ts +239 -0
  1757. package/src/resources/extensions/gsd/tests/insert-slice-no-wipe.test.ts +88 -0
  1758. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +199 -0
  1759. package/src/resources/extensions/gsd/tests/integration/atomic-task-closeout.test.ts +72 -0
  1760. package/src/resources/extensions/gsd/tests/integration/auto-preflight.test.ts +38 -0
  1761. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +966 -0
  1762. package/src/resources/extensions/gsd/tests/integration/auto-secrets-gate.test.ts +194 -0
  1763. package/src/resources/extensions/gsd/tests/integration/auto-stash-merge.test.ts +121 -0
  1764. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +964 -0
  1765. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +430 -0
  1766. package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +256 -0
  1767. package/src/resources/extensions/gsd/tests/integration/continue-here.test.ts +281 -0
  1768. package/src/resources/extensions/gsd/tests/integration/doctor-completion-deferral.test.ts +88 -0
  1769. package/src/resources/extensions/gsd/tests/integration/doctor-delimiter-fix.test.ts +83 -0
  1770. package/src/resources/extensions/gsd/tests/integration/doctor-enhancements.test.ts +243 -0
  1771. package/src/resources/extensions/gsd/tests/integration/doctor-environment-worktree.test.ts +164 -0
  1772. package/src/resources/extensions/gsd/tests/integration/doctor-environment.test.ts +403 -0
  1773. package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
  1774. package/src/resources/extensions/gsd/tests/integration/doctor-fixlevel.test.ts +263 -0
  1775. package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +90 -0
  1776. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +954 -0
  1777. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +431 -0
  1778. package/src/resources/extensions/gsd/tests/integration/doctor-roadmap-summary-atomicity.test.ts +123 -0
  1779. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +549 -0
  1780. package/src/resources/extensions/gsd/tests/integration/doctor.test.ts +612 -0
  1781. package/src/resources/extensions/gsd/tests/integration/e2e-workflow-pipeline-integration.test.ts +476 -0
  1782. package/src/resources/extensions/gsd/tests/integration/feature-branch-lifecycle-integration.test.ts +415 -0
  1783. package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +130 -0
  1784. package/src/resources/extensions/gsd/tests/integration/git-self-heal.test.ts +131 -0
  1785. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +2040 -0
  1786. package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
  1787. package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +257 -0
  1788. package/src/resources/extensions/gsd/tests/integration/headless-command.ts +534 -0
  1789. package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +474 -0
  1790. package/src/resources/extensions/gsd/tests/integration/inherited-repo-home-dir.test.ts +191 -0
  1791. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +274 -0
  1792. package/src/resources/extensions/gsd/tests/integration/integration-mixed-milestones.test.ts +539 -0
  1793. package/src/resources/extensions/gsd/tests/integration/integration-proof.test.ts +634 -0
  1794. package/src/resources/extensions/gsd/tests/integration/merge-cwd-restore.test.ts +169 -0
  1795. package/src/resources/extensions/gsd/tests/integration/merge-preserve-worktree-on-preteardown-error.test.ts +77 -0
  1796. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +405 -0
  1797. package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +119 -0
  1798. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +669 -0
  1799. package/src/resources/extensions/gsd/tests/integration/parallel-workers-multi-milestone-e2e.test.ts +337 -0
  1800. package/src/resources/extensions/gsd/tests/integration/paths.test.ts +98 -0
  1801. package/src/resources/extensions/gsd/tests/integration/plugin-importer-live.test.ts +481 -0
  1802. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +161 -0
  1803. package/src/resources/extensions/gsd/tests/integration/queue-reorder-e2e.test.ts +335 -0
  1804. package/src/resources/extensions/gsd/tests/integration/quick-branch-lifecycle.test.ts +253 -0
  1805. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +689 -0
  1806. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +1356 -0
  1807. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +980 -0
  1808. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +832 -0
  1809. package/src/resources/extensions/gsd/tests/integration/test-isolation.ts +53 -0
  1810. package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +341 -0
  1811. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +369 -0
  1812. package/src/resources/extensions/gsd/tests/integration/worktree-e2e.test.ts +248 -0
  1813. package/src/resources/extensions/gsd/tests/integration-edge.test.ts +223 -0
  1814. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +71 -0
  1815. package/src/resources/extensions/gsd/tests/interactive-tool-idle-exemption.test.ts +119 -0
  1816. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +241 -0
  1817. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +180 -0
  1818. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +19 -0
  1819. package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
  1820. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  1821. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +1473 -0
  1822. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +179 -0
  1823. package/src/resources/extensions/gsd/tests/journal.test.ts +373 -0
  1824. package/src/resources/extensions/gsd/tests/json-persistence-atomic.test.ts +183 -0
  1825. package/src/resources/extensions/gsd/tests/key-manager.test.ts +501 -0
  1826. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  1827. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  1828. package/src/resources/extensions/gsd/tests/knowledge.test.ts +434 -0
  1829. package/src/resources/extensions/gsd/tests/lazy-pi-tui-import.test.ts +53 -0
  1830. package/src/resources/extensions/gsd/tests/lease-conflict-notice.test.ts +38 -0
  1831. package/src/resources/extensions/gsd/tests/legacy-component-format-telemetry.test.ts +62 -0
  1832. package/src/resources/extensions/gsd/tests/legacy-telemetry.test.ts +144 -0
  1833. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  1834. package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
  1835. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +274 -0
  1836. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1292 -0
  1837. package/src/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
  1838. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +47 -0
  1839. package/src/resources/extensions/gsd/tests/mcp-filter.test.ts +287 -0
  1840. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +89 -0
  1841. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +183 -0
  1842. package/src/resources/extensions/gsd/tests/md-importer.test.ts +416 -0
  1843. package/src/resources/extensions/gsd/tests/measurement.test.ts +531 -0
  1844. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  1845. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  1846. package/src/resources/extensions/gsd/tests/memory-embeddings.test.ts +213 -0
  1847. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +244 -0
  1848. package/src/resources/extensions/gsd/tests/memory-ingest.test.ts +153 -0
  1849. package/src/resources/extensions/gsd/tests/memory-leak-guards.test.ts +91 -0
  1850. package/src/resources/extensions/gsd/tests/memory-maintenance.test.ts +107 -0
  1851. package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +79 -0
  1852. package/src/resources/extensions/gsd/tests/memory-relations.test.ts +175 -0
  1853. package/src/resources/extensions/gsd/tests/memory-store.test.ts +460 -0
  1854. package/src/resources/extensions/gsd/tests/memory-tools.test.ts +327 -0
  1855. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +303 -0
  1856. package/src/resources/extensions/gsd/tests/merge-db-cycle.test.ts +179 -0
  1857. package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +105 -0
  1858. package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
  1859. package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
  1860. package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
  1861. package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
  1862. package/src/resources/extensions/gsd/tests/metrics-milestone-scope.test.ts +64 -0
  1863. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
  1864. package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
  1865. package/src/resources/extensions/gsd/tests/metrics.test.ts +519 -0
  1866. package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +165 -0
  1867. package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
  1868. package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +782 -0
  1869. package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +242 -0
  1870. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +651 -0
  1871. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +448 -0
  1872. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +347 -0
  1873. package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +361 -0
  1874. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +135 -0
  1875. package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
  1876. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +73 -0
  1877. package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +152 -0
  1878. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +364 -0
  1879. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +68 -0
  1880. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +206 -0
  1881. package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
  1882. package/src/resources/extensions/gsd/tests/milestone-status-tool.test.ts +202 -0
  1883. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  1884. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +122 -0
  1885. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +111 -0
  1886. package/src/resources/extensions/gsd/tests/model-isolation.test.ts +305 -0
  1887. package/src/resources/extensions/gsd/tests/model-router.test.ts +990 -0
  1888. package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +90 -0
  1889. package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +278 -0
  1890. package/src/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
  1891. package/src/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
  1892. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +228 -0
  1893. package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
  1894. package/src/resources/extensions/gsd/tests/native-has-changes-cache.test.ts +61 -0
  1895. package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +55 -0
  1896. package/src/resources/extensions/gsd/tests/next-milestone-id.test.ts +23 -0
  1897. package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +200 -0
  1898. package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +50 -0
  1899. package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +129 -0
  1900. package/src/resources/extensions/gsd/tests/notification-store.test.ts +325 -0
  1901. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +87 -0
  1902. package/src/resources/extensions/gsd/tests/notifications-handler.test.ts +134 -0
  1903. package/src/resources/extensions/gsd/tests/notifications.test.ts +134 -0
  1904. package/src/resources/extensions/gsd/tests/onboarding-state.test.ts +105 -0
  1905. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +159 -0
  1906. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +144 -0
  1907. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  1908. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +374 -0
  1909. package/src/resources/extensions/gsd/tests/overrides.test.ts +124 -0
  1910. package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +330 -0
  1911. package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +164 -0
  1912. package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +273 -0
  1913. package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +170 -0
  1914. package/src/resources/extensions/gsd/tests/parallel-milestone-isolation.test.ts +106 -0
  1915. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +114 -0
  1916. package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +736 -0
  1917. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  1918. package/src/resources/extensions/gsd/tests/parallel-orchestrator-zombie-cleanup.test.ts +332 -0
  1919. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +308 -0
  1920. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +158 -0
  1921. package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +226 -0
  1922. package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +199 -0
  1923. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +157 -0
  1924. package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +253 -0
  1925. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +420 -0
  1926. package/src/resources/extensions/gsd/tests/parsers.test.ts +1892 -0
  1927. package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
  1928. package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
  1929. package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
  1930. package/src/resources/extensions/gsd/tests/paused-session-via-db.test.ts +121 -0
  1931. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +144 -0
  1932. package/src/resources/extensions/gsd/tests/phantom-ghost-detection.test.ts +42 -0
  1933. package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +24 -0
  1934. package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +83 -0
  1935. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +126 -0
  1936. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +404 -0
  1937. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
  1938. package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +102 -0
  1939. package/src/resources/extensions/gsd/tests/plan-milestone-boundary-map-preservation.test.ts +114 -0
  1940. package/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts +48 -0
  1941. package/src/resources/extensions/gsd/tests/plan-milestone-rendering.test.ts +45 -0
  1942. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  1943. package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +71 -0
  1944. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +349 -0
  1945. package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +474 -0
  1946. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +306 -0
  1947. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +712 -0
  1948. package/src/resources/extensions/gsd/tests/plan-task.test.ts +183 -0
  1949. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
  1950. package/src/resources/extensions/gsd/tests/planning-depth-setter.test.ts +172 -0
  1951. package/src/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
  1952. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +536 -0
  1953. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +1065 -0
  1954. package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
  1955. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +25 -0
  1956. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +300 -0
  1957. package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +567 -0
  1958. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  1959. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  1960. package/src/resources/extensions/gsd/tests/pr-evidence.test.ts +79 -0
  1961. package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +149 -0
  1962. package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +275 -0
  1963. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +2246 -0
  1964. package/src/resources/extensions/gsd/tests/pre-execution-fail-closed.test.ts +244 -0
  1965. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +708 -0
  1966. package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
  1967. package/src/resources/extensions/gsd/tests/preferences-mcp.test.ts +128 -0
  1968. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +118 -0
  1969. package/src/resources/extensions/gsd/tests/preferences.test.ts +1314 -0
  1970. package/src/resources/extensions/gsd/tests/preflight-context-draft-filter.test.ts +115 -0
  1971. package/src/resources/extensions/gsd/tests/prefs-missing-models-crash.test.ts +148 -0
  1972. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +222 -0
  1973. package/src/resources/extensions/gsd/tests/process-task-path.test.ts +51 -0
  1974. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +620 -0
  1975. package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
  1976. package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +35 -0
  1977. package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +56 -0
  1978. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +277 -0
  1979. package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +677 -0
  1980. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +326 -0
  1981. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +574 -0
  1982. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +387 -0
  1983. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  1984. package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
  1985. package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
  1986. package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
  1987. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  1988. package/src/resources/extensions/gsd/tests/prompt-ordering.test.ts +296 -0
  1989. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  1990. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +91 -0
  1991. package/src/resources/extensions/gsd/tests/prompt-system-gate-coverage.test.ts +208 -0
  1992. package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
  1993. package/src/resources/extensions/gsd/tests/prompts-no-gitignored-test-refs.test.ts +56 -0
  1994. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +744 -0
  1995. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  1996. package/src/resources/extensions/gsd/tests/python-resolver.test.ts +131 -0
  1997. package/src/resources/extensions/gsd/tests/quality-gates.test.ts +344 -0
  1998. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +51 -0
  1999. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +39 -0
  2000. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +101 -0
  2001. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +166 -0
  2002. package/src/resources/extensions/gsd/tests/queue-order.test.ts +192 -0
  2003. package/src/resources/extensions/gsd/tests/queue-prompt-rendering.test.ts +37 -0
  2004. package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +54 -0
  2005. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +106 -0
  2006. package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +36 -0
  2007. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  2008. package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +61 -0
  2009. package/src/resources/extensions/gsd/tests/rate-limit-model-fallback.test.ts +90 -0
  2010. package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +511 -0
  2011. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +363 -0
  2012. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +728 -0
  2013. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +146 -0
  2014. package/src/resources/extensions/gsd/tests/reassess-detection.test.ts +154 -0
  2015. package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +442 -0
  2016. package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +135 -0
  2017. package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
  2018. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +144 -0
  2019. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +161 -0
  2020. package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +126 -0
  2021. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +252 -0
  2022. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +442 -0
  2023. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +131 -0
  2024. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +197 -0
  2025. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +107 -0
  2026. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +774 -0
  2027. package/src/resources/extensions/gsd/tests/remote-status.test.ts +99 -0
  2028. package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
  2029. package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
  2030. package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
  2031. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +609 -0
  2032. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +258 -0
  2033. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +101 -0
  2034. package/src/resources/extensions/gsd/tests/require-slice-discussion-dispatch.test.ts +170 -0
  2035. package/src/resources/extensions/gsd/tests/requirements.test.ts +110 -0
  2036. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +132 -0
  2037. package/src/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +23 -0
  2038. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +9 -0
  2039. package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +50 -0
  2040. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +65 -0
  2041. package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +102 -0
  2042. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
  2043. package/src/resources/extensions/gsd/tests/retry-diagnostic-reasoning.test.ts +161 -0
  2044. package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +305 -0
  2045. package/src/resources/extensions/gsd/tests/rewrite-count-persist.test.ts +82 -0
  2046. package/src/resources/extensions/gsd/tests/rewrite-docs-abandon-detect.test.ts +195 -0
  2047. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +213 -0
  2048. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +399 -0
  2049. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +464 -0
  2050. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +294 -0
  2051. package/src/resources/extensions/gsd/tests/routing-history.test.ts +229 -0
  2052. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +411 -0
  2053. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  2054. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +151 -0
  2055. package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +94 -0
  2056. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +94 -0
  2057. package/src/resources/extensions/gsd/tests/runtime-kv.test.ts +120 -0
  2058. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +268 -0
  2059. package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
  2060. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
  2061. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  2062. package/src/resources/extensions/gsd/tests/schema-v9-sequence.test.ts +176 -0
  2063. package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +364 -0
  2064. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  2065. package/src/resources/extensions/gsd/tests/service-tier.test.ts +131 -0
  2066. package/src/resources/extensions/gsd/tests/session-forensics-readonly-classification.test.ts +70 -0
  2067. package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +166 -0
  2068. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +379 -0
  2069. package/src/resources/extensions/gsd/tests/session-lock-transient-read.test.ts +224 -0
  2070. package/src/resources/extensions/gsd/tests/session-model-override.test.ts +40 -0
  2071. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +387 -0
  2072. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +304 -0
  2073. package/src/resources/extensions/gsd/tests/shared-wal.test.ts +239 -0
  2074. package/src/resources/extensions/gsd/tests/show-config-command.test.ts +58 -0
  2075. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +182 -0
  2076. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +130 -0
  2077. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +244 -0
  2078. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +180 -0
  2079. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  2080. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +352 -0
  2081. package/src/resources/extensions/gsd/tests/skill-catalog.test.ts +193 -0
  2082. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +126 -0
  2083. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  2084. package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +125 -0
  2085. package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +63 -0
  2086. package/src/resources/extensions/gsd/tests/skipped-validation-completion.test.ts +144 -0
  2087. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +57 -0
  2088. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +301 -0
  2089. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +79 -0
  2090. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +187 -0
  2091. package/src/resources/extensions/gsd/tests/slice-parallel-conflict.test.ts +92 -0
  2092. package/src/resources/extensions/gsd/tests/slice-parallel-eligibility.test.ts +95 -0
  2093. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +348 -0
  2094. package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +124 -0
  2095. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +76 -0
  2096. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +33 -0
  2097. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  2098. package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +29 -0
  2099. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +65 -0
  2100. package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +45 -0
  2101. package/src/resources/extensions/gsd/tests/stale-milestone-id-reservation.test.ts +79 -0
  2102. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +147 -0
  2103. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +49 -0
  2104. package/src/resources/extensions/gsd/tests/stale-worktree-cwd.test.ts +152 -0
  2105. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +148 -0
  2106. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +334 -0
  2107. package/src/resources/extensions/gsd/tests/stash-pop-gsd-conflict.test.ts +203 -0
  2108. package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +442 -0
  2109. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +424 -0
  2110. package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
  2111. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1645 -0
  2112. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +1137 -0
  2113. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  2114. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +42 -0
  2115. package/src/resources/extensions/gsd/tests/status-guards.test.ts +50 -0
  2116. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +123 -0
  2117. package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +95 -0
  2118. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +18 -0
  2119. package/src/resources/extensions/gsd/tests/stop-backtrack.test.ts +216 -0
  2120. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +285 -0
  2121. package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +232 -0
  2122. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +197 -0
  2123. package/src/resources/extensions/gsd/tests/subagent-agent-discovery.test.ts +91 -0
  2124. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +174 -0
  2125. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +226 -0
  2126. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +121 -0
  2127. package/src/resources/extensions/gsd/tests/symlink-extension-discovery.test.ts +125 -0
  2128. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +145 -0
  2129. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +153 -0
  2130. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +40 -0
  2131. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  2132. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +99 -0
  2133. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
  2134. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +98 -0
  2135. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
  2136. package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +128 -0
  2137. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  2138. package/src/resources/extensions/gsd/tests/test-helpers.ts +214 -0
  2139. package/src/resources/extensions/gsd/tests/test-utils.ts +165 -0
  2140. package/src/resources/extensions/gsd/tests/token-cost-display.test.ts +118 -0
  2141. package/src/resources/extensions/gsd/tests/token-counter.test.ts +242 -0
  2142. package/src/resources/extensions/gsd/tests/token-profile.test.ts +100 -0
  2143. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +382 -0
  2144. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +179 -0
  2145. package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +306 -0
  2146. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +211 -0
  2147. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +155 -0
  2148. package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +383 -0
  2149. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +138 -0
  2150. package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +612 -0
  2151. package/src/resources/extensions/gsd/tests/tui-header-lifecycle.test.ts +330 -0
  2152. package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +88 -0
  2153. package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +153 -0
  2154. package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
  2155. package/src/resources/extensions/gsd/tests/unborn-branch.test.ts +85 -0
  2156. package/src/resources/extensions/gsd/tests/undo.test.ts +462 -0
  2157. package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +203 -0
  2158. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +529 -0
  2159. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +462 -0
  2160. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +326 -0
  2161. package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +258 -0
  2162. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +335 -0
  2163. package/src/resources/extensions/gsd/tests/unmerged-milestone-guard.test.ts +112 -0
  2164. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +67 -0
  2165. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +101 -0
  2166. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +245 -0
  2167. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +85 -0
  2168. package/src/resources/extensions/gsd/tests/uok-flags.test.ts +69 -0
  2169. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +145 -0
  2170. package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +241 -0
  2171. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +58 -0
  2172. package/src/resources/extensions/gsd/tests/uok-kernel-path.test.ts +178 -0
  2173. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +163 -0
  2174. package/src/resources/extensions/gsd/tests/uok-model-policy.test.ts +89 -0
  2175. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  2176. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +262 -0
  2177. package/src/resources/extensions/gsd/tests/uok-preferences.test.ts +42 -0
  2178. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  2179. package/src/resources/extensions/gsd/tests/update-command.test.ts +86 -0
  2180. package/src/resources/extensions/gsd/tests/vacuous-truth-slices.test.ts +115 -0
  2181. package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
  2182. package/src/resources/extensions/gsd/tests/validate-directory.test.ts +269 -0
  2183. package/src/resources/extensions/gsd/tests/validate-extension-package.test.ts +168 -0
  2184. package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +21 -0
  2185. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +300 -0
  2186. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +371 -0
  2187. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +766 -0
  2188. package/src/resources/extensions/gsd/tests/validation-block-guard.test.ts +104 -0
  2189. package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +178 -0
  2190. package/src/resources/extensions/gsd/tests/validation.test.ts +72 -0
  2191. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
  2192. package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
  2193. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +601 -0
  2194. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +1265 -0
  2195. package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +112 -0
  2196. package/src/resources/extensions/gsd/tests/verification-retry-policy.test.ts +83 -0
  2197. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  2198. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +204 -0
  2199. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +109 -0
  2200. package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -0
  2201. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +359 -0
  2202. package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +716 -0
  2203. package/src/resources/extensions/gsd/tests/wave1-critical-regressions.test.ts +49 -0
  2204. package/src/resources/extensions/gsd/tests/wave2-events-regressions.test.ts +48 -0
  2205. package/src/resources/extensions/gsd/tests/wave3-session-regressions.test.ts +47 -0
  2206. package/src/resources/extensions/gsd/tests/wave4-write-safety-regressions.test.ts +70 -0
  2207. package/src/resources/extensions/gsd/tests/wave5-consistency-regressions.test.ts +165 -0
  2208. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +97 -0
  2209. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +56 -0
  2210. package/src/resources/extensions/gsd/tests/worker-registry.test.ts +146 -0
  2211. package/src/resources/extensions/gsd/tests/workflow-custom-engine-dispatch-outcome.test.ts +55 -0
  2212. package/src/resources/extensions/gsd/tests/workflow-custom-engine-iteration.test.ts +93 -0
  2213. package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile-outcome.test.ts +108 -0
  2214. package/src/resources/extensions/gsd/tests/workflow-custom-engine-reconcile.test.ts +146 -0
  2215. package/src/resources/extensions/gsd/tests/workflow-custom-engine-retry.test.ts +136 -0
  2216. package/src/resources/extensions/gsd/tests/workflow-custom-engine-verify-outcome.test.ts +95 -0
  2217. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +313 -0
  2218. package/src/resources/extensions/gsd/tests/workflow-dispatch-ledger.test.ts +82 -0
  2219. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
  2220. package/src/resources/extensions/gsd/tests/workflow-install.test.ts +113 -0
  2221. package/src/resources/extensions/gsd/tests/workflow-iteration-completion.test.ts +44 -0
  2222. package/src/resources/extensions/gsd/tests/workflow-journal-reporter.test.ts +49 -0
  2223. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +630 -0
  2224. package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +123 -0
  2225. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +92 -0
  2226. package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +411 -0
  2227. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +336 -0
  2228. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +76 -0
  2229. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +771 -0
  2230. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +91 -0
  2231. package/src/resources/extensions/gsd/tests/workflow-phase-reporter.test.ts +40 -0
  2232. package/src/resources/extensions/gsd/tests/workflow-plugins.test.ts +310 -0
  2233. package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +405 -0
  2234. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  2235. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +91 -0
  2236. package/src/resources/extensions/gsd/tests/workflow-session-lock.test.ts +135 -0
  2237. package/src/resources/extensions/gsd/tests/workflow-sidecar-iteration.test.ts +110 -0
  2238. package/src/resources/extensions/gsd/tests/workflow-sidecar-queue.test.ts +116 -0
  2239. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +198 -0
  2240. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1397 -0
  2241. package/src/resources/extensions/gsd/tests/workflow-turn-reporter.test.ts +87 -0
  2242. package/src/resources/extensions/gsd/tests/workflow-unit-dispatch.test.ts +160 -0
  2243. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +154 -0
  2244. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  2245. package/src/resources/extensions/gsd/tests/workspace-index.test.ts +38 -0
  2246. package/src/resources/extensions/gsd/tests/workspace.test.ts +196 -0
  2247. package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +117 -0
  2248. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +202 -0
  2249. package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +219 -0
  2250. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +165 -0
  2251. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +440 -0
  2252. package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +39 -0
  2253. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  2254. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +207 -0
  2255. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +109 -0
  2256. package/src/resources/extensions/gsd/tests/worktree-health.test.ts +181 -0
  2257. package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +216 -0
  2258. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +397 -0
  2259. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +992 -0
  2260. package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +27 -0
  2261. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +290 -0
  2262. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +110 -0
  2263. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +242 -0
  2264. package/src/resources/extensions/gsd/tests/worktree-post-create-hook.test.ts +165 -0
  2265. package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +180 -0
  2266. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  2267. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +206 -0
  2268. package/src/resources/extensions/gsd/tests/worktree-root-resolution.test.ts +50 -0
  2269. package/src/resources/extensions/gsd/tests/worktree-root.test.ts +69 -0
  2270. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +417 -0
  2271. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +120 -0
  2272. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +228 -0
  2273. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +134 -0
  2274. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +705 -0
  2275. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +156 -0
  2276. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +85 -0
  2277. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +148 -0
  2278. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +283 -0
  2279. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +206 -0
  2280. package/src/resources/extensions/gsd/tests/worktree.test.ts +304 -0
  2281. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +476 -0
  2282. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +188 -0
  2283. package/src/resources/extensions/gsd/tests/write-gate.test.ts +726 -0
  2284. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
  2285. package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +25 -0
  2286. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +81 -0
  2287. package/src/resources/extensions/gsd/token-counter.ts +83 -0
  2288. package/src/resources/extensions/gsd/tool-contract.ts +82 -0
  2289. package/src/resources/extensions/gsd/tools/complete-milestone.ts +273 -0
  2290. package/src/resources/extensions/gsd/tools/complete-slice.ts +568 -0
  2291. package/src/resources/extensions/gsd/tools/complete-task.ts +473 -0
  2292. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  2293. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
  2294. package/src/resources/extensions/gsd/tools/exec-tool.ts +286 -0
  2295. package/src/resources/extensions/gsd/tools/memory-tools.ts +427 -0
  2296. package/src/resources/extensions/gsd/tools/plan-milestone.ts +370 -0
  2297. package/src/resources/extensions/gsd/tools/plan-slice.ts +443 -0
  2298. package/src/resources/extensions/gsd/tools/plan-task.ts +161 -0
  2299. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +289 -0
  2300. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +152 -0
  2301. package/src/resources/extensions/gsd/tools/reopen-slice.ts +152 -0
  2302. package/src/resources/extensions/gsd/tools/reopen-task.ts +146 -0
  2303. package/src/resources/extensions/gsd/tools/replan-slice.ts +242 -0
  2304. package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
  2305. package/src/resources/extensions/gsd/tools/skip-slice.ts +133 -0
  2306. package/src/resources/extensions/gsd/tools/validate-milestone.ts +301 -0
  2307. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +991 -0
  2308. package/src/resources/extensions/gsd/triage-resolution.ts +578 -0
  2309. package/src/resources/extensions/gsd/triage-ui.ts +196 -0
  2310. package/src/resources/extensions/gsd/tui/render-kit.ts +153 -0
  2311. package/src/resources/extensions/gsd/types.ts +721 -0
  2312. package/src/resources/extensions/gsd/undo.ts +465 -0
  2313. package/src/resources/extensions/gsd/unit-context-composer.ts +285 -0
  2314. package/src/resources/extensions/gsd/unit-context-manifest.ts +796 -0
  2315. package/src/resources/extensions/gsd/unit-id.ts +14 -0
  2316. package/src/resources/extensions/gsd/unit-ownership.ts +275 -0
  2317. package/src/resources/extensions/gsd/unit-runtime.ts +267 -0
  2318. package/src/resources/extensions/gsd/unmerged-milestone-guard.ts +150 -0
  2319. package/src/resources/extensions/gsd/uok/audit-toggle.ts +9 -0
  2320. package/src/resources/extensions/gsd/uok/audit.ts +85 -0
  2321. package/src/resources/extensions/gsd/uok/contracts.ts +306 -0
  2322. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +60 -0
  2323. package/src/resources/extensions/gsd/uok/execution-graph.ts +263 -0
  2324. package/src/resources/extensions/gsd/uok/flags.ts +45 -0
  2325. package/src/resources/extensions/gsd/uok/gate-runner.ts +206 -0
  2326. package/src/resources/extensions/gsd/uok/gitops.ts +80 -0
  2327. package/src/resources/extensions/gsd/uok/kernel.ts +124 -0
  2328. package/src/resources/extensions/gsd/uok/loop-adapter.ts +212 -0
  2329. package/src/resources/extensions/gsd/uok/model-policy.ts +112 -0
  2330. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  2331. package/src/resources/extensions/gsd/uok/plan-v2.ts +209 -0
  2332. package/src/resources/extensions/gsd/uok/timeline.ts +158 -0
  2333. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  2334. package/src/resources/extensions/gsd/user-input-boundary.ts +166 -0
  2335. package/src/resources/extensions/gsd/validate-directory.ts +186 -0
  2336. package/src/resources/extensions/gsd/validation-block-guard.ts +83 -0
  2337. package/src/resources/extensions/gsd/validation.ts +45 -0
  2338. package/src/resources/extensions/gsd/verdict-parser.ts +110 -0
  2339. package/src/resources/extensions/gsd/verification-evidence.ts +270 -0
  2340. package/src/resources/extensions/gsd/verification-gate.ts +848 -0
  2341. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  2342. package/src/resources/extensions/gsd/visualizer-data.ts +953 -0
  2343. package/src/resources/extensions/gsd/visualizer-overlay.ts +570 -0
  2344. package/src/resources/extensions/gsd/visualizer-views.ts +1229 -0
  2345. package/src/resources/extensions/gsd/watch/header-renderer.ts +331 -0
  2346. package/src/resources/extensions/gsd/watch/splash-palette.ts +11 -0
  2347. package/src/resources/extensions/gsd/workflow-dispatch.ts +106 -0
  2348. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  2349. package/src/resources/extensions/gsd/workflow-events.ts +166 -0
  2350. package/src/resources/extensions/gsd/workflow-install.ts +422 -0
  2351. package/src/resources/extensions/gsd/workflow-logger.ts +381 -0
  2352. package/src/resources/extensions/gsd/workflow-manifest.ts +260 -0
  2353. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +60 -0
  2354. package/src/resources/extensions/gsd/workflow-mcp.ts +459 -0
  2355. package/src/resources/extensions/gsd/workflow-migration.ts +340 -0
  2356. package/src/resources/extensions/gsd/workflow-plugins.ts +402 -0
  2357. package/src/resources/extensions/gsd/workflow-projections.ts +567 -0
  2358. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  2359. package/src/resources/extensions/gsd/workflow-reconcile.ts +681 -0
  2360. package/src/resources/extensions/gsd/workflow-templates/accessibility-audit.md +88 -0
  2361. package/src/resources/extensions/gsd/workflow-templates/api-breaking-change.md +117 -0
  2362. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +88 -0
  2363. package/src/resources/extensions/gsd/workflow-templates/changelog-gen.md +82 -0
  2364. package/src/resources/extensions/gsd/workflow-templates/ci-bootstrap.md +144 -0
  2365. package/src/resources/extensions/gsd/workflow-templates/dead-code.md +81 -0
  2366. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +75 -0
  2367. package/src/resources/extensions/gsd/workflow-templates/docs-sync.yaml +76 -0
  2368. package/src/resources/extensions/gsd/workflow-templates/env-audit.yaml +88 -0
  2369. package/src/resources/extensions/gsd/workflow-templates/full-project.md +42 -0
  2370. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +46 -0
  2371. package/src/resources/extensions/gsd/workflow-templates/issue-triage.md +84 -0
  2372. package/src/resources/extensions/gsd/workflow-templates/observability-setup.md +133 -0
  2373. package/src/resources/extensions/gsd/workflow-templates/onboarding-check.md +74 -0
  2374. package/src/resources/extensions/gsd/workflow-templates/performance-audit.md +125 -0
  2375. package/src/resources/extensions/gsd/workflow-templates/pr-review.md +67 -0
  2376. package/src/resources/extensions/gsd/workflow-templates/pr-triage.md +83 -0
  2377. package/src/resources/extensions/gsd/workflow-templates/refactor.md +84 -0
  2378. package/src/resources/extensions/gsd/workflow-templates/registry.json +269 -0
  2379. package/src/resources/extensions/gsd/workflow-templates/release.md +118 -0
  2380. package/src/resources/extensions/gsd/workflow-templates/rename-symbol.yaml +99 -0
  2381. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +74 -0
  2382. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +82 -0
  2383. package/src/resources/extensions/gsd/workflow-templates/spike.md +76 -0
  2384. package/src/resources/extensions/gsd/workflow-templates/test-backfill.yaml +73 -0
  2385. package/src/resources/extensions/gsd/workflow-templates.ts +278 -0
  2386. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  2387. package/src/resources/extensions/gsd/workspace-index.ts +277 -0
  2388. package/src/resources/extensions/gsd/workspace.ts +95 -0
  2389. package/src/resources/extensions/gsd/worktree-command-bootstrap.ts +46 -0
  2390. package/src/resources/extensions/gsd/worktree-command.ts +834 -0
  2391. package/src/resources/extensions/gsd/worktree-health.ts +178 -0
  2392. package/src/resources/extensions/gsd/worktree-lifecycle.ts +1989 -0
  2393. package/src/resources/extensions/gsd/worktree-manager.ts +909 -0
  2394. package/src/resources/extensions/gsd/worktree-root.ts +182 -0
  2395. package/src/resources/extensions/gsd/worktree-safety.ts +329 -0
  2396. package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
  2397. package/src/resources/extensions/gsd/worktree-state-projection.ts +447 -0
  2398. package/src/resources/extensions/gsd/worktree-telemetry.ts +366 -0
  2399. package/src/resources/extensions/gsd/worktree.ts +235 -0
  2400. package/src/resources/extensions/gsd/write-intercept.ts +99 -0
  2401. package/src/resources/extensions/mac-tools/extension-manifest.json +16 -0
  2402. package/src/resources/extensions/mac-tools/index.ts +852 -0
  2403. package/src/resources/extensions/mac-tools/swift-cli/Package.swift +22 -0
  2404. package/src/resources/extensions/mac-tools/swift-cli/Sources/main.swift +1318 -0
  2405. package/src/resources/extensions/mcp-client/auth.ts +160 -0
  2406. package/src/resources/extensions/mcp-client/index.ts +526 -0
  2407. package/src/resources/extensions/mcp-client/manager.ts +516 -0
  2408. package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
  2409. package/src/resources/extensions/mcp-client/tests/manager.test.ts +165 -0
  2410. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +89 -0
  2411. package/src/resources/extensions/ollama/index.ts +158 -0
  2412. package/src/resources/extensions/ollama/model-capabilities.ts +186 -0
  2413. package/src/resources/extensions/ollama/ndjson-stream.ts +63 -0
  2414. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +128 -0
  2415. package/src/resources/extensions/ollama/ollama-chat-provider.ts +459 -0
  2416. package/src/resources/extensions/ollama/ollama-client.ts +262 -0
  2417. package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
  2418. package/src/resources/extensions/ollama/ollama-discovery.ts +134 -0
  2419. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +215 -0
  2420. package/src/resources/extensions/ollama/ollama-tool.ts +287 -0
  2421. package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +258 -0
  2422. package/src/resources/extensions/ollama/tests/ollama-chat-provider-stream.test.ts +82 -0
  2423. package/src/resources/extensions/ollama/tests/ollama-client-timeout-env.test.ts +147 -0
  2424. package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
  2425. package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +55 -0
  2426. package/src/resources/extensions/ollama/thinking-parser.ts +116 -0
  2427. package/src/resources/extensions/ollama/types.ts +153 -0
  2428. package/src/resources/extensions/package.json +3 -0
  2429. package/src/resources/extensions/remote-questions/commands.ts +480 -0
  2430. package/src/resources/extensions/remote-questions/config.ts +126 -0
  2431. package/src/resources/extensions/remote-questions/discord-adapter.ts +148 -0
  2432. package/src/resources/extensions/remote-questions/extension-manifest.json +11 -0
  2433. package/src/resources/extensions/remote-questions/format.ts +315 -0
  2434. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  2435. package/src/resources/extensions/remote-questions/manager.ts +270 -0
  2436. package/src/resources/extensions/remote-questions/mod.ts +16 -0
  2437. package/src/resources/extensions/remote-questions/notify.ts +90 -0
  2438. package/src/resources/extensions/remote-questions/remote-command.ts +437 -0
  2439. package/src/resources/extensions/remote-questions/slack-adapter.ts +141 -0
  2440. package/src/resources/extensions/remote-questions/status.ts +31 -0
  2441. package/src/resources/extensions/remote-questions/store.ts +81 -0
  2442. package/src/resources/extensions/remote-questions/telegram-adapter.ts +231 -0
  2443. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +256 -0
  2444. package/src/resources/extensions/remote-questions/tests/remote-answer-normalization.test.ts +92 -0
  2445. package/src/resources/extensions/remote-questions/tests/telegram-commands.test.ts +267 -0
  2446. package/src/resources/extensions/remote-questions/types.ts +102 -0
  2447. package/src/resources/extensions/search-the-web/cache.ts +78 -0
  2448. package/src/resources/extensions/search-the-web/command-search-provider.ts +105 -0
  2449. package/src/resources/extensions/search-the-web/extension-manifest.json +13 -0
  2450. package/src/resources/extensions/search-the-web/format.ts +258 -0
  2451. package/src/resources/extensions/search-the-web/http.ts +238 -0
  2452. package/src/resources/extensions/search-the-web/index.ts +64 -0
  2453. package/src/resources/extensions/search-the-web/native-search.ts +276 -0
  2454. package/src/resources/extensions/search-the-web/provider.ts +150 -0
  2455. package/src/resources/extensions/search-the-web/tavily.ts +116 -0
  2456. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +589 -0
  2457. package/src/resources/extensions/search-the-web/tool-llm-context.ts +608 -0
  2458. package/src/resources/extensions/search-the-web/tool-search.ts +677 -0
  2459. package/src/resources/extensions/search-the-web/url-utils.ts +144 -0
  2460. package/src/resources/extensions/shared/cmux-events.ts +59 -0
  2461. package/src/resources/extensions/shared/confirm-ui.ts +126 -0
  2462. package/src/resources/extensions/shared/format-utils.ts +99 -0
  2463. package/src/resources/extensions/shared/frontmatter.ts +117 -0
  2464. package/src/resources/extensions/shared/gsd-phase-state.ts +95 -0
  2465. package/src/resources/extensions/shared/html-shell.ts +412 -0
  2466. package/src/resources/extensions/shared/interview-ui.ts +848 -0
  2467. package/src/resources/extensions/shared/layout-utils.ts +75 -0
  2468. package/src/resources/extensions/shared/mod.ts +31 -0
  2469. package/src/resources/extensions/shared/next-action-ui.ts +226 -0
  2470. package/src/resources/extensions/shared/path-display.ts +19 -0
  2471. package/src/resources/extensions/shared/rtk-session-stats.ts +248 -0
  2472. package/src/resources/extensions/shared/rtk-shared.ts +58 -0
  2473. package/src/resources/extensions/shared/rtk.ts +98 -0
  2474. package/src/resources/extensions/shared/sanitize.ts +55 -0
  2475. package/src/resources/extensions/shared/terminal.ts +28 -0
  2476. package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +161 -0
  2477. package/src/resources/extensions/shared/tests/format-utils.test.ts +155 -0
  2478. package/src/resources/extensions/shared/tests/gsd-phase-state.test.ts +90 -0
  2479. package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +198 -0
  2480. package/src/resources/extensions/shared/tests/interview-preview.test.ts +185 -0
  2481. package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +144 -0
  2482. package/src/resources/extensions/shared/tests/preview-layout.test.ts +120 -0
  2483. package/src/resources/extensions/shared/tui.ts +11 -0
  2484. package/src/resources/extensions/shared/ui.ts +401 -0
  2485. package/src/resources/extensions/slash-commands/audit.ts +89 -0
  2486. package/src/resources/extensions/slash-commands/clear.ts +10 -0
  2487. package/src/resources/extensions/slash-commands/create-extension.ts +311 -0
  2488. package/src/resources/extensions/slash-commands/create-slash-command.ts +234 -0
  2489. package/src/resources/extensions/slash-commands/extension-manifest.json +11 -0
  2490. package/src/resources/extensions/slash-commands/index.ts +12 -0
  2491. package/src/resources/extensions/subagent/agents.ts +166 -0
  2492. package/src/resources/extensions/subagent/extension-manifest.json +13 -0
  2493. package/src/resources/extensions/subagent/index.ts +1938 -0
  2494. package/src/resources/extensions/subagent/isolation.ts +504 -0
  2495. package/src/resources/extensions/subagent/launch.ts +131 -0
  2496. package/src/resources/extensions/subagent/run-store.ts +218 -0
  2497. package/src/resources/extensions/subagent/tests/agents-conflicts.test.ts +33 -0
  2498. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  2499. package/src/resources/extensions/subagent/tests/model-override.test.ts +55 -0
  2500. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  2501. package/src/resources/extensions/subagent/worker-registry.ts +100 -0
  2502. package/src/resources/extensions/ttsr/extension-manifest.json +11 -0
  2503. package/src/resources/extensions/ttsr/index.ts +168 -0
  2504. package/src/resources/extensions/ttsr/rule-loader.ts +75 -0
  2505. package/src/resources/extensions/ttsr/ttsr-interrupt.md +6 -0
  2506. package/src/resources/extensions/ttsr/ttsr-manager.ts +465 -0
  2507. package/src/resources/extensions/universal-config/discovery.ts +104 -0
  2508. package/src/resources/extensions/universal-config/extension-manifest.json +13 -0
  2509. package/src/resources/extensions/universal-config/format.ts +191 -0
  2510. package/src/resources/extensions/universal-config/index.ts +120 -0
  2511. package/src/resources/extensions/universal-config/package.json +11 -0
  2512. package/src/resources/extensions/universal-config/scanners.ts +642 -0
  2513. package/src/resources/extensions/universal-config/tests/discovery.test.ts +119 -0
  2514. package/src/resources/extensions/universal-config/tests/format.test.ts +127 -0
  2515. package/src/resources/extensions/universal-config/tests/scanners.test.ts +456 -0
  2516. package/src/resources/extensions/universal-config/tools.ts +60 -0
  2517. package/src/resources/extensions/universal-config/types.ts +135 -0
  2518. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  2519. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  2520. package/src/resources/extensions/visual-brief/index.ts +8 -0
  2521. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  2522. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  2523. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  2524. package/src/resources/extensions/voice/extension-manifest.json +12 -0
  2525. package/src/resources/extensions/voice/index.ts +264 -0
  2526. package/src/resources/extensions/voice/linux-ready.ts +86 -0
  2527. package/src/resources/extensions/voice/speech-recognizer.py +504 -0
  2528. package/src/resources/extensions/voice/speech-recognizer.swift +154 -0
  2529. package/src/resources/extensions/voice/tests/linux-ready.test.ts +140 -0
  2530. package/src/resources/skills/accessibility/SKILL.md +522 -0
  2531. package/src/resources/skills/accessibility/references/WCAG.md +162 -0
  2532. package/src/resources/skills/agent-browser/SKILL.md +517 -0
  2533. package/src/resources/skills/agent-browser/references/authentication.md +202 -0
  2534. package/src/resources/skills/agent-browser/references/commands.md +263 -0
  2535. package/src/resources/skills/agent-browser/references/profiling.md +120 -0
  2536. package/src/resources/skills/agent-browser/references/proxy-support.md +194 -0
  2537. package/src/resources/skills/agent-browser/references/session-management.md +193 -0
  2538. package/src/resources/skills/agent-browser/references/snapshot-refs.md +194 -0
  2539. package/src/resources/skills/agent-browser/references/video-recording.md +173 -0
  2540. package/src/resources/skills/agent-browser/templates/authenticated-session.sh +105 -0
  2541. package/src/resources/skills/agent-browser/templates/capture-workflow.sh +69 -0
  2542. package/src/resources/skills/agent-browser/templates/form-automation.sh +62 -0
  2543. package/src/resources/skills/api-design/SKILL.md +190 -0
  2544. package/src/resources/skills/best-practices/SKILL.md +583 -0
  2545. package/src/resources/skills/btw/SKILL.md +42 -0
  2546. package/src/resources/skills/code-optimizer/SKILL.md +160 -0
  2547. package/src/resources/skills/code-optimizer/references/algorithmic-complexity.md +66 -0
  2548. package/src/resources/skills/code-optimizer/references/build-compilation.md +90 -0
  2549. package/src/resources/skills/code-optimizer/references/bundle-dependencies.md +82 -0
  2550. package/src/resources/skills/code-optimizer/references/caching-memoization.md +76 -0
  2551. package/src/resources/skills/code-optimizer/references/concurrency-async.md +80 -0
  2552. package/src/resources/skills/code-optimizer/references/config-infra.md +71 -0
  2553. package/src/resources/skills/code-optimizer/references/data-structures.md +80 -0
  2554. package/src/resources/skills/code-optimizer/references/database-queries.md +76 -0
  2555. package/src/resources/skills/code-optimizer/references/dead-code-redundancy.md +84 -0
  2556. package/src/resources/skills/code-optimizer/references/error-resilience.md +80 -0
  2557. package/src/resources/skills/code-optimizer/references/io-network.md +89 -0
  2558. package/src/resources/skills/code-optimizer/references/logging-observability.md +64 -0
  2559. package/src/resources/skills/code-optimizer/references/memory-resources.md +66 -0
  2560. package/src/resources/skills/code-optimizer/references/rendering-ui.md +90 -0
  2561. package/src/resources/skills/code-optimizer/references/security-performance.md +68 -0
  2562. package/src/resources/skills/core-web-vitals/SKILL.md +441 -0
  2563. package/src/resources/skills/core-web-vitals/references/LCP.md +208 -0
  2564. package/src/resources/skills/create-gsd-extension/SKILL.md +93 -0
  2565. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  2566. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  2567. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  2568. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  2569. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  2570. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  2571. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  2572. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  2573. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  2574. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +37 -0
  2575. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  2576. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  2577. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  2578. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  2579. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  2580. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  2581. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  2582. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  2583. package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +104 -0
  2584. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  2585. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +176 -0
  2586. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +76 -0
  2587. package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
  2588. package/src/resources/skills/create-skill/SKILL.md +186 -0
  2589. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  2590. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  2591. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  2592. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  2593. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  2594. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  2595. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  2596. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  2597. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  2598. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  2599. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  2600. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  2601. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  2602. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  2603. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  2604. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  2605. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  2606. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  2607. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  2608. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  2609. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  2610. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  2611. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  2612. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  2613. package/src/resources/skills/create-workflow/SKILL.md +130 -0
  2614. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  2615. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  2616. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  2617. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  2618. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  2619. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  2620. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  2621. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  2622. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  2623. package/src/resources/skills/debug-like-expert/SKILL.md +231 -0
  2624. package/src/resources/skills/debug-like-expert/references/debugging-mindset.md +253 -0
  2625. package/src/resources/skills/debug-like-expert/references/hypothesis-testing.md +373 -0
  2626. package/src/resources/skills/debug-like-expert/references/investigation-techniques.md +337 -0
  2627. package/src/resources/skills/debug-like-expert/references/verification-patterns.md +425 -0
  2628. package/src/resources/skills/debug-like-expert/references/when-to-research.md +361 -0
  2629. package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
  2630. package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
  2631. package/src/resources/skills/design-an-interface/SKILL.md +102 -0
  2632. package/src/resources/skills/forensics/SKILL.md +153 -0
  2633. package/src/resources/skills/frontend-design/SKILL.md +45 -0
  2634. package/src/resources/skills/github-workflows/SKILL.md +90 -0
  2635. package/src/resources/skills/github-workflows/references/gh/SKILL.md +276 -0
  2636. package/src/resources/skills/github-workflows/references/gh/references/issue-stories.md +204 -0
  2637. package/src/resources/skills/github-workflows/references/gh/references/labels.md +170 -0
  2638. package/src/resources/skills/github-workflows/references/gh/references/milestones.md +158 -0
  2639. package/src/resources/skills/github-workflows/references/gh/references/projects-v2.md +177 -0
  2640. package/src/resources/skills/github-workflows/references/gh/scripts/experiment_cleanup.py +191 -0
  2641. package/src/resources/skills/github-workflows/references/gh/scripts/github_project_setup.py +799 -0
  2642. package/src/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
  2643. package/src/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +608 -0
  2644. package/src/resources/skills/grill-me/SKILL.md +93 -0
  2645. package/src/resources/skills/handoff/SKILL.md +121 -0
  2646. package/src/resources/skills/lint/SKILL.md +145 -0
  2647. package/src/resources/skills/make-interfaces-feel-better/SKILL.md +122 -0
  2648. package/src/resources/skills/make-interfaces-feel-better/animations.md +379 -0
  2649. package/src/resources/skills/make-interfaces-feel-better/performance.md +88 -0
  2650. package/src/resources/skills/make-interfaces-feel-better/surfaces.md +247 -0
  2651. package/src/resources/skills/make-interfaces-feel-better/typography.md +123 -0
  2652. package/src/resources/skills/observability/SKILL.md +174 -0
  2653. package/src/resources/skills/react-best-practices/README.md +123 -0
  2654. package/src/resources/skills/react-best-practices/SKILL.md +136 -0
  2655. package/src/resources/skills/react-best-practices/metadata.json +15 -0
  2656. package/src/resources/skills/react-best-practices/rules/_sections.md +46 -0
  2657. package/src/resources/skills/react-best-practices/rules/_template.md +28 -0
  2658. package/src/resources/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  2659. package/src/resources/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  2660. package/src/resources/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  2661. package/src/resources/skills/react-best-practices/rules/async-api-routes.md +38 -0
  2662. package/src/resources/skills/react-best-practices/rules/async-defer-await.md +80 -0
  2663. package/src/resources/skills/react-best-practices/rules/async-dependencies.md +51 -0
  2664. package/src/resources/skills/react-best-practices/rules/async-parallel.md +28 -0
  2665. package/src/resources/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  2666. package/src/resources/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  2667. package/src/resources/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  2668. package/src/resources/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  2669. package/src/resources/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  2670. package/src/resources/skills/react-best-practices/rules/bundle-preload.md +50 -0
  2671. package/src/resources/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  2672. package/src/resources/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  2673. package/src/resources/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  2674. package/src/resources/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  2675. package/src/resources/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
  2676. package/src/resources/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  2677. package/src/resources/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  2678. package/src/resources/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  2679. package/src/resources/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  2680. package/src/resources/skills/react-best-practices/rules/js-early-exit.md +50 -0
  2681. package/src/resources/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  2682. package/src/resources/skills/react-best-practices/rules/js-index-maps.md +37 -0
  2683. package/src/resources/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  2684. package/src/resources/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  2685. package/src/resources/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  2686. package/src/resources/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  2687. package/src/resources/skills/react-best-practices/rules/rendering-activity.md +26 -0
  2688. package/src/resources/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  2689. package/src/resources/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  2690. package/src/resources/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  2691. package/src/resources/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  2692. package/src/resources/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  2693. package/src/resources/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  2694. package/src/resources/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  2695. package/src/resources/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  2696. package/src/resources/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  2697. package/src/resources/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  2698. package/src/resources/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  2699. package/src/resources/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  2700. package/src/resources/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  2701. package/src/resources/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  2702. package/src/resources/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  2703. package/src/resources/skills/react-best-practices/rules/rerender-memo.md +44 -0
  2704. package/src/resources/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  2705. package/src/resources/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  2706. package/src/resources/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  2707. package/src/resources/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  2708. package/src/resources/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  2709. package/src/resources/skills/react-best-practices/rules/server-auth-actions.md +96 -0
  2710. package/src/resources/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  2711. package/src/resources/skills/react-best-practices/rules/server-cache-react.md +76 -0
  2712. package/src/resources/skills/react-best-practices/rules/server-dedup-props.md +65 -0
  2713. package/src/resources/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  2714. package/src/resources/skills/react-best-practices/rules/server-serialization.md +38 -0
  2715. package/src/resources/skills/review/SKILL.md +218 -0
  2716. package/src/resources/skills/security-review/SKILL.md +181 -0
  2717. package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
  2718. package/src/resources/skills/tdd/SKILL.md +112 -0
  2719. package/src/resources/skills/test/SKILL.md +204 -0
  2720. package/src/resources/skills/userinterface-wiki/SKILL.md +253 -0
  2721. package/src/resources/skills/userinterface-wiki/rules/_sections.md +66 -0
  2722. package/src/resources/skills/userinterface-wiki/rules/_template.md +24 -0
  2723. package/src/resources/skills/userinterface-wiki/rules/a11y-reduced-motion-check.md +30 -0
  2724. package/src/resources/skills/userinterface-wiki/rules/a11y-toggle-setting.md +30 -0
  2725. package/src/resources/skills/userinterface-wiki/rules/a11y-visual-equivalent.md +36 -0
  2726. package/src/resources/skills/userinterface-wiki/rules/a11y-volume-control.md +28 -0
  2727. package/src/resources/skills/userinterface-wiki/rules/appropriate-confirmations-only.md +19 -0
  2728. package/src/resources/skills/userinterface-wiki/rules/appropriate-errors-warnings.md +18 -0
  2729. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-decorative.md +21 -0
  2730. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-high-frequency.md +28 -0
  2731. package/src/resources/skills/userinterface-wiki/rules/appropriate-no-punishing.md +27 -0
  2732. package/src/resources/skills/userinterface-wiki/rules/container-callback-ref.md +31 -0
  2733. package/src/resources/skills/userinterface-wiki/rules/container-guard-initial-zero.md +25 -0
  2734. package/src/resources/skills/userinterface-wiki/rules/container-no-excessive-use.md +13 -0
  2735. package/src/resources/skills/userinterface-wiki/rules/container-overflow-hidden.md +25 -0
  2736. package/src/resources/skills/userinterface-wiki/rules/container-transition-delay.md +21 -0
  2737. package/src/resources/skills/userinterface-wiki/rules/container-two-div-pattern.md +35 -0
  2738. package/src/resources/skills/userinterface-wiki/rules/container-use-resize-observer.md +48 -0
  2739. package/src/resources/skills/userinterface-wiki/rules/context-cleanup-nodes.md +25 -0
  2740. package/src/resources/skills/userinterface-wiki/rules/context-resume-suspended.md +28 -0
  2741. package/src/resources/skills/userinterface-wiki/rules/context-reuse-single.md +30 -0
  2742. package/src/resources/skills/userinterface-wiki/rules/design-filter-for-character.md +25 -0
  2743. package/src/resources/skills/userinterface-wiki/rules/design-noise-for-percussion.md +26 -0
  2744. package/src/resources/skills/userinterface-wiki/rules/design-oscillator-for-tonal.md +22 -0
  2745. package/src/resources/skills/userinterface-wiki/rules/duration-max-300ms.md +21 -0
  2746. package/src/resources/skills/userinterface-wiki/rules/duration-press-hover.md +21 -0
  2747. package/src/resources/skills/userinterface-wiki/rules/duration-shorten-before-curve.md +21 -0
  2748. package/src/resources/skills/userinterface-wiki/rules/duration-small-state.md +15 -0
  2749. package/src/resources/skills/userinterface-wiki/rules/easing-entrance-ease-out.md +21 -0
  2750. package/src/resources/skills/userinterface-wiki/rules/easing-exit-ease-in.md +21 -0
  2751. package/src/resources/skills/userinterface-wiki/rules/easing-for-state-change.md +27 -0
  2752. package/src/resources/skills/userinterface-wiki/rules/easing-linear-only-progress.md +21 -0
  2753. package/src/resources/skills/userinterface-wiki/rules/easing-natural-decay.md +22 -0
  2754. package/src/resources/skills/userinterface-wiki/rules/easing-no-linear-motion.md +22 -0
  2755. package/src/resources/skills/userinterface-wiki/rules/easing-transition-ease-in-out.md +15 -0
  2756. package/src/resources/skills/userinterface-wiki/rules/envelope-exponential-decay.md +21 -0
  2757. package/src/resources/skills/userinterface-wiki/rules/envelope-no-zero-target.md +21 -0
  2758. package/src/resources/skills/userinterface-wiki/rules/envelope-set-initial-value.md +22 -0
  2759. package/src/resources/skills/userinterface-wiki/rules/exit-key-required.md +29 -0
  2760. package/src/resources/skills/userinterface-wiki/rules/exit-matches-initial.md +29 -0
  2761. package/src/resources/skills/userinterface-wiki/rules/exit-prop-required.md +33 -0
  2762. package/src/resources/skills/userinterface-wiki/rules/exit-requires-wrapper.md +27 -0
  2763. package/src/resources/skills/userinterface-wiki/rules/impl-default-subtle.md +21 -0
  2764. package/src/resources/skills/userinterface-wiki/rules/impl-preload-audio.md +34 -0
  2765. package/src/resources/skills/userinterface-wiki/rules/impl-reset-current-time.md +26 -0
  2766. package/src/resources/skills/userinterface-wiki/rules/mode-pop-layout-for-lists.md +25 -0
  2767. package/src/resources/skills/userinterface-wiki/rules/mode-sync-layout-conflict.md +29 -0
  2768. package/src/resources/skills/userinterface-wiki/rules/mode-wait-doubles-duration.md +25 -0
  2769. package/src/resources/skills/userinterface-wiki/rules/morphing-aria-hidden.md +21 -0
  2770. package/src/resources/skills/userinterface-wiki/rules/morphing-consistent-viewbox.md +23 -0
  2771. package/src/resources/skills/userinterface-wiki/rules/morphing-group-variants.md +33 -0
  2772. package/src/resources/skills/userinterface-wiki/rules/morphing-jump-non-grouped.md +29 -0
  2773. package/src/resources/skills/userinterface-wiki/rules/morphing-reduced-motion.md +28 -0
  2774. package/src/resources/skills/userinterface-wiki/rules/morphing-spring-rotation.md +23 -0
  2775. package/src/resources/skills/userinterface-wiki/rules/morphing-strokelinecap-round.md +21 -0
  2776. package/src/resources/skills/userinterface-wiki/rules/morphing-three-lines.md +32 -0
  2777. package/src/resources/skills/userinterface-wiki/rules/morphing-use-collapsed.md +33 -0
  2778. package/src/resources/skills/userinterface-wiki/rules/native-backdrop-styling.md +27 -0
  2779. package/src/resources/skills/userinterface-wiki/rules/native-placeholder-styling.md +27 -0
  2780. package/src/resources/skills/userinterface-wiki/rules/native-selection-styling.md +18 -0
  2781. package/src/resources/skills/userinterface-wiki/rules/nested-consistent-timing.md +25 -0
  2782. package/src/resources/skills/userinterface-wiki/rules/nested-propagate-required.md +41 -0
  2783. package/src/resources/skills/userinterface-wiki/rules/none-context-menu-entrance.md +25 -0
  2784. package/src/resources/skills/userinterface-wiki/rules/none-high-frequency.md +29 -0
  2785. package/src/resources/skills/userinterface-wiki/rules/none-keyboard-navigation.md +32 -0
  2786. package/src/resources/skills/userinterface-wiki/rules/param-click-duration.md +21 -0
  2787. package/src/resources/skills/userinterface-wiki/rules/param-filter-frequency-range.md +21 -0
  2788. package/src/resources/skills/userinterface-wiki/rules/param-q-value-range.md +21 -0
  2789. package/src/resources/skills/userinterface-wiki/rules/param-reasonable-gain.md +21 -0
  2790. package/src/resources/skills/userinterface-wiki/rules/physics-active-state.md +23 -0
  2791. package/src/resources/skills/userinterface-wiki/rules/physics-no-excessive-stagger.md +22 -0
  2792. package/src/resources/skills/userinterface-wiki/rules/physics-spring-for-overshoot.md +23 -0
  2793. package/src/resources/skills/userinterface-wiki/rules/physics-subtle-deformation.md +22 -0
  2794. package/src/resources/skills/userinterface-wiki/rules/prefetch-hit-slop.md +27 -0
  2795. package/src/resources/skills/userinterface-wiki/rules/prefetch-keyboard-tab.md +19 -0
  2796. package/src/resources/skills/userinterface-wiki/rules/prefetch-not-everything.md +22 -0
  2797. package/src/resources/skills/userinterface-wiki/rules/prefetch-touch-fallback.md +34 -0
  2798. package/src/resources/skills/userinterface-wiki/rules/prefetch-trajectory-over-hover.md +32 -0
  2799. package/src/resources/skills/userinterface-wiki/rules/prefetch-use-selectively.md +13 -0
  2800. package/src/resources/skills/userinterface-wiki/rules/presence-disable-interactions.md +31 -0
  2801. package/src/resources/skills/userinterface-wiki/rules/presence-hook-in-child.md +31 -0
  2802. package/src/resources/skills/userinterface-wiki/rules/presence-safe-to-remove.md +37 -0
  2803. package/src/resources/skills/userinterface-wiki/rules/pseudo-content-required.md +28 -0
  2804. package/src/resources/skills/userinterface-wiki/rules/pseudo-first-line-styling.md +27 -0
  2805. package/src/resources/skills/userinterface-wiki/rules/pseudo-hit-target-expansion.md +31 -0
  2806. package/src/resources/skills/userinterface-wiki/rules/pseudo-marker-styling.md +28 -0
  2807. package/src/resources/skills/userinterface-wiki/rules/pseudo-over-dom-node.md +32 -0
  2808. package/src/resources/skills/userinterface-wiki/rules/pseudo-position-relative-parent.md +33 -0
  2809. package/src/resources/skills/userinterface-wiki/rules/pseudo-z-index-layering.md +37 -0
  2810. package/src/resources/skills/userinterface-wiki/rules/spring-for-gestures.md +27 -0
  2811. package/src/resources/skills/userinterface-wiki/rules/spring-for-interruptible.md +27 -0
  2812. package/src/resources/skills/userinterface-wiki/rules/spring-params-balanced.md +29 -0
  2813. package/src/resources/skills/userinterface-wiki/rules/spring-preserves-velocity.md +28 -0
  2814. package/src/resources/skills/userinterface-wiki/rules/staging-dim-background.md +22 -0
  2815. package/src/resources/skills/userinterface-wiki/rules/staging-one-focal-point.md +24 -0
  2816. package/src/resources/skills/userinterface-wiki/rules/staging-z-index-hierarchy.md +22 -0
  2817. package/src/resources/skills/userinterface-wiki/rules/timing-consistent.md +24 -0
  2818. package/src/resources/skills/userinterface-wiki/rules/timing-no-entrance-context-menu.md +22 -0
  2819. package/src/resources/skills/userinterface-wiki/rules/timing-under-300ms.md +22 -0
  2820. package/src/resources/skills/userinterface-wiki/rules/transition-name-cleanup.md +28 -0
  2821. package/src/resources/skills/userinterface-wiki/rules/transition-name-required.md +27 -0
  2822. package/src/resources/skills/userinterface-wiki/rules/transition-name-unique.md +24 -0
  2823. package/src/resources/skills/userinterface-wiki/rules/transition-over-js-library.md +32 -0
  2824. package/src/resources/skills/userinterface-wiki/rules/transition-style-pseudo-elements.md +24 -0
  2825. package/src/resources/skills/userinterface-wiki/rules/type-antialiased-on-retina.md +18 -0
  2826. package/src/resources/skills/userinterface-wiki/rules/type-disambiguation-stylistic-set.md +15 -0
  2827. package/src/resources/skills/userinterface-wiki/rules/type-font-display-swap.md +28 -0
  2828. package/src/resources/skills/userinterface-wiki/rules/type-justify-with-hyphens.md +24 -0
  2829. package/src/resources/skills/userinterface-wiki/rules/type-letter-spacing-uppercase.md +28 -0
  2830. package/src/resources/skills/userinterface-wiki/rules/type-no-font-synthesis.md +18 -0
  2831. package/src/resources/skills/userinterface-wiki/rules/type-oldstyle-nums-for-prose.md +21 -0
  2832. package/src/resources/skills/userinterface-wiki/rules/type-opentype-contextual-alternates.md +15 -0
  2833. package/src/resources/skills/userinterface-wiki/rules/type-optical-sizing-auto.md +25 -0
  2834. package/src/resources/skills/userinterface-wiki/rules/type-proper-fractions.md +15 -0
  2835. package/src/resources/skills/userinterface-wiki/rules/type-slashed-zero.md +17 -0
  2836. package/src/resources/skills/userinterface-wiki/rules/type-tabular-nums-for-data.md +21 -0
  2837. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-balance-headings.md +21 -0
  2838. package/src/resources/skills/userinterface-wiki/rules/type-text-wrap-pretty.md +16 -0
  2839. package/src/resources/skills/userinterface-wiki/rules/type-underline-offset.md +25 -0
  2840. package/src/resources/skills/userinterface-wiki/rules/type-variable-weight-continuous.md +23 -0
  2841. package/src/resources/skills/userinterface-wiki/rules/ux-aesthetic-usability.md +32 -0
  2842. package/src/resources/skills/userinterface-wiki/rules/ux-cognitive-load-reduce.md +49 -0
  2843. package/src/resources/skills/userinterface-wiki/rules/ux-common-region-boundaries.md +50 -0
  2844. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-perceived-speed.md +29 -0
  2845. package/src/resources/skills/userinterface-wiki/rules/ux-doherty-under-400ms.md +30 -0
  2846. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-hit-area.md +32 -0
  2847. package/src/resources/skills/userinterface-wiki/rules/ux-fitts-target-size.md +31 -0
  2848. package/src/resources/skills/userinterface-wiki/rules/ux-goal-gradient-progress.md +33 -0
  2849. package/src/resources/skills/userinterface-wiki/rules/ux-hicks-minimize-choices.md +45 -0
  2850. package/src/resources/skills/userinterface-wiki/rules/ux-jakobs-familiar-patterns.md +37 -0
  2851. package/src/resources/skills/userinterface-wiki/rules/ux-millers-chunking.md +23 -0
  2852. package/src/resources/skills/userinterface-wiki/rules/ux-pareto-prioritize-features.md +36 -0
  2853. package/src/resources/skills/userinterface-wiki/rules/ux-peak-end-finish-strong.md +35 -0
  2854. package/src/resources/skills/userinterface-wiki/rules/ux-postels-accept-messy-input.md +45 -0
  2855. package/src/resources/skills/userinterface-wiki/rules/ux-pragnanz-simplify.md +33 -0
  2856. package/src/resources/skills/userinterface-wiki/rules/ux-progressive-disclosure.md +41 -0
  2857. package/src/resources/skills/userinterface-wiki/rules/ux-proximity-grouping.md +38 -0
  2858. package/src/resources/skills/userinterface-wiki/rules/ux-serial-position.md +31 -0
  2859. package/src/resources/skills/userinterface-wiki/rules/ux-similarity-consistency.md +35 -0
  2860. package/src/resources/skills/userinterface-wiki/rules/ux-teslers-complexity.md +28 -0
  2861. package/src/resources/skills/userinterface-wiki/rules/ux-uniform-connectedness.md +43 -0
  2862. package/src/resources/skills/userinterface-wiki/rules/ux-von-restorff-emphasis.md +29 -0
  2863. package/src/resources/skills/userinterface-wiki/rules/ux-zeigarnik-show-incomplete.md +36 -0
  2864. package/src/resources/skills/userinterface-wiki/rules/visual-animate-shadow-pseudo.md +49 -0
  2865. package/src/resources/skills/userinterface-wiki/rules/visual-border-alpha-colors.md +25 -0
  2866. package/src/resources/skills/userinterface-wiki/rules/visual-button-shadow-anatomy.md +49 -0
  2867. package/src/resources/skills/userinterface-wiki/rules/visual-concentric-radius.md +40 -0
  2868. package/src/resources/skills/userinterface-wiki/rules/visual-consistent-spacing-scale.md +35 -0
  2869. package/src/resources/skills/userinterface-wiki/rules/visual-layered-shadows.md +30 -0
  2870. package/src/resources/skills/userinterface-wiki/rules/visual-no-pure-black-shadow.md +25 -0
  2871. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-direction.md +25 -0
  2872. package/src/resources/skills/userinterface-wiki/rules/visual-shadow-matches-elevation.md +23 -0
  2873. package/src/resources/skills/userinterface-wiki/rules/weight-duration-matches-action.md +29 -0
  2874. package/src/resources/skills/userinterface-wiki/rules/weight-match-action.md +32 -0
  2875. package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
  2876. package/src/resources/skills/web-design-guidelines/SKILL.md +39 -0
  2877. package/src/resources/skills/web-quality-audit/SKILL.md +168 -0
  2878. package/src/resources/skills/web-quality-audit/scripts/analyze.sh +91 -0
  2879. package/src/resources/skills/write-docs/SKILL.md +82 -0
  2880. 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
+ }