gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00

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 (545) hide show
  1. package/README.md +53 -17
  2. package/dist/claude-cli-check.js +46 -10
  3. package/dist/headless.js +49 -4
  4. package/dist/resource-loader.d.ts +40 -0
  5. package/dist/resource-loader.js +32 -13
  6. package/dist/resources/extensions/browser-tools/capture.js +9 -0
  7. package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  8. package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  9. package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  10. package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
  11. package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
  12. package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
  13. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
  14. package/dist/resources/extensions/github-sync/templates.js +103 -0
  15. package/dist/resources/extensions/google-search/index.js +3 -2
  16. package/dist/resources/extensions/gsd/auto/loop.js +124 -2
  17. package/dist/resources/extensions/gsd/auto/phases.js +57 -39
  18. package/dist/resources/extensions/gsd/auto/session.js +6 -2
  19. package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
  20. package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
  21. package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
  22. package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
  23. package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
  24. package/dist/resources/extensions/gsd/auto-start.js +107 -29
  25. package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
  26. package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
  27. package/dist/resources/extensions/gsd/auto.js +76 -21
  28. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
  30. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
  31. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
  32. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
  33. package/dist/resources/extensions/gsd/component-loader.js +447 -0
  34. package/dist/resources/extensions/gsd/component-types.js +69 -0
  35. package/dist/resources/extensions/gsd/context-store.js +23 -7
  36. package/dist/resources/extensions/gsd/detection.js +49 -1
  37. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
  38. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  39. package/dist/resources/extensions/gsd/forensics.js +106 -0
  40. package/dist/resources/extensions/gsd/gate-registry.js +2 -2
  41. package/dist/resources/extensions/gsd/git-constants.js +28 -1
  42. package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
  43. package/dist/resources/extensions/gsd/git-service.js +126 -2
  44. package/dist/resources/extensions/gsd/gsd-db.js +6 -3
  45. package/dist/resources/extensions/gsd/guided-flow.js +39 -13
  46. package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
  47. package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
  48. package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
  49. package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
  50. package/dist/resources/extensions/gsd/model-router.js +6 -0
  51. package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
  52. package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
  53. package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
  54. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  55. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  56. package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  57. package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  58. package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
  59. package/dist/resources/extensions/gsd/service-tier.js +5 -2
  60. package/dist/resources/extensions/gsd/session-lock.js +19 -10
  61. package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
  62. package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
  63. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
  64. package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
  65. package/dist/resources/extensions/gsd/state.js +69 -58
  66. package/dist/resources/extensions/gsd/sync-lock.js +98 -42
  67. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
  68. package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
  69. package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
  70. package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
  71. package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
  72. package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
  73. package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
  74. package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
  75. package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
  76. package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
  77. package/dist/resources/extensions/gsd/uok/writer.js +82 -0
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
  79. package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
  80. package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
  81. package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
  82. package/dist/resources/extensions/mcp-client/index.js +3 -1
  83. package/dist/resources/extensions/ollama/index.js +5 -1
  84. package/dist/resources/extensions/remote-questions/manager.js +11 -5
  85. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  86. package/dist/web/standalone/.next/BUILD_ID +1 -1
  87. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  88. package/dist/web/standalone/.next/build-manifest.json +2 -2
  89. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  90. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  91. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  115. package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
  116. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  117. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
  119. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  120. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  121. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  122. package/package.json +2 -3
  123. package/packages/daemon/package.json +2 -2
  124. package/packages/daemon/src/logger.ts +4 -3
  125. package/packages/mcp-server/dist/server.d.ts +24 -0
  126. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  127. package/packages/mcp-server/dist/server.js +88 -87
  128. package/packages/mcp-server/dist/server.js.map +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +15 -6
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/package.json +2 -2
  133. package/packages/mcp-server/src/mcp-server.test.ts +25 -3
  134. package/packages/mcp-server/src/readers/graph.test.ts +87 -15
  135. package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
  136. package/packages/mcp-server/src/server.ts +131 -105
  137. package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
  138. package/packages/mcp-server/src/workflow-tools.ts +19 -6
  139. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  140. package/packages/native/package.json +2 -2
  141. package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
  142. package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
  143. package/packages/native/src/__tests__/ps.test.mjs +14 -8
  144. package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
  145. package/packages/native/src/__tests__/truncate.test.mjs +17 -2
  146. package/packages/pi-agent-core/package.json +1 -1
  147. package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
  148. package/packages/pi-agent-core/src/agent.test.ts +96 -102
  149. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  150. package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
  151. package/packages/pi-ai/dist/models/capability-patches.js +9 -2
  152. package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
  153. package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
  154. package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
  155. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
  156. package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
  158. package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
  159. package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
  160. package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
  161. package/packages/pi-ai/dist/models/generated/openai.js +17 -0
  162. package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
  163. package/packages/pi-ai/dist/models.generated.test.js +43 -70
  164. package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
  165. package/packages/pi-ai/dist/models.test.js +36 -11
  166. package/packages/pi-ai/dist/models.test.js.map +1 -1
  167. package/packages/pi-ai/package.json +1 -1
  168. package/packages/pi-ai/scripts/generate-models.ts +44 -0
  169. package/packages/pi-ai/src/models/capability-patches.ts +10 -2
  170. package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
  171. package/packages/pi-ai/src/models/generated/openai.ts +17 -0
  172. package/packages/pi-ai/src/models.generated.test.ts +46 -73
  173. package/packages/pi-ai/src/models.test.ts +48 -11
  174. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  175. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
  176. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  177. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js +75 -12
  178. package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
  179. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
  180. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  181. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
  182. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
  184. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
  186. package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
  188. package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
  190. package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  192. package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
  193. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  194. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
  195. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
  197. package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
  198. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
  199. package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
  200. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
  201. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  202. package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
  203. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  204. package/packages/pi-coding-agent/dist/index.d.ts +1 -0
  205. package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
  206. package/packages/pi-coding-agent/dist/index.js +1 -0
  207. package/packages/pi-coding-agent/dist/index.js.map +1 -1
  208. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
  209. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
  211. package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
  212. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  213. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
  214. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  215. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
  217. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
  219. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  220. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
  221. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
  224. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  225. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +105 -13
  226. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
  230. package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
  231. package/packages/pi-coding-agent/package.json +1 -1
  232. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
  233. package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
  234. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
  235. package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
  236. package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
  237. package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
  238. package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
  239. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
  240. package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
  241. package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
  242. package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
  243. package/packages/pi-coding-agent/src/index.ts +1 -0
  244. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
  245. package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
  246. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
  247. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
  248. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
  249. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
  250. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
  251. package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
  252. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  253. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
  254. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  255. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
  256. package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
  257. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
  258. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
  259. package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
  260. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  261. package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
  262. package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
  263. package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
  264. package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
  265. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
  266. package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
  267. package/packages/pi-tui/dist/components/editor.d.ts +14 -0
  268. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/components/editor.js +19 -0
  270. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  271. package/packages/pi-tui/dist/components/image.test.js +6 -5
  272. package/packages/pi-tui/dist/components/image.test.js.map +1 -1
  273. package/packages/pi-tui/dist/editor-component.d.ts +2 -0
  274. package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
  275. package/packages/pi-tui/dist/editor-component.js.map +1 -1
  276. package/packages/pi-tui/package.json +1 -1
  277. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
  278. package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
  279. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
  280. package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
  281. package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
  282. package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
  283. package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
  284. package/packages/pi-tui/src/components/editor.ts +22 -0
  285. package/packages/pi-tui/src/components/image.test.ts +10 -5
  286. package/packages/pi-tui/src/editor-component.ts +3 -0
  287. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  288. package/packages/rpc-client/dist/rpc-client.test.js +101 -51
  289. package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
  290. package/packages/rpc-client/package.json +1 -1
  291. package/packages/rpc-client/src/rpc-client.test.ts +109 -52
  292. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  293. package/pkg/package.json +1 -1
  294. package/scripts/install.js +15 -1
  295. package/src/resources/extensions/browser-tools/capture.ts +12 -0
  296. package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
  297. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
  298. package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
  299. package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
  300. package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
  301. package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
  302. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
  303. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
  304. package/src/resources/extensions/github-sync/templates.ts +151 -0
  305. package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
  306. package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
  307. package/src/resources/extensions/google-search/index.ts +3 -2
  308. package/src/resources/extensions/gsd/auto/loop.ts +142 -2
  309. package/src/resources/extensions/gsd/auto/phases.ts +62 -38
  310. package/src/resources/extensions/gsd/auto/session.ts +7 -2
  311. package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
  312. package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
  313. package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
  314. package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
  315. package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
  316. package/src/resources/extensions/gsd/auto-start.ts +127 -9
  317. package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
  318. package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
  319. package/src/resources/extensions/gsd/auto.ts +90 -23
  320. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
  321. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
  322. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
  323. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
  324. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
  325. package/src/resources/extensions/gsd/component-loader.ts +598 -0
  326. package/src/resources/extensions/gsd/component-types.ts +362 -0
  327. package/src/resources/extensions/gsd/context-store.ts +25 -8
  328. package/src/resources/extensions/gsd/detection.ts +58 -1
  329. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
  330. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  331. package/src/resources/extensions/gsd/forensics.ts +118 -1
  332. package/src/resources/extensions/gsd/gate-registry.ts +2 -2
  333. package/src/resources/extensions/gsd/git-constants.ts +30 -1
  334. package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
  335. package/src/resources/extensions/gsd/git-service.ts +149 -2
  336. package/src/resources/extensions/gsd/gsd-db.ts +6 -3
  337. package/src/resources/extensions/gsd/guided-flow.ts +57 -14
  338. package/src/resources/extensions/gsd/journal.ts +11 -1
  339. package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
  340. package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
  341. package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
  342. package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
  343. package/src/resources/extensions/gsd/model-router.ts +6 -0
  344. package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
  345. package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
  346. package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
  347. package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
  348. package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
  349. package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
  350. package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
  351. package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
  352. package/src/resources/extensions/gsd/service-tier.ts +5 -2
  353. package/src/resources/extensions/gsd/session-lock.ts +20 -10
  354. package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
  355. package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
  356. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
  357. package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
  358. package/src/resources/extensions/gsd/state.ts +76 -66
  359. package/src/resources/extensions/gsd/sync-lock.ts +97 -39
  360. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
  361. package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
  362. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
  363. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
  364. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
  365. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
  366. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
  367. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
  368. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
  369. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
  370. package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
  371. package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
  372. package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
  373. package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
  374. package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
  375. package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
  376. package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
  377. package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
  378. package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
  379. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
  380. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
  381. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
  382. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
  383. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
  384. package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
  385. package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
  386. package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
  387. package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
  388. package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
  389. package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
  390. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
  391. package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
  392. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
  393. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
  394. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
  395. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
  396. package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
  397. package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
  398. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
  399. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
  400. package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
  401. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
  402. package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
  403. package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
  404. package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
  405. package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
  406. package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
  407. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
  408. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
  409. package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
  410. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
  411. package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
  412. package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
  413. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
  414. package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
  415. package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
  416. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
  417. package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
  418. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
  419. package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
  420. package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
  421. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
  422. package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
  423. package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
  424. package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
  425. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
  426. package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
  427. package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
  428. package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
  429. package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
  430. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
  431. package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
  432. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
  433. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
  434. package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
  435. package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
  436. package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
  437. package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
  438. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
  439. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
  440. package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
  441. package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
  442. package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
  443. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
  444. package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
  445. package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
  446. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
  447. package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
  448. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
  449. package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
  451. package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
  452. package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
  453. package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
  454. package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
  455. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
  456. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
  457. package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
  458. package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
  459. package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
  460. package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
  461. package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
  462. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
  463. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
  464. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
  465. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
  466. package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
  467. package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
  468. package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
  469. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
  470. package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
  471. package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
  472. package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
  473. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
  474. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
  475. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
  476. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
  477. package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
  478. package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
  479. package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
  480. package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
  481. package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
  482. package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
  483. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
  484. package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
  485. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
  486. package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
  487. package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
  488. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
  489. package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
  490. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
  491. package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
  492. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
  493. package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
  494. package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
  495. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
  496. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
  497. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
  498. package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
  499. package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
  500. package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
  501. package/src/resources/extensions/gsd/types.ts +3 -3
  502. package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
  503. package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
  504. package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
  505. package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
  506. package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
  507. package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
  508. package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
  509. package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
  510. package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
  511. package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
  512. package/src/resources/extensions/gsd/uok/writer.ts +113 -0
  513. package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
  514. package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
  515. package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
  516. package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
  517. package/src/resources/extensions/mcp-client/index.ts +3 -1
  518. package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
  519. package/src/resources/extensions/ollama/index.ts +5 -1
  520. package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
  521. package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
  522. package/src/resources/extensions/remote-questions/manager.ts +36 -4
  523. package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
  524. package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
  525. package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
  526. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
  527. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
  528. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
  529. package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
  530. package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
  531. package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
  532. package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
  533. package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
  534. package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
  535. package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
  536. package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
  537. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
  538. package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
  539. package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
  540. package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
  541. package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
  542. package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
  543. package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
  544. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
  545. /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
@@ -19,9 +19,11 @@ import { getPendingGatesForTurn } from "./gsd-db.js";
19
19
  import { assertGateCoverage, getGatesForTurn, } from "./gate-registry.js";
20
20
  import { formatDecisionsCompact, formatRequirementsCompact } from "./structured-data-formatter.js";
21
21
  import { readPhaseAnchor, formatAnchorForPrompt } from "./phase-anchor.js";
22
+ import { composeInlinedContext } from "./unit-context-composer.js";
22
23
  import { logWarning } from "./workflow-logger.js";
23
24
  import { inlineGraphSubgraph } from "./graph-context.js";
24
25
  import { buildExtractionStepsBlock } from "./commands-extract-learnings.js";
26
+ import { warnIfManifestHasMissingSkills } from "./skill-manifest.js";
25
27
  // ─── Preamble Cap ─────────────────────────────────────────────────────────────
26
28
  /**
27
29
  * Historical static ceiling for the preamble cap. Kept as an upper bound even
@@ -201,6 +203,87 @@ export async function inlineFileSmart(absPath, relPath, label, query, threshold
201
203
  const truncated = truncateAtSectionBoundary(content, threshold).content;
202
204
  return `### ${label}\nSource: \`${relPath}\`\n\n${truncated}`;
203
205
  }
206
+ /**
207
+ * Compact slice-summary excerpt for milestone-level closers (#4780).
208
+ *
209
+ * Emits the frontmatter fields + short body section heads rather than the
210
+ * full SUMMARY.md body, and keeps the source path in the header so the
211
+ * closer agent can Read the full file on demand when drafting LEARNINGS.
212
+ *
213
+ * Scope: designed for `buildCompleteMilestonePrompt`, which previously
214
+ * inlined the full SUMMARY per slice and routinely paid ~300–500K tokens
215
+ * per close when the narrative was never synthesized. Not used by
216
+ * `buildValidateMilestonePrompt` yet — validate needs fuller verification
217
+ * evidence; follow-up PR can extend or parameterize.
218
+ *
219
+ * If parsing fails (unrecognizable frontmatter, missing id, etc.) the
220
+ * function falls back to `inlineFile` so the closer loses no information.
221
+ */
222
+ export async function buildSliceSummaryExcerpt(absPath, relPath, sid) {
223
+ const header = `### ${sid} Summary (excerpt)\nSource: \`${relPath}\``;
224
+ const content = absPath ? await loadFile(absPath) : null;
225
+ if (!content) {
226
+ return `${header}\n\n_(not found — file does not exist yet)_`;
227
+ }
228
+ try {
229
+ const s = parseSummary(content);
230
+ if (!s.frontmatter.id) {
231
+ // Unrecognizable — fall back to full file so no context is lost.
232
+ return `### ${sid} Summary\nSource: \`${relPath}\`\n\n${content.trim()}`;
233
+ }
234
+ const lines = [header, ""];
235
+ if (s.title)
236
+ lines.push(`**Title:** ${s.title}`);
237
+ if (s.oneLiner)
238
+ lines.push(`**One-liner:** ${s.oneLiner}`);
239
+ if (s.frontmatter.verification_result) {
240
+ lines.push(`**Verification:** \`${s.frontmatter.verification_result}\``);
241
+ }
242
+ lines.push(`**Blockers:** ${s.frontmatter.blocker_discovered ? "⚠️ blocker recorded — Read full summary" : "none"}`);
243
+ if (s.frontmatter.duration)
244
+ lines.push(`**Duration:** ${s.frontmatter.duration}`);
245
+ if (s.frontmatter.provides.length > 0)
246
+ lines.push(`**Provides:** ${s.frontmatter.provides.join("; ")}`);
247
+ if (s.frontmatter.affects.length > 0)
248
+ lines.push(`**Affects:** ${s.frontmatter.affects.join("; ")}`);
249
+ if (s.frontmatter.key_decisions.length > 0)
250
+ lines.push(`**Key decisions:** ${s.frontmatter.key_decisions.join("; ")}`);
251
+ if (s.frontmatter.patterns_established.length > 0)
252
+ lines.push(`**Patterns established:** ${s.frontmatter.patterns_established.join("; ")}`);
253
+ if (s.frontmatter.key_files.length > 0) {
254
+ const files = s.frontmatter.key_files.slice(0, 8);
255
+ const more = s.frontmatter.key_files.length > files.length ? ` (+${s.frontmatter.key_files.length - files.length} more)` : "";
256
+ lines.push(`**Key files:** ${files.join(", ")}${more}`);
257
+ }
258
+ // Cap section bodies (coderabbit review on #4908): if any of these
259
+ // narrative sections balloon, excerpt mode still inflates and
260
+ // undermines the token-reduction goal. 800 chars (~200 tokens) is
261
+ // enough to carry intent; the closer agent Reads the full file when
262
+ // it needs richer context for LEARNINGS synthesis.
263
+ const SECTION_CAP_CHARS = 800;
264
+ const capSection = (body) => {
265
+ const trimmed = body.trim();
266
+ if (trimmed.length <= SECTION_CAP_CHARS)
267
+ return trimmed;
268
+ return `${trimmed.slice(0, SECTION_CAP_CHARS)}\n… (truncated — see full \`${relPath}\`)`;
269
+ };
270
+ if (s.deviations && s.deviations.trim()) {
271
+ lines.push("", "#### Deviations", capSection(s.deviations));
272
+ }
273
+ if (s.knownLimitations && s.knownLimitations.trim()) {
274
+ lines.push("", "#### Known limitations", capSection(s.knownLimitations));
275
+ }
276
+ if (s.followUps && s.followUps.trim()) {
277
+ lines.push("", "#### Follow-ups", capSection(s.followUps));
278
+ }
279
+ lines.push("", `> **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.`);
280
+ return lines.join("\n");
281
+ }
282
+ catch {
283
+ // Defensive — any parse failure falls back to full inline.
284
+ return `### ${sid} Summary\nSource: \`${relPath}\`\n\n${content.trim()}`;
285
+ }
286
+ }
204
287
  /**
205
288
  * Load and inline dependency slice summaries (full content, not just paths).
206
289
  */
@@ -446,6 +529,40 @@ export async function inlineKnowledgeScoped(base, keywords) {
446
529
  return null;
447
530
  return `### Project Knowledge (scoped)\nSource: \`${relGsdRootFile("KNOWLEDGE")}\`\n\n${scoped.trim()}`;
448
531
  }
532
+ /**
533
+ * Budget-capped knowledge inline for milestone-level prompt assembly.
534
+ *
535
+ * Addresses issue #4719: the six milestone-phase prompts (research-milestone,
536
+ * plan-milestone, complete-slice, complete-milestone, validate-milestone,
537
+ * reassess-roadmap) previously injected the full KNOWLEDGE.md (~226KB for a
538
+ * real project) on every invocation. This helper scopes by caller-supplied
539
+ * keywords and caps the payload at `maxChars` (default 30,000 chars).
540
+ *
541
+ * Returns null when no KNOWLEDGE.md exists or no entries match any keyword.
542
+ */
543
+ export async function inlineKnowledgeBudgeted(base, keywords, options) {
544
+ const DEFAULT_MAX_CHARS = 30_000;
545
+ const HARD_MAX_CHARS = 100_000;
546
+ const raw = Number(options?.maxChars ?? DEFAULT_MAX_CHARS);
547
+ const maxChars = Number.isFinite(raw)
548
+ ? Math.max(0, Math.min(Math.floor(raw), HARD_MAX_CHARS))
549
+ : DEFAULT_MAX_CHARS;
550
+ const knowledgePath = resolveGsdRootFile(base, "KNOWLEDGE");
551
+ if (!existsSync(knowledgePath))
552
+ return null;
553
+ const content = await loadFile(knowledgePath);
554
+ if (!content)
555
+ return null;
556
+ const { queryKnowledge } = await import("./context-store.js");
557
+ const scoped = await queryKnowledge(content, keywords);
558
+ if (!scoped)
559
+ return null;
560
+ const trimmed = scoped.trim();
561
+ const truncated = trimmed.length > maxChars
562
+ ? `${trimmed.slice(0, maxChars)}\n\n[...truncated ${trimmed.length - maxChars} chars; rerun with narrower scope if needed]`
563
+ : trimmed;
564
+ return `### Project Knowledge (scoped)\nSource: \`${relGsdRootFile("KNOWLEDGE")}\`\n\n${truncated}`;
565
+ }
449
566
  /**
450
567
  * Inline a roadmap excerpt for a specific slice.
451
568
  * Reads full roadmap, extracts minimal excerpt with header + predecessor + target row.
@@ -559,10 +676,23 @@ function formatSkillActivationBlock(skillNames) {
559
676
  return `<skill_activation>${calls}.</skill_activation>`;
560
677
  }
561
678
  export function buildSkillActivationBlock(params) {
562
- const prefs = params.preferences ?? loadEffectiveGSDPreferences()?.preferences;
679
+ const prefs = params.preferences ?? loadEffectiveGSDPreferences(params.base)?.preferences;
563
680
  const contextTokens = tokenizeSkillContext(params.milestoneId, params.milestoneTitle, params.sliceId, params.sliceTitle, params.taskId, params.taskTitle);
564
- const visibleSkills = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
681
+ const loaded = (typeof getLoadedSkills === 'function' ? getLoadedSkills() : []).filter(skill => !skill.disableModelInvocation);
682
+ // Skill activation here is driven entirely by explicit sources
683
+ // (always_use_skills, prefer_skills, skill_rules, task-plan skills_used).
684
+ // Every match is an explicit user/project intent and must not be dropped
685
+ // by the unit-type manifest — user intent is stronger signal than
686
+ // defaults. The manifest's real home is the skill catalog rendering
687
+ // layer (pi-coding-agent `formatSkillsForPrompt`); that wiring is tracked
688
+ // as the "load-time short-circuit" follow-up to RFC #4779.
689
+ //
690
+ // `unitType` stays plumbed so the strict-mode warning can surface
691
+ // manifest entries that reference uninstalled skills, and so the
692
+ // activation-block site is ready to opt in once PR B lands.
693
+ const visibleSkills = loaded;
565
694
  const installedNames = new Set(visibleSkills.map(skill => normalizeSkillReference(skill.name)));
695
+ warnIfManifestHasMissingSkills(params.unitType, installedNames);
566
696
  const avoided = new Set(resolvePreferenceSkillNames(prefs?.avoid_skills ?? [], params.base));
567
697
  const matched = new Set();
568
698
  for (const name of resolvePreferenceSkillNames(prefs?.always_use_skills ?? [], params.base)) {
@@ -945,30 +1075,63 @@ export async function buildDiscussMilestonePrompt(mid, midTitle, base, structure
945
1075
  return basePrompt;
946
1076
  }
947
1077
  export async function buildResearchMilestonePrompt(mid, midTitle, base) {
948
- const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
949
- const contextRel = relMilestoneFile(base, mid, "CONTEXT");
950
- const inlined = [];
951
- inlined.push(await inlineFile(contextPath, contextRel, "Milestone Context"));
952
- const projectInline = await inlineProjectFromDb(base);
953
- if (projectInline)
954
- inlined.push(projectInline);
955
- const requirementsInline = await inlineRequirementsFromDb(base, mid);
956
- if (requirementsInline)
957
- inlined.push(requirementsInline);
958
- const decisionsInline = await inlineDecisionsFromDb(base, mid);
959
- if (decisionsInline)
960
- inlined.push(decisionsInline);
961
- const knowledgeInlineRM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
962
- if (knowledgeInlineRM)
963
- inlined.push(knowledgeInlineRM);
964
- inlined.push(inlineTemplate("research", "Research"));
965
- const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`);
1078
+ // #4782 phase 3: research-milestone migrated through the composer.
1079
+ // Declared inline order: milestone-context, project, requirements,
1080
+ // decisions, templates. Knowledge stays outside the composer
1081
+ // (budget-driven, scoped by keyword extraction — future phase folds
1082
+ // policy-driven blocks in).
1083
+ const resolveArtifact = async (key) => {
1084
+ switch (key) {
1085
+ case "milestone-context": {
1086
+ const p = resolveMilestoneFile(base, mid, "CONTEXT");
1087
+ const r = relMilestoneFile(base, mid, "CONTEXT");
1088
+ return await inlineFile(p, r, "Milestone Context");
1089
+ }
1090
+ case "project":
1091
+ return await inlineProjectFromDb(base);
1092
+ case "requirements":
1093
+ return await inlineRequirementsFromDb(base, mid);
1094
+ case "decisions":
1095
+ return await inlineDecisionsFromDb(base, mid);
1096
+ case "templates":
1097
+ return inlineTemplate("research", "Research");
1098
+ default:
1099
+ return null;
1100
+ }
1101
+ };
1102
+ const composed = await composeInlinedContext("research-milestone", resolveArtifact);
1103
+ // Knowledge block stays outside the composer — budgeted, scoped via
1104
+ // keyword extraction (#4719). Inserted between decisions and the
1105
+ // templates block to match the pre-migration output order. We split
1106
+ // the composer output around the templates section to preserve that
1107
+ // ordering.
1108
+ const knowledgeInlineRM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
1109
+ const parts = [];
1110
+ if (knowledgeInlineRM && composed) {
1111
+ // Insert knowledge before the template block so the overall order is:
1112
+ // milestone-context → project → requirements → decisions → KNOWLEDGE → research template
1113
+ const idx = composed.lastIndexOf("### Output Template:");
1114
+ if (idx > 0) {
1115
+ const before = composed.slice(0, idx).replace(/\n\n---\n\n$/, "");
1116
+ const after = composed.slice(idx);
1117
+ parts.push(before, knowledgeInlineRM, after);
1118
+ }
1119
+ else {
1120
+ parts.push(composed, knowledgeInlineRM);
1121
+ }
1122
+ }
1123
+ else if (composed) {
1124
+ parts.push(composed);
1125
+ if (knowledgeInlineRM)
1126
+ parts.push(knowledgeInlineRM);
1127
+ }
1128
+ const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${parts.join("\n\n---\n\n")}`);
966
1129
  const outputRelPath = relMilestoneFile(base, mid, "RESEARCH");
967
1130
  return loadPrompt("research-milestone", {
968
1131
  workingDirectory: base,
969
1132
  milestoneId: mid, milestoneTitle: midTitle,
970
1133
  milestonePath: relMilestonePath(base, mid),
971
- contextPath: contextRel,
1134
+ contextPath: relMilestoneFile(base, mid, "CONTEXT"),
972
1135
  outputPath: join(base, outputRelPath),
973
1136
  inlinedContext,
974
1137
  skillActivation: buildSkillActivationBlock({
@@ -976,6 +1139,7 @@ export async function buildResearchMilestonePrompt(mid, midTitle, base) {
976
1139
  milestoneId: mid,
977
1140
  milestoneTitle: midTitle,
978
1141
  extraContext: [inlinedContext],
1142
+ unitType: "research-milestone",
979
1143
  }),
980
1144
  ...buildSkillDiscoveryVars(),
981
1145
  });
@@ -1015,7 +1179,8 @@ export async function buildPlanMilestonePrompt(mid, midTitle, base, level) {
1015
1179
  const queueInline = await inlineFileSmart(queuePath, relGsdRootFile("QUEUE"), "Project Queue", `${mid} ${midTitle}`);
1016
1180
  inlined.push(queueInline);
1017
1181
  }
1018
- const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
1182
+ // Scoped + budgeted see issue #4719
1183
+ const knowledgeInlinePM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
1019
1184
  if (knowledgeInlinePM)
1020
1185
  inlined.push(knowledgeInlinePM);
1021
1186
  inlined.push(inlineTemplate("roadmap", "Roadmap"));
@@ -1050,6 +1215,7 @@ export async function buildPlanMilestonePrompt(mid, midTitle, base, level) {
1050
1215
  milestoneId: mid,
1051
1216
  milestoneTitle: midTitle,
1052
1217
  extraContext: [inlinedContext],
1218
+ unitType: "plan-milestone",
1053
1219
  }),
1054
1220
  ...buildSkillDiscoveryVars(),
1055
1221
  });
@@ -1123,6 +1289,7 @@ export async function buildResearchSlicePrompt(mid, _midTitle, sid, sTitle, base
1123
1289
  sliceId: sid,
1124
1290
  sliceTitle: sTitle,
1125
1291
  extraContext: [inlinedContext, depContent],
1292
+ unitType: "research-slice",
1126
1293
  }),
1127
1294
  ...buildSkillDiscoveryVars(),
1128
1295
  });
@@ -1209,6 +1376,7 @@ async function renderSlicePrompt(options) {
1209
1376
  sliceId: sid,
1210
1377
  sliceTitle: sTitle,
1211
1378
  extraContext: [inlinedContext, depContent],
1379
+ unitType: promptTemplate,
1212
1380
  }),
1213
1381
  ...extraVars,
1214
1382
  });
@@ -1417,51 +1585,95 @@ export async function buildExecuteTaskPrompt(mid, sid, sTitle, tid, tTitle, base
1417
1585
  }),
1418
1586
  });
1419
1587
  }
1420
- export async function buildCompleteSlicePrompt(mid, _midTitle, sid, sTitle, base, level) {
1588
+ export async function buildCompleteSlicePrompt(mid, midTitle, sid, sTitle, base, level) {
1421
1589
  const inlineLevel = level ?? resolveInlineLevel();
1422
- const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
1423
- const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
1424
- const slicePlanPath = resolveSliceFile(base, mid, sid, "PLAN");
1425
- const slicePlanRel = relSliceFile(base, mid, sid, "PLAN");
1426
- const sliceContextPath = resolveSliceFile(base, mid, sid, "CONTEXT");
1427
- const sliceContextRel = relSliceFile(base, mid, sid, "CONTEXT");
1428
- const inlined = [];
1429
- inlined.push(await inlineFile(roadmapPath, roadmapRel, "Milestone Roadmap"));
1430
- const sliceCtxInline = await inlineFileOptional(sliceContextPath, sliceContextRel, "Slice Context (from discussion)");
1431
- if (sliceCtxInline)
1432
- inlined.push(sliceCtxInline);
1433
- inlined.push(await inlineFile(slicePlanPath, slicePlanRel, "Slice Plan"));
1434
- if (inlineLevel !== "minimal") {
1435
- const requirementsInline = await inlineRequirementsFromDb(base, mid, sid, inlineLevel);
1436
- if (requirementsInline)
1437
- inlined.push(requirementsInline);
1438
- }
1439
- const knowledgeInlineCS = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
1440
- if (knowledgeInlineCS)
1441
- inlined.push(knowledgeInlineCS);
1442
- // Inline all task summaries for this slice
1443
- const tDir = resolveTasksDir(base, mid, sid);
1444
- if (tDir) {
1445
- const summaryFiles = resolveTaskFiles(tDir, "SUMMARY").sort();
1446
- for (const file of summaryFiles) {
1447
- const absPath = join(tDir, file);
1448
- const content = await loadFile(absPath);
1449
- const sRel = relSlicePath(base, mid, sid);
1450
- const relPath = `${sRel}/tasks/${file}`;
1451
- if (content) {
1452
- inlined.push(`### Task Summary: ${file.replace(/-SUMMARY\.md$/i, "")}\nSource: \`${relPath}\`\n\n${content.trim()}`);
1590
+ // #4782 phase 3: complete-slice migrated through composer. Manifest
1591
+ // declares [roadmap, slice-context, slice-plan, requirements,
1592
+ // prior-task-summaries, templates]. Overrides prepend and knowledge
1593
+ // splice stay imperative they need the composer v2 contract
1594
+ // (computed + prepend blocks; see RFC #4924).
1595
+ const resolveArtifact = async (key) => {
1596
+ switch (key) {
1597
+ case "roadmap": {
1598
+ const p = resolveMilestoneFile(base, mid, "ROADMAP");
1599
+ const r = relMilestoneFile(base, mid, "ROADMAP");
1600
+ return await inlineFile(p, r, "Milestone Roadmap");
1453
1601
  }
1602
+ case "slice-context": {
1603
+ const p = resolveSliceFile(base, mid, sid, "CONTEXT");
1604
+ const r = relSliceFile(base, mid, sid, "CONTEXT");
1605
+ return await inlineFileOptional(p, r, "Slice Context (from discussion)");
1606
+ }
1607
+ case "slice-plan": {
1608
+ const p = resolveSliceFile(base, mid, sid, "PLAN");
1609
+ const r = relSliceFile(base, mid, sid, "PLAN");
1610
+ return await inlineFile(p, r, "Slice Plan");
1611
+ }
1612
+ case "requirements":
1613
+ if (inlineLevel === "minimal")
1614
+ return null;
1615
+ return await inlineRequirementsFromDb(base, mid, sid, inlineLevel);
1616
+ case "prior-task-summaries": {
1617
+ const tDir = resolveTasksDir(base, mid, sid);
1618
+ if (!tDir)
1619
+ return null;
1620
+ const summaryFiles = resolveTaskFiles(tDir, "SUMMARY").sort();
1621
+ const sRel = relSlicePath(base, mid, sid);
1622
+ const blocks = [];
1623
+ for (const file of summaryFiles) {
1624
+ const absPath = join(tDir, file);
1625
+ const content = await loadFile(absPath);
1626
+ if (!content)
1627
+ continue;
1628
+ const relPath = `${sRel}/tasks/${file}`;
1629
+ blocks.push(`### Task Summary: ${file.replace(/-SUMMARY\.md$/i, "")}\nSource: \`${relPath}\`\n\n${content.trim()}`);
1630
+ }
1631
+ return blocks.length > 0 ? blocks.join("\n\n---\n\n") : null;
1632
+ }
1633
+ case "templates": {
1634
+ const parts = [inlineTemplate("slice-summary", "Slice Summary")];
1635
+ if (inlineLevel !== "minimal") {
1636
+ parts.push(inlineTemplate("uat", "UAT"));
1637
+ }
1638
+ return parts.join("\n\n---\n\n");
1639
+ }
1640
+ default:
1641
+ return null;
1642
+ }
1643
+ };
1644
+ const composed = await composeInlinedContext("complete-slice", resolveArtifact);
1645
+ // Knowledge splices in between requirements and prior-task-summaries
1646
+ // so overall order matches pre-migration: roadmap → slice-context →
1647
+ // slice-plan → requirements → KNOWLEDGE → task summaries → templates.
1648
+ const knowledgeInlineCS = await inlineKnowledgeBudgeted(base, [...extractKeywords(midTitle), ...extractKeywords(sTitle)]);
1649
+ let body = composed;
1650
+ if (knowledgeInlineCS && body) {
1651
+ // Splice knowledge right before the first "### Task Summary:" block
1652
+ // to preserve pre-migration ordering. If no task summaries exist,
1653
+ // splice before the templates block (which inlineTemplate emits as
1654
+ // "### Output Template: Slice Summary").
1655
+ const taskIdx = body.indexOf("### Task Summary:");
1656
+ const templatesIdx = body.lastIndexOf("### Output Template: Slice Summary");
1657
+ const spliceIdx = taskIdx > -1 ? taskIdx : templatesIdx;
1658
+ if (spliceIdx > 0) {
1659
+ const before = body.slice(0, spliceIdx).replace(/\n\n---\n\n$/, "");
1660
+ const after = body.slice(spliceIdx);
1661
+ body = [before, knowledgeInlineCS, after].join("\n\n---\n\n");
1662
+ }
1663
+ else {
1664
+ body = `${body}\n\n---\n\n${knowledgeInlineCS}`;
1454
1665
  }
1455
1666
  }
1456
- inlined.push(inlineTemplate("slice-summary", "Slice Summary"));
1457
- if (inlineLevel !== "minimal") {
1458
- inlined.push(inlineTemplate("uat", "UAT"));
1459
- }
1667
+ // Overrides section prepends to the top of the inlined context
1668
+ // standard pattern for slice-level builders (until composer v2 lands
1669
+ // the prepend contract).
1460
1670
  const completeActiveOverrides = await loadActiveOverrides(base);
1461
1671
  const completeOverridesInline = formatOverridesSection(completeActiveOverrides);
1462
- if (completeOverridesInline)
1463
- inlined.unshift(completeOverridesInline);
1464
- const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`);
1672
+ const finalBody = completeOverridesInline
1673
+ ? `${completeOverridesInline}\n\n---\n\n${body}`
1674
+ : body;
1675
+ const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${finalBody}`);
1676
+ const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
1465
1677
  const sliceRel = relSlicePath(base, mid, sid);
1466
1678
  const sliceSummaryPath = join(base, `${sliceRel}/${sid}-SUMMARY.md`);
1467
1679
  const sliceUatPath = join(base, `${sliceRel}/${sid}-UAT.md`);
@@ -1512,13 +1724,21 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
1512
1724
  }
1513
1725
  }
1514
1726
  const seenSlices = new Set();
1727
+ const summaryRelPaths = [];
1515
1728
  for (const sid of sliceIds) {
1516
1729
  if (seenSlices.has(sid))
1517
1730
  continue;
1518
1731
  seenSlices.add(sid);
1519
1732
  const summaryPath = resolveSliceFile(base, mid, sid, "SUMMARY");
1520
1733
  const summaryRel = relSliceFile(base, mid, sid, "SUMMARY");
1521
- inlined.push(await inlineFile(summaryPath, summaryRel, `${sid} Summary`));
1734
+ summaryRelPaths.push(summaryRel);
1735
+ // Compact excerpt instead of full inline (#4780). Closer Reads the
1736
+ // full file on-demand when synthesizing LEARNINGS narrative.
1737
+ inlined.push(await buildSliceSummaryExcerpt(summaryPath, summaryRel, sid));
1738
+ }
1739
+ if (summaryRelPaths.length > 0) {
1740
+ const pathList = summaryRelPaths.map(p => `- \`${p}\``).join("\n");
1741
+ inlined.push(`### 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}`);
1522
1742
  }
1523
1743
  // Inline root GSD files (skip for minimal — completion can read these if needed)
1524
1744
  if (inlineLevel !== "minimal") {
@@ -1532,7 +1752,8 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
1532
1752
  if (projectInline)
1533
1753
  inlined.push(projectInline);
1534
1754
  }
1535
- const knowledgeInlineCM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
1755
+ // Scoped + budgeted see issue #4719
1756
+ const knowledgeInlineCM = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
1536
1757
  if (knowledgeInlineCM)
1537
1758
  inlined.push(knowledgeInlineCM);
1538
1759
  // Inline milestone context file (milestone-level, not GSD root)
@@ -1564,6 +1785,7 @@ export async function buildCompleteMilestonePrompt(mid, midTitle, base, level) {
1564
1785
  milestoneId: mid,
1565
1786
  milestoneTitle: midTitle,
1566
1787
  extraContext: [inlinedContext],
1788
+ unitType: "complete-milestone",
1567
1789
  }),
1568
1790
  });
1569
1791
  }
@@ -1671,7 +1893,8 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
1671
1893
  if (projectInline)
1672
1894
  inlined.push(projectInline);
1673
1895
  }
1674
- const knowledgeInline = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
1896
+ // Scoped + budgeted see issue #4719
1897
+ const knowledgeInline = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
1675
1898
  if (knowledgeInline)
1676
1899
  inlined.push(knowledgeInline);
1677
1900
  // Inline milestone context file
@@ -1706,6 +1929,7 @@ export async function buildValidateMilestonePrompt(mid, midTitle, base, level) {
1706
1929
  milestoneId: mid,
1707
1930
  milestoneTitle: midTitle,
1708
1931
  extraContext: [inlinedContext],
1932
+ unitType: "validate-milestone",
1709
1933
  }),
1710
1934
  });
1711
1935
  }
@@ -1781,23 +2005,42 @@ export async function buildReplanSlicePrompt(mid, midTitle, sid, sTitle, base) {
1781
2005
  sliceId: sid,
1782
2006
  sliceTitle: sTitle,
1783
2007
  extraContext: [inlinedContext, captureContext],
2008
+ unitType: "replan-slice",
1784
2009
  }),
1785
2010
  });
1786
2011
  }
1787
2012
  export async function buildRunUatPrompt(mid, sliceId, uatPath, uatContent, base) {
1788
- const inlined = [];
1789
- inlined.push(await inlineFile(resolveSliceFile(base, mid, sliceId, "UAT"), uatPath, `${sliceId} UAT`));
1790
- const summaryPath = resolveSliceFile(base, mid, sliceId, "SUMMARY");
1791
- const summaryRel = relSliceFile(base, mid, sliceId, "SUMMARY");
1792
- if (summaryPath) {
1793
- const summaryInline = await inlineFileOptional(summaryPath, summaryRel, `${sliceId} Summary`);
1794
- if (summaryInline)
1795
- inlined.push(summaryInline);
1796
- }
1797
- const projectInline = await inlineProjectFromDb(base);
1798
- if (projectInline)
1799
- inlined.push(projectInline);
1800
- const inlinedContext = capPreamble(`## Inlined Context (preloaded do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`);
2013
+ // #4782 phase 3: run-uat migrated to compose its inlined context via
2014
+ // the manifest. Behavior-equivalent resolver dispatches to the same
2015
+ // inline* helpers as the pre-migration builder.
2016
+ const resolveArtifact = async (key) => {
2017
+ switch (key) {
2018
+ case "slice-uat": {
2019
+ // Use the in-memory snapshot the caller already loaded (#4925 review).
2020
+ // Re-reading from disk via inlineFile(p, uatPath, ...) would risk
2021
+ // drift between the inlined body and uatType (computed from
2022
+ // uatContent below) if the file changes mid-dispatch.
2023
+ const trimmed = uatContent.trim();
2024
+ if (!trimmed) {
2025
+ return `### ${sliceId} UAT\nSource: \`${uatPath}\`\n\n_(not found file does not exist yet)_`;
2026
+ }
2027
+ return `### ${sliceId} UAT\nSource: \`${uatPath}\`\n\n${trimmed}`;
2028
+ }
2029
+ case "slice-summary": {
2030
+ const p = resolveSliceFile(base, mid, sliceId, "SUMMARY");
2031
+ if (!p)
2032
+ return null;
2033
+ const r = relSliceFile(base, mid, sliceId, "SUMMARY");
2034
+ return await inlineFileOptional(p, r, `${sliceId} Summary`);
2035
+ }
2036
+ case "project":
2037
+ return await inlineProjectFromDb(base);
2038
+ default:
2039
+ return null;
2040
+ }
2041
+ };
2042
+ const composed = await composeInlinedContext("run-uat", resolveArtifact);
2043
+ const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${composed}`);
1801
2044
  const uatResultPath = join(base, relSliceFile(base, mid, sliceId, "ASSESSMENT"));
1802
2045
  const uatType = getUatType(uatContent);
1803
2046
  return loadPrompt("run-uat", {
@@ -1813,38 +2056,62 @@ export async function buildRunUatPrompt(mid, sliceId, uatPath, uatContent, base)
1813
2056
  milestoneId: mid,
1814
2057
  sliceId,
1815
2058
  extraContext: [inlinedContext],
2059
+ unitType: "run-uat",
1816
2060
  }),
1817
2061
  });
1818
2062
  }
1819
2063
  export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId, base, level) {
1820
2064
  const inlineLevel = level ?? resolveInlineLevel();
1821
- const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
1822
- const roadmapRel = relMilestoneFile(base, mid, "ROADMAP");
1823
- const summaryPath = resolveSliceFile(base, mid, completedSliceId, "SUMMARY");
1824
- const summaryRel = relSliceFile(base, mid, completedSliceId, "SUMMARY");
1825
- const sliceContextPath = resolveSliceFile(base, mid, completedSliceId, "CONTEXT");
1826
- const sliceContextRel = relSliceFile(base, mid, completedSliceId, "CONTEXT");
1827
- const inlined = [];
1828
- inlined.push(await inlineFile(roadmapPath, roadmapRel, "Current Roadmap"));
1829
- const sliceCtxInline = await inlineFileOptional(sliceContextPath, sliceContextRel, "Slice Context (from discussion)");
1830
- if (sliceCtxInline)
1831
- inlined.push(sliceCtxInline);
1832
- inlined.push(await inlineFile(summaryPath, summaryRel, `${completedSliceId} Summary`));
1833
- if (inlineLevel !== "minimal") {
1834
- const projectInline = await inlineProjectFromDb(base);
1835
- if (projectInline)
1836
- inlined.push(projectInline);
1837
- const requirementsInline = await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
1838
- if (requirementsInline)
1839
- inlined.push(requirementsInline);
1840
- const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
1841
- if (decisionsInline)
1842
- inlined.push(decisionsInline);
1843
- }
1844
- const knowledgeInlineRA = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
2065
+ // #4782 phase 2 pilot: reassess-roadmap is the first unit type to
2066
+ // compose its inlined context through the manifest-driven composer.
2067
+ // The resolver below dispatches artifact keys to the existing inline*
2068
+ // helpers, preserving identical output so the migration is
2069
+ // observable-equivalent. Knowledge stays outside the composer (it's
2070
+ // budget-driven, not manifest-driven) until a later phase formalizes
2071
+ // knowledge/memory policies as composer inputs.
2072
+ const resolveArtifact = async (key) => {
2073
+ switch (key) {
2074
+ case "roadmap": {
2075
+ const p = resolveMilestoneFile(base, mid, "ROADMAP");
2076
+ const r = relMilestoneFile(base, mid, "ROADMAP");
2077
+ return await inlineFile(p, r, "Current Roadmap");
2078
+ }
2079
+ case "slice-context": {
2080
+ const p = resolveSliceFile(base, mid, completedSliceId, "CONTEXT");
2081
+ const r = relSliceFile(base, mid, completedSliceId, "CONTEXT");
2082
+ return await inlineFileOptional(p, r, "Slice Context (from discussion)");
2083
+ }
2084
+ case "slice-summary": {
2085
+ const p = resolveSliceFile(base, mid, completedSliceId, "SUMMARY");
2086
+ const r = relSliceFile(base, mid, completedSliceId, "SUMMARY");
2087
+ return await inlineFile(p, r, `${completedSliceId} Summary`);
2088
+ }
2089
+ case "project":
2090
+ if (inlineLevel === "minimal")
2091
+ return null;
2092
+ return await inlineProjectFromDb(base);
2093
+ case "requirements":
2094
+ if (inlineLevel === "minimal")
2095
+ return null;
2096
+ return await inlineRequirementsFromDb(base, mid, undefined, inlineLevel);
2097
+ case "decisions":
2098
+ if (inlineLevel === "minimal")
2099
+ return null;
2100
+ return await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
2101
+ default:
2102
+ return null;
2103
+ }
2104
+ };
2105
+ const composed = await composeInlinedContext("reassess-roadmap", resolveArtifact);
2106
+ const parts = [];
2107
+ if (composed)
2108
+ parts.push(composed);
2109
+ // Knowledge block stays outside the composer — budgeted, scoped via
2110
+ // keyword extraction (#4719). Future phase folds it in.
2111
+ const knowledgeInlineRA = await inlineKnowledgeBudgeted(base, extractKeywords(midTitle));
1845
2112
  if (knowledgeInlineRA)
1846
- inlined.push(knowledgeInlineRA);
1847
- const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${inlined.join("\n\n---\n\n")}`);
2113
+ parts.push(knowledgeInlineRA);
2114
+ const inlinedContext = capPreamble(`## Inlined Context (preloaded — do not re-read these files)\n\n${parts.join("\n\n---\n\n")}`);
1848
2115
  const assessmentPath = join(base, relSliceFile(base, mid, completedSliceId, "ASSESSMENT"));
1849
2116
  // Build deferred captures context for reassess prompt
1850
2117
  let deferredCaptures = "(none)";
@@ -1864,7 +2131,7 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
1864
2131
  milestoneId: mid,
1865
2132
  milestoneTitle: midTitle,
1866
2133
  completedSliceId,
1867
- roadmapPath: roadmapRel,
2134
+ roadmapPath: relMilestoneFile(base, mid, "ROADMAP"),
1868
2135
  assessmentPath,
1869
2136
  inlinedContext,
1870
2137
  deferredCaptures,
@@ -1874,6 +2141,7 @@ export async function buildReassessRoadmapPrompt(mid, midTitle, completedSliceId
1874
2141
  milestoneId: mid,
1875
2142
  milestoneTitle: midTitle,
1876
2143
  extraContext: [inlinedContext, deferredCaptures],
2144
+ unitType: "reassess-roadmap",
1877
2145
  }),
1878
2146
  });
1879
2147
  }