gsd-pi 2.66.1-dev.ed243f2 → 2.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/dist/claude-cli-check.d.ts +8 -0
  2. package/dist/claude-cli-check.js +36 -0
  3. package/dist/cli.js +40 -0
  4. package/dist/onboarding.js +19 -2
  5. package/dist/resources/extensions/ask-user-questions.js +79 -11
  6. package/dist/resources/extensions/claude-code-cli/partial-builder.js +4 -3
  7. package/dist/resources/extensions/claude-code-cli/readiness.js +63 -12
  8. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +10 -3
  9. package/dist/resources/extensions/gsd/auto/loop.js +13 -1
  10. package/dist/resources/extensions/gsd/auto/phases.js +22 -3
  11. package/dist/resources/extensions/gsd/auto/run-unit.js +10 -2
  12. package/dist/resources/extensions/gsd/auto/session.js +1 -1
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +65 -15
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +30 -28
  15. package/dist/resources/extensions/gsd/auto-model-selection.js +12 -3
  16. package/dist/resources/extensions/gsd/auto-prompts.js +173 -25
  17. package/dist/resources/extensions/gsd/auto-recovery.js +11 -12
  18. package/dist/resources/extensions/gsd/auto.js +13 -1
  19. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -1
  20. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +18 -6
  21. package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +5 -0
  22. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +59 -5
  23. package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +8 -5
  24. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +186 -14
  25. package/dist/resources/extensions/gsd/codebase-generator.js +4 -0
  26. package/dist/resources/extensions/gsd/commands/handlers/core.js +3 -3
  27. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -4
  28. package/dist/resources/extensions/gsd/context-store.js +134 -2
  29. package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -1
  30. package/dist/resources/extensions/gsd/detection.js +6 -0
  31. package/dist/resources/extensions/gsd/files.js +19 -2
  32. package/dist/resources/extensions/gsd/guided-flow.js +12 -8
  33. package/dist/resources/extensions/gsd/index.js +1 -1
  34. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +2 -0
  35. package/dist/resources/extensions/gsd/parsers-legacy.js +3 -1
  36. package/dist/resources/extensions/gsd/preferences.js +6 -1
  37. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  38. package/dist/resources/extensions/gsd/prompts/discuss-prepared.md +7 -7
  39. package/dist/resources/extensions/gsd/prompts/discuss.md +3 -3
  40. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -3
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  42. package/dist/resources/extensions/gsd/prompts/rethink.md +6 -2
  43. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  44. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  45. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +4 -4
  46. package/dist/resources/extensions/gsd/prompts/worktree-merge.md +3 -1
  47. package/dist/resources/extensions/gsd/safety/file-change-validator.js +2 -1
  48. package/dist/resources/extensions/gsd/state.js +2 -1
  49. package/dist/resources/extensions/gsd/visualizer-overlay.js +27 -26
  50. package/dist/resources/extensions/gsd/workflow-reconcile.js +46 -7
  51. package/dist/resources/extensions/remote-questions/manager.js +8 -0
  52. package/dist/resources/extensions/shared/interview-ui.js +10 -0
  53. package/dist/web/standalone/.next/BUILD_ID +1 -1
  54. package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
  55. package/dist/web/standalone/.next/build-manifest.json +3 -3
  56. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  57. package/dist/web/standalone/.next/required-server-files.json +3 -3
  58. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  59. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  60. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  61. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  62. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  63. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  64. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  65. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  69. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  70. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  71. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  72. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  73. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  75. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  79. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  80. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  81. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  82. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  83. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  84. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  85. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  86. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  87. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  88. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  89. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  90. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  91. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  92. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  93. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  94. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  95. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  96. package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
  97. package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
  98. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  99. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  100. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  101. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  102. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  103. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  104. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  105. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  106. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  107. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  108. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  110. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  111. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  112. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  113. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  114. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  115. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  116. package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
  117. package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  118. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  119. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  121. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  122. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  123. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  124. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  125. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
  127. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  132. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  133. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
  147. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  149. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  151. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  153. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  162. package/dist/web/standalone/.next/server/app/index.html +1 -1
  163. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  164. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  165. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  166. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  167. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  168. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  169. package/dist/web/standalone/.next/server/app/page.js +2 -2
  170. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
  172. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  173. package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
  174. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/middleware.js +2 -2
  176. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  178. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  179. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  180. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  181. package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
  182. package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
  183. package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.js +1 -0
  184. package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
  185. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
  186. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  187. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  188. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  189. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  190. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  191. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  192. package/dist/web/standalone/server.js +1 -1
  193. package/package.json +1 -1
  194. package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
  195. package/packages/pi-ai/dist/providers/anthropic-shared.js +4 -3
  196. package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
  197. package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
  198. package/packages/pi-ai/dist/utils/json-parse.js +11 -1
  199. package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
  200. package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -1
  201. package/packages/pi-ai/dist/utils/repair-tool-json.js +60 -1
  202. package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
  203. package/packages/pi-ai/dist/utils/tests/json-parse.test.d.ts +2 -0
  204. package/packages/pi-ai/dist/utils/tests/json-parse.test.d.ts.map +1 -0
  205. package/packages/pi-ai/dist/utils/tests/json-parse.test.js +14 -0
  206. package/packages/pi-ai/dist/utils/tests/json-parse.test.js.map +1 -0
  207. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +10 -0
  208. package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
  209. package/packages/pi-ai/src/providers/anthropic-shared.ts +4 -3
  210. package/packages/pi-ai/src/utils/json-parse.ts +11 -1
  211. package/packages/pi-ai/src/utils/repair-tool-json.ts +69 -1
  212. package/packages/pi-ai/src/utils/tests/json-parse.test.ts +17 -0
  213. package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +13 -0
  214. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -0
  215. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -0
  217. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +16 -0
  219. package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
  220. package/packages/pi-coding-agent/dist/core/retry-handler.js +58 -1
  221. package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/retry-handler.test.js +58 -0
  223. package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/sdk.d.ts +3 -0
  225. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  226. package/packages/pi-coding-agent/dist/core/sdk.js +1 -0
  227. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  228. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.d.ts +2 -0
  229. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.d.ts.map +1 -0
  230. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js +17 -0
  231. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/provider-display-name.test.js.map +1 -0
  232. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  233. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +2 -1
  234. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  235. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts +1 -0
  236. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  237. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js +9 -2
  238. package/packages/pi-coding-agent/dist/modes/interactive/components/model-selector.js.map +1 -1
  239. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
  240. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +2 -1
  241. package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
  242. package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.js +2 -1
  244. package/packages/pi-coding-agent/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +2 -2
  246. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  247. package/packages/pi-coding-agent/package.json +1 -1
  248. package/packages/pi-coding-agent/src/core/agent-session.ts +4 -0
  249. package/packages/pi-coding-agent/src/core/retry-handler.test.ts +69 -0
  250. package/packages/pi-coding-agent/src/core/retry-handler.ts +66 -1
  251. package/packages/pi-coding-agent/src/core/sdk.ts +5 -0
  252. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/provider-display-name.test.ts +18 -0
  253. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +2 -1
  254. package/packages/pi-coding-agent/src/modes/interactive/components/model-selector.ts +11 -2
  255. package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +2 -1
  256. package/packages/pi-coding-agent/src/modes/interactive/components/scoped-models-selector.ts +2 -1
  257. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +2 -2
  258. package/packages/pi-tui/dist/__tests__/autocomplete.test.js +13 -0
  259. package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
  260. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts +2 -0
  261. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.d.ts.map +1 -0
  262. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +35 -0
  263. package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -0
  264. package/packages/pi-tui/dist/__tests__/tui.test.d.ts +2 -0
  265. package/packages/pi-tui/dist/__tests__/tui.test.d.ts.map +1 -0
  266. package/packages/pi-tui/dist/__tests__/tui.test.js +43 -0
  267. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -0
  268. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  269. package/packages/pi-tui/dist/autocomplete.js +9 -7
  270. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  271. package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts +2 -0
  272. package/packages/pi-tui/dist/components/__tests__/editor.test.d.ts.map +1 -0
  273. package/packages/pi-tui/dist/components/__tests__/editor.test.js +54 -0
  274. package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -0
  275. package/packages/pi-tui/dist/components/editor.d.ts +3 -1
  276. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  277. package/packages/pi-tui/dist/components/editor.js +14 -3
  278. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  279. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  280. package/packages/pi-tui/dist/stdin-buffer.js +6 -0
  281. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  282. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  283. package/packages/pi-tui/dist/tui.js +8 -0
  284. package/packages/pi-tui/dist/tui.js.map +1 -1
  285. package/packages/pi-tui/src/__tests__/autocomplete.test.ts +15 -0
  286. package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +43 -0
  287. package/packages/pi-tui/src/__tests__/tui.test.ts +50 -0
  288. package/packages/pi-tui/src/autocomplete.ts +9 -7
  289. package/packages/pi-tui/src/components/__tests__/editor.test.ts +64 -0
  290. package/packages/pi-tui/src/components/editor.ts +14 -3
  291. package/packages/pi-tui/src/stdin-buffer.ts +7 -0
  292. package/packages/pi-tui/src/tui.ts +9 -0
  293. package/pkg/package.json +1 -1
  294. package/src/resources/extensions/ask-user-questions.ts +103 -11
  295. package/src/resources/extensions/claude-code-cli/partial-builder.ts +4 -3
  296. package/src/resources/extensions/claude-code-cli/readiness.ts +67 -12
  297. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +12 -3
  298. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +17 -0
  299. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +18 -0
  300. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -1
  301. package/src/resources/extensions/gsd/auto/loop.ts +14 -1
  302. package/src/resources/extensions/gsd/auto/phases.ts +27 -4
  303. package/src/resources/extensions/gsd/auto/run-unit.ts +14 -2
  304. package/src/resources/extensions/gsd/auto/session.ts +1 -1
  305. package/src/resources/extensions/gsd/auto-dashboard.ts +76 -16
  306. package/src/resources/extensions/gsd/auto-dispatch.ts +36 -35
  307. package/src/resources/extensions/gsd/auto-model-selection.ts +12 -3
  308. package/src/resources/extensions/gsd/auto-prompts.ts +195 -25
  309. package/src/resources/extensions/gsd/auto-recovery.ts +15 -15
  310. package/src/resources/extensions/gsd/auto.ts +12 -1
  311. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -1
  312. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +27 -6
  313. package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +6 -0
  314. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +67 -6
  315. package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +11 -8
  316. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +209 -16
  317. package/src/resources/extensions/gsd/codebase-generator.ts +4 -0
  318. package/src/resources/extensions/gsd/commands/handlers/core.ts +6 -6
  319. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +11 -4
  320. package/src/resources/extensions/gsd/context-store.ts +167 -2
  321. package/src/resources/extensions/gsd/custom-workflow-engine.ts +3 -1
  322. package/src/resources/extensions/gsd/detection.ts +6 -0
  323. package/src/resources/extensions/gsd/files.ts +21 -2
  324. package/src/resources/extensions/gsd/guided-flow.ts +15 -8
  325. package/src/resources/extensions/gsd/index.ts +6 -0
  326. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +2 -0
  327. package/src/resources/extensions/gsd/parsers-legacy.ts +3 -1
  328. package/src/resources/extensions/gsd/preferences.ts +6 -1
  329. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  330. package/src/resources/extensions/gsd/prompts/discuss-prepared.md +7 -7
  331. package/src/resources/extensions/gsd/prompts/discuss.md +3 -3
  332. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -3
  333. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  334. package/src/resources/extensions/gsd/prompts/rethink.md +6 -2
  335. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  336. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  337. package/src/resources/extensions/gsd/prompts/validate-milestone.md +4 -4
  338. package/src/resources/extensions/gsd/prompts/worktree-merge.md +3 -1
  339. package/src/resources/extensions/gsd/safety/file-change-validator.ts +4 -1
  340. package/src/resources/extensions/gsd/state.ts +2 -1
  341. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +52 -1
  342. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +50 -2
  343. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +21 -7
  344. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +48 -0
  345. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  346. package/src/resources/extensions/gsd/tests/context-store.test.ts +176 -0
  347. package/src/resources/extensions/gsd/tests/core-overlay-fallback.test.ts +44 -0
  348. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +7 -1
  349. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +31 -0
  350. package/src/resources/extensions/gsd/tests/decision-scope-cascade.test.ts +370 -0
  351. package/src/resources/extensions/gsd/tests/detection.test.ts +37 -0
  352. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +50 -0
  353. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +35 -0
  354. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +34 -0
  355. package/src/resources/extensions/gsd/tests/health-widget.test.ts +45 -0
  356. package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +53 -13
  357. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -2
  358. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +3 -3
  359. package/src/resources/extensions/gsd/tests/measurement.test.ts +531 -0
  360. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +3 -4
  361. package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +21 -0
  362. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +71 -2
  363. package/src/resources/extensions/gsd/tests/parsers.test.ts +25 -0
  364. package/src/resources/extensions/gsd/tests/preferences.test.ts +20 -0
  365. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -1
  366. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +60 -0
  367. package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +9 -0
  368. package/src/resources/extensions/gsd/tests/reactive-graph.test.ts +19 -0
  369. package/src/resources/extensions/gsd/tests/register-shortcuts.test.ts +73 -0
  370. package/src/resources/extensions/gsd/tests/remote-questions.test.ts +98 -0
  371. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +2 -2
  372. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +26 -0
  373. package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +59 -0
  374. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +91 -0
  375. package/src/resources/extensions/gsd/tests/write-gate.test.ts +210 -35
  376. package/src/resources/extensions/gsd/visualizer-overlay.ts +31 -27
  377. package/src/resources/extensions/gsd/workflow-reconcile.ts +59 -8
  378. package/src/resources/extensions/remote-questions/manager.ts +9 -0
  379. package/src/resources/extensions/shared/interview-ui.ts +13 -0
  380. package/dist/web/standalone/.next/static/chunks/app/page-0c485498795110d6.js +0 -1
  381. package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
  382. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
  383. /package/dist/web/standalone/.next/static/{HAq0VE4k68rhRvJbQL1VW → DFZllMYDbO0OwyS6FSvm5}/_buildManifest.js +0 -0
  384. /package/dist/web/standalone/.next/static/{HAq0VE4k68rhRvJbQL1VW → DFZllMYDbO0OwyS6FSvm5}/_ssgManifest.js +0 -0
@@ -17,6 +17,7 @@ import {
17
17
  detectProjectState,
18
18
  detectV1Planning,
19
19
  detectProjectSignals,
20
+ scanProjectFiles,
20
21
  } from "../detection.ts";
21
22
 
22
23
  function makeTempDir(prefix: string): string {
@@ -1188,3 +1189,39 @@ test("detectProjectSignals: Spring Boot settings-defined catalog accessor emits
1188
1189
  cleanup(dir);
1189
1190
  }
1190
1191
  });
1192
+
1193
+ // ─── scanProjectFiles: RECURSIVE_SCAN_IGNORED_DIRS ──────────────────────
1194
+
1195
+ test("scanProjectFiles: excludes .claude, .gsd, .planning, .plans, .cursor, .vscode directories", () => {
1196
+ const dir = makeTempDir("scan-ignore-dotdirs");
1197
+ try {
1198
+ // Create project files that should be included
1199
+ mkdirSync(join(dir, "src"), { recursive: true });
1200
+ writeFileSync(join(dir, "src", "main.ts"), "// main\n", "utf-8");
1201
+ writeFileSync(join(dir, "README.md"), "# Project\n", "utf-8");
1202
+
1203
+ // Create tool directories that should be excluded
1204
+ const excludedDirs = [".claude", ".gsd", ".planning", ".plans", ".cursor", ".vscode"];
1205
+ for (const d of excludedDirs) {
1206
+ mkdirSync(join(dir, d), { recursive: true });
1207
+ writeFileSync(join(dir, d, "config.json"), "{}\n", "utf-8");
1208
+ }
1209
+ // Nested .claude directory
1210
+ mkdirSync(join(dir, ".claude", "memory"), { recursive: true });
1211
+ writeFileSync(join(dir, ".claude", "memory", "user.md"), "# Memory\n", "utf-8");
1212
+
1213
+ const files = scanProjectFiles(dir);
1214
+
1215
+ // Should include project files
1216
+ assert.ok(files.includes("src/main.ts"), "should include src/main.ts");
1217
+ assert.ok(files.includes("README.md"), "should include README.md");
1218
+
1219
+ // Should exclude all tool directories
1220
+ for (const d of excludedDirs) {
1221
+ const hasExcluded = files.some((f) => f.startsWith(`${d}/`));
1222
+ assert.ok(!hasExcluded, `should exclude ${d}/ directory but found: ${files.filter((f) => f.startsWith(`${d}/`)).join(", ")}`);
1223
+ }
1224
+ } finally {
1225
+ cleanup(dir);
1226
+ }
1227
+ });
@@ -0,0 +1,50 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { execFileSync } from "node:child_process";
4
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+
8
+ import { validateFileChanges } from "../safety/file-change-validator.ts";
9
+
10
+ function git(cwd: string, ...args: string[]): string {
11
+ return execFileSync("git", args, {
12
+ cwd,
13
+ stdio: ["ignore", "pipe", "pipe"],
14
+ encoding: "utf-8",
15
+ }).trim();
16
+ }
17
+
18
+ test("validateFileChanges ignores inline descriptions in expected output paths", (t) => {
19
+ const base = mkdtempSync(join(tmpdir(), "gsd-file-change-validator-"));
20
+ t.after(() => rmSync(base, { recursive: true, force: true }));
21
+
22
+ mkdirSync(join(base, "definitions"), { recursive: true });
23
+ git(base, "init");
24
+ git(base, "config", "user.email", "test@example.com");
25
+ git(base, "config", "user.name", "Test User");
26
+
27
+ const target = join(base, "definitions", "ac-audit.md");
28
+ writeFileSync(target, "initial\n");
29
+ git(base, "add", ".");
30
+ git(base, "commit", "-m", "initial");
31
+
32
+ writeFileSync(target, "updated\n");
33
+ git(base, "add", ".");
34
+ git(base, "commit", "-m", "update");
35
+
36
+ const audit = validateFileChanges(
37
+ base,
38
+ ["definitions/ac-audit.md — current state of AC CRM, tags, pipelines, automations"],
39
+ [],
40
+ );
41
+
42
+ assert.ok(audit, "audit should be produced when expected output exists");
43
+ assert.deepEqual(audit.unexpectedFiles, []);
44
+ assert.deepEqual(audit.missingFiles, []);
45
+ assert.equal(
46
+ audit.violations.some((v) => v.severity === "warning"),
47
+ false,
48
+ "described expected output should not trigger unexpected-file warnings",
49
+ );
50
+ });
@@ -245,6 +245,41 @@ describe('gsd-tools', () => {
245
245
  }
246
246
  });
247
247
 
248
+ test('gsd_summary_save supports CONTEXT-DRAFT persistence', async () => {
249
+ const tmpDir = makeTmpDir();
250
+ try {
251
+ const dbPath = path.join(tmpDir, '.gsd', 'gsd.db');
252
+ openDatabase(dbPath);
253
+
254
+ await saveArtifactToDb(
255
+ {
256
+ path: 'milestones/M001/M001-CONTEXT-DRAFT.md',
257
+ artifact_type: 'CONTEXT-DRAFT',
258
+ content: '# M001 Draft Context\n\nDraft notes.',
259
+ milestone_id: 'M001',
260
+ },
261
+ tmpDir,
262
+ );
263
+
264
+ const draftPath = path.join(tmpDir, '.gsd', 'milestones', 'M001', 'M001-CONTEXT-DRAFT.md');
265
+ assert.ok(fs.existsSync(draftPath), 'Draft context file should be created');
266
+ const draftContent = fs.readFileSync(draftPath, 'utf-8');
267
+ assert.ok(draftContent.includes('Draft Context'), 'Draft context file should contain draft content');
268
+
269
+ const adapter = _getAdapter();
270
+ assert.ok(adapter !== null, 'Adapter should be available');
271
+ const rows = adapter!.prepare(
272
+ "SELECT * FROM artifacts WHERE path = 'milestones/M001/M001-CONTEXT-DRAFT.md'",
273
+ ).all();
274
+ assert.deepStrictEqual(rows.length, 1, 'Should have 1 draft artifact row');
275
+ assert.deepStrictEqual(rows[0]['artifact_type'] as string, 'CONTEXT-DRAFT', 'Artifact type should be CONTEXT-DRAFT');
276
+
277
+ closeDatabase();
278
+ } finally {
279
+ cleanupDir(tmpDir);
280
+ }
281
+ });
282
+
248
283
  test('DB unavailable error paths', async () => {
249
284
  // (d) All tools return isError when DB unavailable
250
285
  // Close any open DB and don't open a new one
@@ -10,11 +10,15 @@
10
10
 
11
11
  import { describe, test, beforeEach } from "node:test";
12
12
  import assert from "node:assert/strict";
13
+ import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { tmpdir } from "node:os";
13
16
 
14
17
  import {
15
18
  getDiscussionMilestoneId,
16
19
  setPendingAutoStart,
17
20
  clearPendingAutoStart,
21
+ checkAutoStartAfterDiscuss,
18
22
  } from "../guided-flow.ts";
19
23
 
20
24
  // ─── Tests ─────────────────────────────────────────────────────────────────
@@ -95,3 +99,33 @@ describe("#2985 Bug 4 — getDiscussionMilestoneId must be keyed by basePath", (
95
99
  assert.equal(result, "M001", "should return the only active milestone for backward compat");
96
100
  });
97
101
  });
102
+
103
+ test("checkAutoStartAfterDiscuss fails closed when a multi-milestone manifest is missing", () => {
104
+ const base = mkdtempSync(join(tmpdir(), "gsd-auto-start-manifest-"));
105
+ try {
106
+ const gsdDir = join(base, ".gsd");
107
+ const milestoneDir = join(gsdDir, "milestones", "M001");
108
+ mkdirSync(milestoneDir, { recursive: true });
109
+ mkdirSync(join(gsdDir, "milestones", "M002"), { recursive: true });
110
+ writeFileSync(
111
+ join(gsdDir, "PROJECT.md"),
112
+ `# Project\n\n| M001 | First milestone | active |\n| M002 | Second milestone | queued |\n`,
113
+ );
114
+ writeFileSync(join(gsdDir, "STATE.md"), "# State\n");
115
+ writeFileSync(join(milestoneDir, "M001-CONTEXT.md"), "# M001 Context\n");
116
+
117
+ clearPendingAutoStart();
118
+ setPendingAutoStart(base, {
119
+ basePath: base,
120
+ milestoneId: "M001",
121
+ ctx: { ui: { notify: () => undefined } } as any,
122
+ pi: { setActiveTools: () => undefined, getActiveTools: () => [] } as any,
123
+ });
124
+
125
+ const started = checkAutoStartAfterDiscuss();
126
+ assert.equal(started, false, "auto-start should fail closed without the manifest");
127
+ } finally {
128
+ clearPendingAutoStart();
129
+ rmSync(base, { recursive: true, force: true });
130
+ }
131
+ });
@@ -9,6 +9,7 @@ import {
9
9
  formatRelativeTime,
10
10
  type HealthWidgetData,
11
11
  } from "../health-widget-core.ts";
12
+ import { registerHooks } from "../bootstrap/register-hooks.ts";
12
13
 
13
14
  function makeTempDir(prefix: string): string {
14
15
  const dir = join(
@@ -177,3 +178,47 @@ test("detectHealthWidgetProjectState: metrics file alone does not imply project"
177
178
  );
178
179
  assert.equal(detectHealthWidgetProjectState(dir), "initialized");
179
180
  });
181
+
182
+ test("session_start bootstraps the health widget alongside notifications", async (t) => {
183
+ const dir = makeTempDir("bootstrap");
184
+ mkdirSync(join(dir, ".gsd"), { recursive: true });
185
+
186
+ const originalCwd = process.cwd();
187
+ process.chdir(dir);
188
+ t.after(() => {
189
+ process.chdir(originalCwd);
190
+ cleanup(dir);
191
+ });
192
+
193
+ const widgets: string[] = [];
194
+ const handlers = new Map<string, (event: unknown, ctx: any) => Promise<void> | void>();
195
+ const pi = {
196
+ on(event: string, handler: (event: unknown, ctx: any) => Promise<void> | void) {
197
+ handlers.set(event, handler);
198
+ },
199
+ } as any;
200
+
201
+ registerHooks(pi);
202
+ const sessionStart = handlers.get("session_start");
203
+ assert.ok(sessionStart, "session_start handler is registered");
204
+
205
+ await sessionStart!({}, {
206
+ hasUI: true,
207
+ ui: {
208
+ notify: () => {},
209
+ setStatus: () => {},
210
+ setWorkingMessage: () => {},
211
+ onTerminalInput: () => () => {},
212
+ setWidget: (key: string) => {
213
+ widgets.push(key);
214
+ },
215
+ },
216
+ sessionManager: {
217
+ getSessionId: () => null,
218
+ },
219
+ model: null,
220
+ } as any);
221
+
222
+ assert.ok(widgets.includes("gsd-health"), "health widget is bootstrapped");
223
+ assert.ok(widgets.includes("gsd-notifications"), "notification widget still boots");
224
+ });
@@ -1,9 +1,10 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { mkdirSync, writeFileSync, existsSync, readFileSync, rmSync } from "node:fs";
3
+ import { mkdirSync, writeFileSync, existsSync, readFileSync, rmSync, chmodSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { randomUUID } from "node:crypto";
7
+ import { execFileSync } from "node:child_process";
7
8
 
8
9
  import {
9
10
  resolveExpectedArtifactPath,
@@ -11,6 +12,7 @@ import {
11
12
  diagnoseExpectedArtifact,
12
13
  buildLoopRemediationSteps,
13
14
  hasImplementationArtifacts,
15
+ reconcileMergeState,
14
16
  } from "../../auto-recovery.ts";
15
17
  import { parseRoadmap, parsePlan } from "../../parsers-legacy.ts";
16
18
  import { parseTaskPlanFile, clearParseCache } from "../../files.ts";
@@ -669,8 +671,6 @@ test("#793: invalidateAllCaches clears all caches so deriveState sees fresh disk
669
671
 
670
672
  // ─── hasImplementationArtifacts (#1703) ───────────────────────────────────
671
673
 
672
- import { execFileSync } from "node:child_process";
673
-
674
674
  function makeGitBase(): string {
675
675
  const base = join(tmpdir(), `gsd-test-git-${randomUUID()}`);
676
676
  mkdirSync(base, { recursive: true });
@@ -745,9 +745,6 @@ test("verifyExpectedArtifact complete-milestone fails with only .gsd/ files (#17
745
745
 
746
746
  // ─── reconcileMergeState: silent nativeCommit failure (#2542) ─────────────
747
747
 
748
- import { reconcileMergeState } from "../../auto-recovery.ts";
749
- import { chmodSync } from "node:fs";
750
-
751
748
  function makeMockCtx(): { ctx: any; notifications: Array<{ msg: string; level: string }> } {
752
749
  const notifications: Array<{ msg: string; level: string }> = [];
753
750
  const ctx = {
@@ -760,7 +757,7 @@ function makeMockCtx(): { ctx: any; notifications: Array<{ msg: string; level: s
760
757
  return { ctx, notifications };
761
758
  }
762
759
 
763
- test("reconcileMergeState returns false and notifies error when nativeCommit fails (#2542)", (t) => {
760
+ test("reconcileMergeState returns blocked and notifies error when nativeCommit fails (#2542)", (t) => {
764
761
  const base = makeGitBase();
765
762
  t.after(() => cleanup(base));
766
763
 
@@ -786,9 +783,7 @@ test("reconcileMergeState returns false and notifies error when nativeCommit fai
786
783
  const { ctx, notifications } = makeMockCtx();
787
784
  const result = reconcileMergeState(base, ctx);
788
785
 
789
- // The function should return false to signal reconciliation failure
790
- // (Currently it silently swallows the error and returns true — this test should FAIL before the fix)
791
- assert.equal(result, false, "reconcileMergeState should return false when nativeCommit fails");
786
+ assert.equal(result, "blocked", "reconcileMergeState should return blocked when nativeCommit fails");
792
787
  const errorNotifications = notifications.filter(n => n.level === "error");
793
788
  assert.ok(errorNotifications.length > 0, "should notify an error when nativeCommit fails");
794
789
  assert.ok(
@@ -797,18 +792,63 @@ test("reconcileMergeState returns false and notifies error when nativeCommit fai
797
792
  );
798
793
  });
799
794
 
800
- test("reconcileMergeState returns true when no merge state present", (t) => {
801
- // When there's no MERGE_HEAD or SQUASH_MSG, reconcileMergeState returns false (no dirty state)
795
+ test("reconcileMergeState returns clean when no merge state present", (t) => {
802
796
  const base = makeGitBase();
803
797
  t.after(() => cleanup(base));
804
798
 
805
799
  const { ctx, notifications } = makeMockCtx();
806
800
  const result = reconcileMergeState(base, ctx);
807
801
 
808
- assert.equal(result, false, "should return false when no merge state exists");
802
+ assert.equal(result, "clean", "should return clean when no merge state exists");
809
803
  assert.equal(notifications.length, 0, "should not notify when no merge state present");
810
804
  });
811
805
 
806
+ test("reconcileMergeState blocks and preserves unresolved code conflicts", (t) => {
807
+ const base = makeGitBase();
808
+ t.after(() => cleanup(base));
809
+
810
+ writeFileSync(join(base, "conflict.txt"), "base\n");
811
+ execFileSync("git", ["add", "conflict.txt"], { cwd: base, stdio: "ignore" });
812
+ execFileSync("git", ["commit", "-m", "add conflict base"], { cwd: base, stdio: "ignore" });
813
+
814
+ execFileSync("git", ["checkout", "-b", "feature"], { cwd: base, stdio: "ignore" });
815
+ writeFileSync(join(base, "conflict.txt"), "feature\n");
816
+ execFileSync("git", ["add", "conflict.txt"], { cwd: base, stdio: "ignore" });
817
+ execFileSync("git", ["commit", "-m", "feature change"], { cwd: base, stdio: "ignore" });
818
+
819
+ execFileSync("git", ["checkout", "main"], { cwd: base, stdio: "ignore" });
820
+ writeFileSync(join(base, "conflict.txt"), "main\n");
821
+ execFileSync("git", ["add", "conflict.txt"], { cwd: base, stdio: "ignore" });
822
+ execFileSync("git", ["commit", "-m", "main change"], { cwd: base, stdio: "ignore" });
823
+
824
+ let mergeFailed = false;
825
+ try {
826
+ execFileSync("git", ["merge", "--no-ff", "feature"], { cwd: base, stdio: "ignore" });
827
+ } catch {
828
+ mergeFailed = true;
829
+ }
830
+ assert.equal(mergeFailed, true, "merge should produce a conflict");
831
+ assert.ok(existsSync(join(base, ".git", "MERGE_HEAD")), "MERGE_HEAD should remain present before reconcile");
832
+
833
+ const beforeContents = readFileSync(join(base, "conflict.txt"), "utf8");
834
+ assert.match(beforeContents, /<<<<<<<|=======|>>>>>>>/, "fixture should contain conflict markers");
835
+
836
+ const { ctx, notifications } = makeMockCtx();
837
+ const result = reconcileMergeState(base, ctx);
838
+
839
+ assert.equal(result, "blocked", "code conflicts should block reconciliation");
840
+ assert.ok(existsSync(join(base, ".git", "MERGE_HEAD")), "MERGE_HEAD should be preserved for manual resolution");
841
+ assert.equal(
842
+ readFileSync(join(base, "conflict.txt"), "utf8"),
843
+ beforeContents,
844
+ "reconcile should preserve the conflicted file contents",
845
+ );
846
+ assert.ok(
847
+ notifications.some((n) => n.level === "error" && n.msg.includes("manual conflict resolution is preserved")),
848
+ "should notify that auto-mode paused and preserved manual work",
849
+ );
850
+ });
851
+
812
852
  test("verifyExpectedArtifact complete-milestone passes with impl files (#1703)", (t) => {
813
853
  const base = makeGitBase();
814
854
  t.after(() => cleanup(base));
@@ -360,8 +360,8 @@ describe("session management", () => {
360
360
  assert.equal(s.unitRecoveryCount.size, 0, "recovery counts cleared");
361
361
  });
362
362
 
363
- test("NEW_SESSION_TIMEOUT_MS is 30 seconds", () => {
364
- assert.equal(NEW_SESSION_TIMEOUT_MS, 30_000, "session timeout should be 30s");
363
+ test("NEW_SESSION_TIMEOUT_MS is 120 seconds", () => {
364
+ assert.equal(NEW_SESSION_TIMEOUT_MS, 120_000, "session timeout should be 120s");
365
365
  });
366
366
 
367
367
  test("MAX_UNIT_DISPATCHES limits retries for a single unit", () => {
@@ -72,7 +72,7 @@ function makeMockDeps(
72
72
  getCurrentBranch: () => "main",
73
73
  autoWorktreeBranch: () => "auto/M001",
74
74
  resolveMilestoneFile: () => null,
75
- reconcileMergeState: () => false,
75
+ reconcileMergeState: () => "clean",
76
76
  getLedger: () => ({ units: [] }),
77
77
  getProjectTotals: () => ({ cost: 0 }),
78
78
  formatCost: (c: number) => `$${c.toFixed(2)}`,
@@ -590,9 +590,9 @@ test("unit-end event contains errorContext when unit is cancelled with structure
590
590
  resolveAgentEndCancelled({ message: "Hard timeout error: exceeded limit", category: "timeout", isTransient: true });
591
591
 
592
592
  const result = await unitPromise;
593
- // Cancelled units break the loop before emitting unit-end
593
+ // Transient timeout cancellations pause (recoverable) instead of hard-stopping
594
594
  assert.equal(result.action, "break");
595
- assert.equal((result as any).reason, "session-failed");
595
+ assert.equal((result as any).reason, "session-timeout");
596
596
 
597
597
  // Verify error classification used structured errorContext on the window entry
598
598
  const entry = loopState.recentUnits[loopState.recentUnits.length - 1];