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
@@ -0,0 +1,58 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { gsdRoot } from "../paths.js";
4
+ function parityLogPath(basePath) {
5
+ return join(gsdRoot(basePath), "runtime", "uok-parity.jsonl");
6
+ }
7
+ function reportPath(basePath) {
8
+ return join(gsdRoot(basePath), "runtime", "uok-parity-report.json");
9
+ }
10
+ function increment(bucket, key) {
11
+ const normalized = key && key.trim().length > 0 ? key : "unknown";
12
+ bucket[normalized] = (bucket[normalized] ?? 0) + 1;
13
+ }
14
+ export function parseParityEvents(raw) {
15
+ return raw
16
+ .split("\n")
17
+ .filter(Boolean)
18
+ .map((line) => {
19
+ try {
20
+ return JSON.parse(line);
21
+ }
22
+ catch {
23
+ return { status: "error", error: "invalid parity json line" };
24
+ }
25
+ });
26
+ }
27
+ export function buildParityReport(events, sourcePath) {
28
+ const paths = {};
29
+ const statuses = {};
30
+ const criticalMismatches = [];
31
+ let fallbackInvocations = 0;
32
+ for (const event of events) {
33
+ increment(paths, event.path);
34
+ increment(statuses, event.status);
35
+ if (event.path === "legacy-fallback")
36
+ fallbackInvocations += 1;
37
+ if (event.status === "error") {
38
+ criticalMismatches.push(event.error ?? "parity event reported error");
39
+ }
40
+ }
41
+ return {
42
+ generatedAt: new Date().toISOString(),
43
+ sourcePath,
44
+ totalEvents: events.length,
45
+ paths,
46
+ statuses,
47
+ criticalMismatches,
48
+ fallbackInvocations,
49
+ };
50
+ }
51
+ export function writeParityReport(basePath) {
52
+ const sourcePath = parityLogPath(basePath);
53
+ const raw = existsSync(sourcePath) ? readFileSync(sourcePath, "utf-8") : "";
54
+ const report = buildParityReport(parseParityEvents(raw), sourcePath);
55
+ mkdirSync(join(gsdRoot(basePath), "runtime"), { recursive: true });
56
+ writeFileSync(reportPath(basePath), JSON.stringify(report, null, 2) + "\n", "utf-8");
57
+ return report;
58
+ }
@@ -3,12 +3,15 @@ import { join } from "node:path";
3
3
  import { gsdRoot, resolveMilestoneFile, resolveSliceFile } from "../paths.js";
4
4
  import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "../gsd-db.js";
5
5
  const PLAN_V2_CLARIFY_ROUND_LIMIT = 3;
6
- const EXECUTION_ENTRY_PHASES = new Set([
6
+ export const EXECUTION_ENTRY_PHASES = new Set([
7
7
  "executing",
8
8
  "summarizing",
9
9
  "validating-milestone",
10
10
  "completing-milestone",
11
11
  ]);
12
+ export function isExecutionEntryPhase(phase) {
13
+ return EXECUTION_ENTRY_PHASES.has(phase);
14
+ }
12
15
  function graphOutputPath(basePath) {
13
16
  return join(gsdRoot(basePath), "runtime", "uok-plan-v2-graph.json");
14
17
  }
@@ -39,6 +42,12 @@ function hasMilestoneFileContent(basePath, milestoneId, suffix) {
39
42
  }
40
43
  return false;
41
44
  }
45
+ export function hasFinalizedMilestoneContext(basePath, milestoneId) {
46
+ return hasMilestoneFileContent(basePath, milestoneId, "CONTEXT");
47
+ }
48
+ export function isMissingFinalizedContextResult(result) {
49
+ return !result.ok && result.finalizedContextIncluded === false;
50
+ }
42
51
  function countSliceResearchArtifacts(basePath, milestoneId, slices) {
43
52
  let count = 0;
44
53
  for (const slice of slices) {
@@ -48,9 +57,6 @@ function countSliceResearchArtifacts(basePath, milestoneId, slices) {
48
57
  }
49
58
  return count;
50
59
  }
51
- function isExecutionEntryPhase(phase) {
52
- return EXECUTION_ENTRY_PHASES.has(phase);
53
- }
54
60
  export function compileUnitGraphFromState(basePath, state) {
55
61
  const mid = state.activeMilestone?.id;
56
62
  if (!mid)
@@ -0,0 +1,82 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { atomicWriteSync } from "../atomic-write.js";
5
+ import { gsdRoot } from "../paths.js";
6
+ const activeTokens = new Map();
7
+ function tokenKey(basePath, turnId) {
8
+ return `${basePath}:${turnId}`;
9
+ }
10
+ function sequencePath(basePath) {
11
+ return join(gsdRoot(basePath), "runtime", "uok-writer-sequence.json");
12
+ }
13
+ function readSequenceState(basePath) {
14
+ const path = sequencePath(basePath);
15
+ if (!existsSync(path)) {
16
+ return { lastSequence: 0, updatedAt: new Date(0).toISOString() };
17
+ }
18
+ try {
19
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
20
+ return {
21
+ lastSequence: Number.isInteger(parsed.lastSequence) ? Number(parsed.lastSequence) : 0,
22
+ updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : new Date(0).toISOString(),
23
+ };
24
+ }
25
+ catch {
26
+ return { lastSequence: 0, updatedAt: new Date(0).toISOString() };
27
+ }
28
+ }
29
+ function writeSequenceState(basePath, state) {
30
+ atomicWriteSync(sequencePath(basePath), JSON.stringify(state, null, 2) + "\n", "utf-8");
31
+ }
32
+ export function acquireWriterToken(args) {
33
+ const key = tokenKey(args.basePath, args.turnId);
34
+ const existing = activeTokens.get(key);
35
+ if (existing) {
36
+ throw new Error(`Writer token already active for turn ${args.turnId}`);
37
+ }
38
+ const token = {
39
+ tokenId: randomUUID(),
40
+ traceId: args.traceId,
41
+ turnId: args.turnId,
42
+ acquiredAt: new Date().toISOString(),
43
+ owner: args.owner ?? "uok",
44
+ };
45
+ activeTokens.set(key, token);
46
+ return token;
47
+ }
48
+ export function releaseWriterToken(basePath, token) {
49
+ const key = tokenKey(basePath, token.turnId);
50
+ const current = activeTokens.get(key);
51
+ if (current?.tokenId === token.tokenId) {
52
+ activeTokens.delete(key);
53
+ }
54
+ }
55
+ export function hasActiveWriterToken(basePath, turnId) {
56
+ return activeTokens.has(tokenKey(basePath, turnId));
57
+ }
58
+ export function nextWriteRecord(args) {
59
+ if (!hasActiveWriterToken(args.basePath, args.token.turnId)) {
60
+ throw new Error(`Writer token is not active for turn ${args.token.turnId}`);
61
+ }
62
+ const state = readSequenceState(args.basePath);
63
+ const sequence = state.lastSequence + 1;
64
+ const updatedAt = new Date().toISOString();
65
+ writeSequenceState(args.basePath, { lastSequence: sequence, updatedAt });
66
+ return {
67
+ writerToken: args.token,
68
+ sequence: {
69
+ traceId: args.token.traceId,
70
+ turnId: args.token.turnId,
71
+ sequence,
72
+ },
73
+ category: args.category,
74
+ operation: args.operation,
75
+ path: args.path,
76
+ ts: updatedAt,
77
+ metadata: args.metadata,
78
+ };
79
+ }
80
+ export function resetWriterTokensForTests() {
81
+ activeTokens.clear();
82
+ }
@@ -15,6 +15,7 @@ const MCP_WORKFLOW_TOOL_SURFACE = new Set([
15
15
  "gsd_journal_query",
16
16
  "gsd_milestone_complete",
17
17
  "gsd_milestone_generate_id",
18
+ "gsd_milestone_reopen",
18
19
  "gsd_checkpoint_db",
19
20
  "gsd_milestone_status",
20
21
  "gsd_milestone_validate",
@@ -23,6 +24,9 @@ const MCP_WORKFLOW_TOOL_SURFACE = new Set([
23
24
  "gsd_plan_slice",
24
25
  "gsd_replan_slice",
25
26
  "gsd_reassess_roadmap",
27
+ "gsd_reopen_milestone",
28
+ "gsd_reopen_slice",
29
+ "gsd_reopen_task",
26
30
  "gsd_requirement_save",
27
31
  "gsd_requirement_update",
28
32
  "gsd_roadmap_reassess",
@@ -32,9 +36,11 @@ const MCP_WORKFLOW_TOOL_SURFACE = new Set([
32
36
  "gsd_skip_slice",
33
37
  "gsd_slice_replan",
34
38
  "gsd_slice_complete",
39
+ "gsd_slice_reopen",
35
40
  "gsd_summary_save",
36
41
  "gsd_task_plan",
37
42
  "gsd_task_complete",
43
+ "gsd_task_reopen",
38
44
  "gsd_update_requirement",
39
45
  "gsd_validate_milestone",
40
46
  ]);
@@ -19,7 +19,8 @@ import { execFileSync } from "node:child_process";
19
19
  import { join, resolve, sep } from "node:path";
20
20
  import { GSDError, GSD_PARSE_ERROR, GSD_STALE_STATE, GSD_LOCK_HELD, GSD_GIT_ERROR, GSD_MERGE_CONFLICT } from "./errors.js";
21
21
  import { logWarning } from "./workflow-logger.js";
22
- import { nativeBranchDelete, nativeBranchExists, nativeBranchForceReset, nativeCommit, nativeDetectMainBranch, nativeDiffContent, nativeDiffNameStatus, nativeDiffNumstat, nativeGetCurrentBranch, nativeLogOneline, nativeMergeSquash, nativeWorktreeAdd, nativeWorktreeList, nativeWorktreePrune, nativeWorktreeRemove, } from "./native-git-bridge.js";
22
+ import { nativeBranchDelete, nativeBranchExists, nativeBranchForceReset, nativeCommit, nativeDetectMainBranch, nativeDiffContent, nativeDiffNameStatus, nativeDiffNumstat, nativeGetCurrentBranch, nativeIsAncestor, nativeLogOneline, nativeMergeSquash, nativeWorktreeAdd, nativeWorktreeList, nativeWorktreePrune, nativeWorktreeRemove, } from "./native-git-bridge.js";
23
+ import { emitCanonicalRootRedirect } from "./worktree-telemetry.js";
23
24
  // ─── Path Helpers ──────────────────────────────────────────────────────────
24
25
  function normalizePathForComparison(path) {
25
26
  const normalized = path
@@ -84,6 +85,56 @@ export function isInsideWorktreesDir(basePath, targetPath) {
84
85
  // not merely be a prefix match (e.g. ".gsd/worktrees-extra" must not match).
85
86
  return resolved === wtDir || resolved.startsWith(wtDir + sep);
86
87
  }
88
+ /**
89
+ * Return the canonical path from which a milestone's artifacts should be read.
90
+ *
91
+ * If a live git worktree exists for this milestone at `.gsd/worktrees/<MID>/`
92
+ * (directory present AND a `.git` file indicating a registered worktree),
93
+ * returns that worktree path. Otherwise returns `basePath` unchanged.
94
+ *
95
+ * Readers that cross the session/worktree boundary (validators, the bootstrap
96
+ * audit, cross-session state queries) should route through this helper so they
97
+ * don't silently read stale project-root state while live work sits in the
98
+ * worktree. Writers and tools whose contract is "operate on the path I was
99
+ * given" should NOT use this helper — they preserve the legacy behavior.
100
+ *
101
+ * A stale worktree directory (no `.git` file) is treated as absent. The
102
+ * createWorktree() path already cleans these up, but readers must not trust
103
+ * them in the window before cleanup runs.
104
+ *
105
+ * Fixes #4761. Used by the #4762 audit for the pre-completion orphan case.
106
+ */
107
+ export function resolveCanonicalMilestoneRoot(basePath, milestoneId) {
108
+ if (!milestoneId || /[\/\\]|\.\./.test(milestoneId))
109
+ return basePath;
110
+ const wtPath = worktreePath(basePath, milestoneId);
111
+ if (!existsSync(wtPath))
112
+ return basePath;
113
+ // A registered git worktree has a .git *file* (not directory) containing
114
+ // "gitdir: <path>". A standalone .git directory indicates a copied repo
115
+ // or nested standalone repo — not a worktree registered with this project —
116
+ // and must not be treated as the canonical root.
117
+ const gitPath = join(wtPath, ".git");
118
+ if (!existsSync(gitPath))
119
+ return basePath;
120
+ try {
121
+ const stat = lstatSync(gitPath);
122
+ if (!stat.isFile())
123
+ return basePath;
124
+ }
125
+ catch {
126
+ return basePath;
127
+ }
128
+ // #4764 — record the redirect so we can measure how often the #4761 fix
129
+ // would have mattered. Best-effort; emit is silent on any failure.
130
+ try {
131
+ emitCanonicalRootRedirect(basePath, milestoneId, wtPath);
132
+ }
133
+ catch (err) {
134
+ logWarning("worktree", `canonical-root-redirect telemetry failed: ${err instanceof Error ? err.message : String(err)}`);
135
+ }
136
+ return wtPath;
137
+ }
87
138
  // ─── Core Operations ───────────────────────────────────────────────────────
88
139
  /**
89
140
  * Create a new git worktree under .gsd/worktrees/<name>/ with branch worktree/<name>.
@@ -120,6 +171,13 @@ export function createWorktree(basePath, name, opts = {}) {
120
171
  // Use the explicit start point (e.g. integration branch) if provided,
121
172
  // otherwise fall back to the repo's detected main branch.
122
173
  const startPoint = opts.startPoint ?? nativeDetectMainBranch(basePath);
174
+ // Reject early if startPoint resolves to an empty/invalid ref. On an
175
+ // unborn branch (zero-commit repo) nativeDetectMainBranch returns "",
176
+ // which would flow into `git worktree add ... ""` and crash with
177
+ // `fatal: not a valid object name`. (Issue #4980 HIGH-9)
178
+ if (!startPoint || startPoint.length === 0) {
179
+ throw new GSDError(GSD_GIT_ERROR, "Repository has no commits yet (unborn branch). Make an initial commit before creating worktrees.");
180
+ }
123
181
  // Check if the branch already exists (leftover from a previous worktree)
124
182
  const branchAlreadyExists = nativeBranchExists(basePath, branch);
125
183
  if (branchAlreadyExists) {
@@ -137,6 +195,18 @@ export function createWorktree(basePath, name, opts = {}) {
137
195
  nativeWorktreeAdd(basePath, wtPath, branch);
138
196
  }
139
197
  else {
198
+ // Ancestry guard: refuse to force-reset a branch that has commits not
199
+ // reachable from startPoint. A crash-then-resume cycle that didn't
200
+ // write the resume file would silently orphan prior-session commits
201
+ // (recoverable from reflog for 90d, then gone — branch is also
202
+ // deleted at teardown). (Issue #4980 HIGH-3)
203
+ const branchIsAncestor = nativeIsAncestor(basePath, branch, startPoint);
204
+ if (!branchIsAncestor) {
205
+ throw new GSDError(GSD_GIT_ERROR, `Branch "${branch}" already exists with commits not reachable from "${startPoint}". ` +
206
+ `Refusing to force-reset — would orphan prior work. ` +
207
+ `If you intend to keep those commits, retry with reuseExistingBranch=true. ` +
208
+ `If you intend to discard, run \`git branch -D ${branch}\` manually first.`);
209
+ }
140
210
  // Reset the stale branch to the start point, then attach worktree to it
141
211
  nativeBranchForceReset(basePath, branch, startPoint);
142
212
  nativeWorktreeAdd(basePath, wtPath, branch);
@@ -368,15 +438,22 @@ export function removeWorktree(basePath, name, opts = {}) {
368
438
  // Lines starting with '+' indicate uncommitted submodule changes
369
439
  hasSubmoduleChanges = submoduleStatus.split("\n").some((line) => line.startsWith("+") || line.startsWith("-"));
370
440
  if (hasSubmoduleChanges) {
371
- // Stash submodule changes so they are not lost during force removal.
372
- // The stash is created in the worktree before it's torn down.
441
+ // Save submodule changes to a labeled rescue branch instead of the
442
+ // shared stash list. Stash is per-repo (not per-worktree), so an
443
+ // entry created here would appear in the user's main-tree stash
444
+ // list and reference paths that disappear after worktree removal.
445
+ // A branch persists in the shared .git refs after worktree removal
446
+ // and is discoverable via `git branch --list 'gsd/submodule-rescue/*'`.
447
+ // (Issue #4980 HIGH-11)
448
+ const rescueBranch = `gsd/submodule-rescue/${name}-${Date.now()}`;
373
449
  try {
374
- execFileSync("git", ["stash", "push", "-m", "gsd: auto-stash submodule changes before worktree teardown"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
375
- logWarning("reconcile", `Stashed uncommitted submodule changes before worktree teardown`, { worktree: name, path: resolvedWtPath });
450
+ execFileSync("git", ["add", "-A"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
451
+ execFileSync("git", ["commit", "-m", `gsd: rescue submodule changes from worktree ${name}`, "--allow-empty"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
452
+ execFileSync("git", ["branch", rescueBranch, "HEAD"], { cwd: resolvedWtPath, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
453
+ logWarning("reconcile", `Saved uncommitted submodule changes to rescue branch ${rescueBranch}`, { worktree: name, path: resolvedWtPath, rescueBranch });
376
454
  }
377
- catch {
378
- // Stash failed — warn the user that submodule changes may be lost
379
- logWarning("reconcile", `Submodule changes detected — stash failed, changes may be lost during force removal`, { worktree: name, path: resolvedWtPath });
455
+ catch (err) {
456
+ logWarning("reconcile", `Submodule rescue branch creation failed — changes may be lost during force removal: ${err instanceof Error ? err.message : String(err)}`, { worktree: name, path: resolvedWtPath });
380
457
  }
381
458
  }
382
459
  }
@@ -17,6 +17,9 @@ import { randomUUID } from "node:crypto";
17
17
  import { join } from "node:path";
18
18
  import { debugLog } from "./debug-logger.js";
19
19
  import { emitJournalEvent } from "./journal.js";
20
+ import { emitWorktreeCreated, emitWorktreeMerged } from "./worktree-telemetry.js";
21
+ import { getCollapseCadence, getMilestoneResquash, resquashMilestoneOnMain } from "./slice-cadence.js";
22
+ import { loadEffectiveGSDPreferences } from "./preferences.js";
20
23
  // ─── Path Helpers ──────────────────────────────────────────────────────────
21
24
  /**
22
25
  * Worktree marker segment — present in any path produced by worktreePath().
@@ -194,6 +197,20 @@ export class WorktreeResolver {
194
197
  eventType: "worktree-enter",
195
198
  data: { milestoneId, wtPath, created: !existingPath },
196
199
  });
200
+ // #4764 — record creation/enter as a lifecycle event so the telemetry
201
+ // aggregator can pair it with the eventual worktree-merged event.
202
+ try {
203
+ emitWorktreeCreated(this.s.originalBasePath || this.s.basePath, milestoneId, {
204
+ reason: existingPath ? "enter-milestone" : "create-milestone",
205
+ });
206
+ }
207
+ catch (telemetryErr) {
208
+ debugLog("WorktreeResolver", {
209
+ action: "enterMilestone",
210
+ phase: "telemetry-emit",
211
+ error: telemetryErr instanceof Error ? telemetryErr.message : String(telemetryErr),
212
+ });
213
+ }
197
214
  ctx.notify(`Entered worktree for ${milestoneId} at ${wtPath}`, "info");
198
215
  }
199
216
  catch (err) {
@@ -289,6 +306,9 @@ export class WorktreeResolver {
289
306
  */
290
307
  mergeAndExit(milestoneId, ctx) {
291
308
  this.validateMilestoneId(milestoneId);
309
+ // #4764 — telemetry: record start timestamp so we can emit merge duration.
310
+ const mergeStartedAt = new Date().toISOString();
311
+ const mergeStartMs = Date.now();
292
312
  // If worktree creation failed earlier, skip merge — work is on current branch (#2483)
293
313
  if (this.s.isolationDegraded) {
294
314
  debugLog("WorktreeResolver", {
@@ -328,14 +348,68 @@ export class WorktreeResolver {
328
348
  });
329
349
  return;
330
350
  }
351
+ let actuallyMerged = false;
331
352
  if (mode === "worktree" || inWorktree) {
332
- this._mergeWorktreeMode(milestoneId, ctx);
353
+ actuallyMerged = this._mergeWorktreeMode(milestoneId, ctx);
333
354
  }
334
355
  else if (mode === "branch") {
335
- this._mergeBranchMode(milestoneId, ctx);
356
+ actuallyMerged = this._mergeBranchMode(milestoneId, ctx);
357
+ }
358
+ // The remainder of this function emits telemetry and runs re-squash.
359
+ // Both are gated on actuallyMerged — if the _merge* helper took a
360
+ // no-merge path (missing originalBase, no roadmap, wrong branch) the
361
+ // milestone branch was intentionally left unmerged and we must not
362
+ // emit a worktree-merged event or collapse commits on main.
363
+ if (!actuallyMerged) {
364
+ // Always clear the start-SHA tracker to avoid leaking across sessions.
365
+ this.s.milestoneStartShas.delete(milestoneId);
366
+ return;
367
+ }
368
+ // #4765 — when collapse_cadence=slice AND milestone_resquash=true, the
369
+ // N per-slice commits on main should be collapsed into one milestone
370
+ // commit. Done AFTER the primary merge-and-teardown so the branch and
371
+ // worktree are already cleaned up; we operate on main directly.
372
+ try {
373
+ const startSha = this.s.milestoneStartShas.get(milestoneId);
374
+ if (startSha) {
375
+ const prefs = loadEffectiveGSDPreferences(this.s.originalBasePath || this.s.basePath)?.preferences;
376
+ if (getCollapseCadence(prefs) === "slice" && getMilestoneResquash(prefs)) {
377
+ const result = resquashMilestoneOnMain(this.s.originalBasePath || this.s.basePath, milestoneId, startSha);
378
+ if (result.resquashed) {
379
+ ctx.notify(`slice-cadence: re-squashed slice commits for ${milestoneId} into a single milestone commit.`, "info");
380
+ }
381
+ }
382
+ this.s.milestoneStartShas.delete(milestoneId);
383
+ }
384
+ }
385
+ catch (err) {
386
+ debugLog("WorktreeResolver", {
387
+ action: "mergeAndExit",
388
+ milestoneId,
389
+ phase: "resquash",
390
+ error: err instanceof Error ? err.message : String(err),
391
+ });
392
+ }
393
+ // #4764 — record merge completion. Only reaches here when an actual
394
+ // merge ran; failure paths throw out of _merge* before this point and
395
+ // no-merge paths returned above.
396
+ try {
397
+ emitWorktreeMerged(this.s.originalBasePath || this.s.basePath, milestoneId, {
398
+ reason: "milestone-complete",
399
+ startedAt: mergeStartedAt,
400
+ durationMs: Date.now() - mergeStartMs,
401
+ });
402
+ }
403
+ catch (telemetryErr) {
404
+ debugLog("WorktreeResolver", {
405
+ action: "mergeAndExit",
406
+ phase: "telemetry-emit",
407
+ error: telemetryErr instanceof Error ? telemetryErr.message : String(telemetryErr),
408
+ });
336
409
  }
337
410
  }
338
- /** Worktree-mode merge: read roadmap, merge, teardown, reset paths. */
411
+ /** Worktree-mode merge: read roadmap, merge, teardown, reset paths.
412
+ * Returns true when a squash-merge actually ran (false on skip paths). */
339
413
  _mergeWorktreeMode(milestoneId, ctx) {
340
414
  const originalBase = this.s.originalBasePath;
341
415
  if (!originalBase) {
@@ -346,8 +420,9 @@ export class WorktreeResolver {
346
420
  skipped: true,
347
421
  reason: "missing-original-base",
348
422
  });
349
- return;
423
+ return false;
350
424
  }
425
+ let merged = false;
351
426
  try {
352
427
  const { synced } = this.deps.syncWorktreeStateBack(originalBase, this.s.basePath, milestoneId);
353
428
  if (synced.length > 0) {
@@ -378,6 +453,7 @@ export class WorktreeResolver {
378
453
  if (roadmapPath) {
379
454
  const roadmapContent = this.deps.readFileSync(roadmapPath, "utf-8");
380
455
  const mergeResult = this.deps.mergeMilestoneToMain(originalBase, milestoneId, roadmapContent);
456
+ merged = true;
381
457
  // #2945 Bug 3: mergeMilestoneToMain performs best-effort worktree
382
458
  // cleanup internally (step 12), but it can silently fail on Windows
383
459
  // or when the worktree directory is locked. Perform a secondary
@@ -470,8 +546,10 @@ export class WorktreeResolver {
470
546
  result: "done",
471
547
  basePath: this.s.basePath,
472
548
  });
549
+ return merged;
473
550
  }
474
- /** Branch-mode merge: check current branch, merge if on milestone branch. */
551
+ /** Branch-mode merge: check current branch, merge if on milestone branch.
552
+ * Returns true when a merge actually ran (false on skip paths). */
475
553
  _mergeBranchMode(milestoneId, ctx) {
476
554
  try {
477
555
  const currentBranch = this.deps.getCurrentBranch(this.s.basePath);
@@ -486,7 +564,7 @@ export class WorktreeResolver {
486
564
  currentBranch,
487
565
  milestoneBranch,
488
566
  });
489
- return;
567
+ return false;
490
568
  }
491
569
  const roadmapPath = this.deps.resolveMilestoneFile(this.s.basePath, milestoneId, "ROADMAP");
492
570
  if (!roadmapPath) {
@@ -497,7 +575,7 @@ export class WorktreeResolver {
497
575
  skipped: true,
498
576
  reason: "no-roadmap",
499
577
  });
500
- return;
578
+ return false;
501
579
  }
502
580
  const roadmapContent = this.deps.readFileSync(roadmapPath, "utf-8");
503
581
  const mergeResult = this.deps.mergeMilestoneToMain(this.s.basePath, milestoneId, roadmapContent);
@@ -516,6 +594,7 @@ export class WorktreeResolver {
516
594
  mode: "branch",
517
595
  result: "success",
518
596
  });
597
+ return true;
519
598
  }
520
599
  catch (err) {
521
600
  const msg = err instanceof Error ? err.message : String(err);