gsd-pi 2.80.0-dev.c5f2443b3 → 2.80.0-dev.d4fc28e6b

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 (580) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.js +0 -19
  3. package/dist/resources/.managed-resources-content-hash +1 -1
  4. package/dist/resources/GSD-WORKFLOW.md +2 -2
  5. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
  6. package/dist/resources/extensions/github-sync/templates.js +39 -8
  7. package/dist/resources/extensions/gsd/auto/loop.js +119 -18
  8. package/dist/resources/extensions/gsd/auto/phases.js +212 -135
  9. package/dist/resources/extensions/gsd/auto/resolve.js +29 -0
  10. package/dist/resources/extensions/gsd/auto/run-unit.js +41 -45
  11. package/dist/resources/extensions/gsd/auto/session.js +8 -0
  12. package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
  13. package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +51 -15
  15. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +26 -0
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +27 -14
  18. package/dist/resources/extensions/gsd/auto-prompts.js +214 -17
  19. package/dist/resources/extensions/gsd/auto-recovery.js +197 -9
  20. package/dist/resources/extensions/gsd/auto-start.js +199 -9
  21. package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
  22. package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
  23. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  24. package/dist/resources/extensions/gsd/auto.js +95 -27
  25. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +103 -3
  26. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
  27. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
  28. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
  29. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
  30. package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +330 -55
  33. package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
  34. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +129 -1
  35. package/dist/resources/extensions/gsd/clean-root-preflight.js +65 -9
  36. package/dist/resources/extensions/gsd/commands/dispatcher.js +5 -0
  37. package/dist/resources/extensions/gsd/commands-extract-learnings.js +17 -12
  38. package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
  39. package/dist/resources/extensions/gsd/context-budget.js +37 -2
  40. package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
  41. package/dist/resources/extensions/gsd/custom-workflow-engine.js +22 -2
  42. package/dist/resources/extensions/gsd/db/unit-dispatches.js +92 -0
  43. package/dist/resources/extensions/gsd/db-base-schema.js +18 -2
  44. package/dist/resources/extensions/gsd/db-migration-steps.js +22 -0
  45. package/dist/resources/extensions/gsd/detection.js +106 -0
  46. package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
  47. package/dist/resources/extensions/gsd/git-service.js +36 -4
  48. package/dist/resources/extensions/gsd/graph.js +9 -3
  49. package/dist/resources/extensions/gsd/gsd-db.js +146 -13
  50. package/dist/resources/extensions/gsd/guided-flow.js +129 -44
  51. package/dist/resources/extensions/gsd/memory-store.js +69 -12
  52. package/dist/resources/extensions/gsd/migrate/command.js +40 -1
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
  54. package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
  55. package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
  56. package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
  57. package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
  58. package/dist/resources/extensions/gsd/pr-evidence.js +57 -16
  59. package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
  60. package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
  61. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  62. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  63. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  64. package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  66. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  67. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
  68. package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  70. package/dist/resources/extensions/gsd/quick.js +34 -2
  71. package/dist/resources/extensions/gsd/safety/evidence-collector.js +10 -2
  72. package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
  73. package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
  74. package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
  75. package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
  76. package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
  77. package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
  78. package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
  79. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
  80. package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
  81. package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
  82. package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
  83. package/dist/resources/extensions/gsd/working-output-messages.js +64 -0
  84. package/dist/resources/extensions/gsd/worktree-manager.js +16 -14
  85. package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
  86. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
  89. package/dist/web/standalone/.next/build-manifest.json +3 -3
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  109. package/dist/web/standalone/.next/server/app/index.html +1 -1
  110. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
  117. package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
  118. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  119. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  121. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  122. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  123. package/dist/web/standalone/.next/static/chunks/{8336.6f6f30e410419aff.js → 8336.631939fb583761fa.js} +1 -1
  124. package/dist/web/standalone/.next/static/chunks/{webpack-d82dbee6356c1733.js → webpack-0481f1221120a7c6.js} +1 -1
  125. package/dist/welcome-screen.d.ts +2 -0
  126. package/dist/welcome-screen.js +9 -7
  127. package/package.json +12 -8
  128. package/packages/contracts/package.json +1 -1
  129. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  130. package/packages/mcp-server/dist/workflow-tools.js +22 -17
  131. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  132. package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
  133. package/packages/mcp-server/src/workflow-tools.ts +30 -16
  134. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  135. package/packages/native/tsconfig.tsbuildinfo +1 -1
  136. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  137. package/packages/pi-agent-core/dist/agent-loop.js +4 -1
  138. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  139. package/packages/pi-agent-core/dist/agent.d.ts +5 -0
  140. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  141. package/packages/pi-agent-core/dist/agent.js +2 -0
  142. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  143. package/packages/pi-agent-core/dist/index.d.ts +1 -0
  144. package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
  145. package/packages/pi-agent-core/dist/index.js +2 -0
  146. package/packages/pi-agent-core/dist/index.js.map +1 -1
  147. package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
  148. package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
  149. package/packages/pi-agent-core/dist/token-audit.js +221 -0
  150. package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
  151. package/packages/pi-agent-core/dist/types.d.ts +9 -0
  152. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  153. package/packages/pi-agent-core/dist/types.js.map +1 -1
  154. package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
  155. package/packages/pi-agent-core/src/agent-loop.ts +4 -1
  156. package/packages/pi-agent-core/src/agent.ts +8 -0
  157. package/packages/pi-agent-core/src/index.ts +2 -0
  158. package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
  159. package/packages/pi-agent-core/src/token-audit.ts +287 -0
  160. package/packages/pi-agent-core/src/types.ts +14 -0
  161. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  162. package/packages/pi-ai/dist/models/fake-model.d.ts +12 -0
  163. package/packages/pi-ai/dist/models/fake-model.d.ts.map +1 -0
  164. package/packages/pi-ai/dist/models/fake-model.js +27 -0
  165. package/packages/pi-ai/dist/models/fake-model.js.map +1 -0
  166. package/packages/pi-ai/dist/models/index.d.ts.map +1 -1
  167. package/packages/pi-ai/dist/models/index.js +8 -0
  168. package/packages/pi-ai/dist/models/index.js.map +1 -1
  169. package/packages/pi-ai/dist/providers/fake.d.ts +42 -0
  170. package/packages/pi-ai/dist/providers/fake.d.ts.map +1 -0
  171. package/packages/pi-ai/dist/providers/fake.js +319 -0
  172. package/packages/pi-ai/dist/providers/fake.js.map +1 -0
  173. package/packages/pi-ai/dist/providers/register-builtins.d.ts.map +1 -1
  174. package/packages/pi-ai/dist/providers/register-builtins.js +24 -0
  175. package/packages/pi-ai/dist/providers/register-builtins.js.map +1 -1
  176. package/packages/pi-ai/src/models/fake-model.ts +30 -0
  177. package/packages/pi-ai/src/models/index.ts +9 -0
  178. package/packages/pi-ai/src/providers/fake.ts +376 -0
  179. package/packages/pi-ai/src/providers/register-builtins.ts +23 -0
  180. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  181. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
  182. package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
  183. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +18 -0
  184. package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
  185. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
  186. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  187. package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
  188. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  189. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +76 -0
  190. package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
  191. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
  192. package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  193. package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
  194. package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  195. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
  196. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
  197. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
  198. package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
  199. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
  200. package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
  201. package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
  202. package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
  203. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
  204. package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
  205. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
  206. package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -0
  207. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  208. package/packages/pi-coding-agent/dist/core/extensions/loader.js +8 -0
  209. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  210. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +5 -0
  211. package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  212. package/packages/pi-coding-agent/dist/core/extensions/runner.js +20 -7
  213. package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  214. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +102 -3
  215. package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
  216. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
  217. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  218. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  219. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
  220. package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  222. package/packages/pi-coding-agent/dist/core/model-registry.js +5 -0
  223. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  224. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
  225. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
  226. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
  227. package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
  228. package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
  229. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  230. package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
  231. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  232. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +24 -0
  233. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  234. package/packages/pi-coding-agent/dist/core/settings-manager.js +33 -0
  235. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  236. package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
  237. package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
  238. package/packages/pi-coding-agent/dist/core/slash-commands.d.ts.map +1 -1
  239. package/packages/pi-coding-agent/dist/core/slash-commands.js +1 -0
  240. package/packages/pi-coding-agent/dist/core/slash-commands.js.map +1 -1
  241. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
  242. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  243. package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
  244. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  245. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js +6 -4
  246. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.js.map +1 -1
  247. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +54 -15
  248. package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
  249. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts +26 -0
  250. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.d.ts.map +1 -0
  251. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js +112 -0
  252. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.js.map +1 -0
  253. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts +2 -0
  254. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.d.ts.map +1 -0
  255. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js +51 -0
  256. package/packages/pi-coding-agent/dist/modes/interactive/components/adaptive-layout.test.js.map +1 -0
  257. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  258. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  259. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
  260. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +10 -9
  261. package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
  262. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +3 -0
  263. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  264. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +11 -0
  265. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  266. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +7 -6
  267. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +17 -0
  269. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +109 -17
  271. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  273. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +69 -2
  274. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  275. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +93 -1
  276. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
  277. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +1 -0
  278. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +1 -0
  280. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  281. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  283. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  284. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +26 -0
  285. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  286. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js +20 -0
  288. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts +2 -0
  290. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.d.ts.map +1 -0
  291. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js +79 -0
  292. package/packages/pi-coding-agent/dist/modes/interactive/slash-command-handlers.test.js.map +1 -0
  293. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  294. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  295. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js +13 -0
  296. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
  298. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +18 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  301. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +36 -27
  303. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  304. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts +11 -0
  305. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.d.ts.map +1 -0
  306. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js +18 -0
  307. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.js.map +1 -0
  308. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts +2 -0
  309. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.d.ts.map +1 -0
  310. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js +48 -0
  311. package/packages/pi-coding-agent/dist/modes/interactive/tui-mode.test.js.map +1 -0
  312. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
  313. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
  314. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
  315. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
  316. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
  317. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
  318. package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
  319. package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
  320. package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
  321. package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
  322. package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +89 -0
  323. package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
  324. package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
  325. package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
  326. package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
  327. package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
  328. package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +113 -3
  329. package/packages/pi-coding-agent/src/core/extensions/runner.ts +24 -6
  330. package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
  331. package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
  332. package/packages/pi-coding-agent/src/core/model-registry.ts +4 -0
  333. package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
  334. package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
  335. package/packages/pi-coding-agent/src/core/settings-manager.ts +51 -1
  336. package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
  337. package/packages/pi-coding-agent/src/core/slash-commands.ts +1 -0
  338. package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
  339. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/chat-frame-compaction-tone.test.ts +7 -5
  340. package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +78 -15
  341. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.test.ts +59 -0
  342. package/packages/pi-coding-agent/src/modes/interactive/components/adaptive-layout.ts +160 -0
  343. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +1 -0
  344. package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +10 -9
  345. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
  346. package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +10 -9
  347. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +122 -17
  348. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +99 -1
  349. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +92 -3
  350. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +1 -0
  351. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +1 -1
  352. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +28 -0
  353. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.test.ts +95 -0
  354. package/packages/pi-coding-agent/src/modes/interactive/slash-command-handlers.ts +24 -1
  355. package/packages/pi-coding-agent/src/modes/interactive/theme/theme-schema.ts +13 -0
  356. package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +32 -2
  357. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +36 -27
  358. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.test.ts +65 -0
  359. package/packages/pi-coding-agent/src/modes/interactive/tui-mode.ts +29 -0
  360. package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
  361. package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
  362. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  363. package/packages/pi-tui/dist/__tests__/style.test.d.ts +2 -0
  364. package/packages/pi-tui/dist/__tests__/style.test.d.ts.map +1 -0
  365. package/packages/pi-tui/dist/__tests__/style.test.js +63 -0
  366. package/packages/pi-tui/dist/__tests__/style.test.js.map +1 -0
  367. package/packages/pi-tui/dist/__tests__/tui.test.js +24 -3
  368. package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
  369. package/packages/pi-tui/dist/index.d.ts +1 -0
  370. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  371. package/packages/pi-tui/dist/index.js +2 -0
  372. package/packages/pi-tui/dist/index.js.map +1 -1
  373. package/packages/pi-tui/dist/style.d.ts +41 -0
  374. package/packages/pi-tui/dist/style.d.ts.map +1 -0
  375. package/packages/pi-tui/dist/style.js +158 -0
  376. package/packages/pi-tui/dist/style.js.map +1 -0
  377. package/packages/pi-tui/dist/tui.d.ts +0 -1
  378. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  379. package/packages/pi-tui/dist/tui.js +21 -16
  380. package/packages/pi-tui/dist/tui.js.map +1 -1
  381. package/packages/pi-tui/src/__tests__/style.test.ts +76 -0
  382. package/packages/pi-tui/src/__tests__/tui.test.ts +29 -3
  383. package/packages/pi-tui/src/index.ts +9 -0
  384. package/packages/pi-tui/src/style.ts +225 -0
  385. package/packages/pi-tui/src/tui.ts +23 -16
  386. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  387. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts +12 -0
  388. package/pkg/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -1
  389. package/pkg/dist/modes/interactive/theme/theme-schema.js +13 -0
  390. package/pkg/dist/modes/interactive/theme/theme-schema.js.map +1 -1
  391. package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
  392. package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  393. package/pkg/dist/modes/interactive/theme/theme.js +18 -1
  394. package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
  395. package/pkg/dist/modes/interactive/theme/themes.d.ts.map +1 -1
  396. package/pkg/dist/modes/interactive/theme/themes.js +36 -27
  397. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  398. package/src/resources/GSD-WORKFLOW.md +2 -2
  399. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
  400. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
  401. package/src/resources/extensions/github-sync/templates.ts +38 -8
  402. package/src/resources/extensions/github-sync/tests/inline-code.test.ts +66 -0
  403. package/src/resources/extensions/gsd/auto/loop-deps.ts +3 -2
  404. package/src/resources/extensions/gsd/auto/loop.ts +151 -26
  405. package/src/resources/extensions/gsd/auto/phases.ts +289 -196
  406. package/src/resources/extensions/gsd/auto/resolve.ts +42 -1
  407. package/src/resources/extensions/gsd/auto/run-unit.ts +52 -44
  408. package/src/resources/extensions/gsd/auto/session.ts +8 -0
  409. package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
  410. package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
  411. package/src/resources/extensions/gsd/auto-dashboard.ts +57 -8
  412. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
  413. package/src/resources/extensions/gsd/auto-dispatch.ts +33 -0
  414. package/src/resources/extensions/gsd/auto-post-unit.ts +28 -14
  415. package/src/resources/extensions/gsd/auto-prompts.ts +228 -16
  416. package/src/resources/extensions/gsd/auto-recovery.ts +207 -7
  417. package/src/resources/extensions/gsd/auto-start.ts +237 -15
  418. package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
  419. package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
  420. package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
  421. package/src/resources/extensions/gsd/auto.ts +110 -22
  422. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +119 -2
  423. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
  424. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
  425. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
  426. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
  427. package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
  428. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
  429. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +386 -55
  430. package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
  431. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +135 -1
  432. package/src/resources/extensions/gsd/clean-root-preflight.ts +72 -9
  433. package/src/resources/extensions/gsd/commands/dispatcher.ts +6 -0
  434. package/src/resources/extensions/gsd/commands-extract-learnings.ts +17 -12
  435. package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
  436. package/src/resources/extensions/gsd/context-budget.ts +44 -2
  437. package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
  438. package/src/resources/extensions/gsd/custom-workflow-engine.ts +24 -1
  439. package/src/resources/extensions/gsd/db/unit-dispatches.ts +107 -0
  440. package/src/resources/extensions/gsd/db-base-schema.ts +19 -2
  441. package/src/resources/extensions/gsd/db-migration-steps.ts +25 -0
  442. package/src/resources/extensions/gsd/detection.ts +128 -0
  443. package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
  444. package/src/resources/extensions/gsd/git-service.ts +46 -8
  445. package/src/resources/extensions/gsd/graph.ts +12 -5
  446. package/src/resources/extensions/gsd/gsd-db.ts +168 -13
  447. package/src/resources/extensions/gsd/guided-flow.ts +150 -51
  448. package/src/resources/extensions/gsd/memory-store.ts +77 -12
  449. package/src/resources/extensions/gsd/migrate/command.ts +47 -1
  450. package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
  451. package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
  452. package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
  453. package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
  454. package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
  455. package/src/resources/extensions/gsd/pr-evidence.ts +63 -5
  456. package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
  457. package/src/resources/extensions/gsd/preferences-types.ts +1 -1
  458. package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
  459. package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -19
  460. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  461. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  462. package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
  463. package/src/resources/extensions/gsd/prompts/plan-milestone.md +3 -1
  464. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  465. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
  466. package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
  467. package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
  468. package/src/resources/extensions/gsd/quick.ts +37 -2
  469. package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -2
  470. package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
  471. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +7 -1
  472. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +33 -0
  473. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +516 -15
  474. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
  475. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +184 -2
  476. package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
  477. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +97 -2
  478. package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +9 -0
  479. package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
  480. package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
  481. package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
  482. package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
  483. package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
  484. package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
  485. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
  486. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +117 -7
  487. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +40 -2
  488. package/src/resources/extensions/gsd/tests/db-migration-steps.integration.test.ts +428 -0
  489. package/src/resources/extensions/gsd/tests/db-schema-metadata.test.ts +2 -2
  490. package/src/resources/extensions/gsd/tests/detection.test.ts +140 -0
  491. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
  492. package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
  493. package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
  494. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
  495. package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
  496. package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
  497. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-basic.md +52 -0
  498. package/src/resources/extensions/gsd/tests/fixtures/pr-body/commands-ship-empty-optionals.md +42 -0
  499. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +55 -0
  500. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +60 -0
  501. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +10 -0
  502. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +44 -0
  503. package/src/resources/extensions/gsd/tests/has-pending-deep-stage.test.ts +33 -1
  504. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
  505. package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
  506. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
  507. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
  508. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
  509. package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
  510. package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
  511. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
  512. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
  513. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
  514. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
  515. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
  516. package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
  517. package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
  518. package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
  519. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
  520. package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
  521. package/src/resources/extensions/gsd/tests/pr-evidence-equivalence.test.ts +102 -0
  522. package/src/resources/extensions/gsd/tests/pr-evidence-hardening.test.ts +165 -0
  523. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
  524. package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
  525. package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
  526. package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
  527. package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
  528. package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
  529. package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
  530. package/src/resources/extensions/gsd/tests/right-sized-workflow-prompts.test.ts +192 -0
  531. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +29 -0
  532. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
  533. package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
  534. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
  535. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
  536. package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
  537. package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +38 -0
  538. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
  539. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +101 -2
  540. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  541. package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
  542. package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
  543. package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
  544. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
  545. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
  546. package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +80 -1
  547. package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
  548. package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
  549. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  550. package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
  551. package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
  552. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
  553. package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
  554. package/src/resources/extensions/gsd/tests/working-output-messages.test.ts +93 -0
  555. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +37 -6
  556. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
  557. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +7 -0
  558. package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +9 -2
  559. package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
  560. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
  561. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
  562. package/src/resources/extensions/gsd/tests/worktree-write-gate.test.ts +179 -0
  563. package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
  564. package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
  565. package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
  566. package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
  567. package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
  568. package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
  569. package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
  570. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
  571. package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
  572. package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
  573. package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
  574. package/src/resources/extensions/gsd/working-output-messages.ts +120 -0
  575. package/src/resources/extensions/gsd/worktree-manager.ts +15 -4
  576. package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
  577. package/packages/contracts/tsconfig.tsbuildinfo +0 -1
  578. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
  579. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{bQDK5_LtkGVS64AirQgQG → cWaxzf-sdbSSbbwYu8q7a}/_ssgManifest.js +0 -0
@@ -32,13 +32,13 @@ import { detectStuck } from "./detect-stuck.js";
32
32
  import { runUnit } from "./run-unit.js";
33
33
  import { debugLog } from "../debug-logger.js";
34
34
  import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
35
- import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
35
+ import { classifyProject } from "../detection.js";
36
36
  import { MergeConflictError } from "../git-service.js";
37
37
  import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
38
38
  import { pauseAutoForProviderError } from "../provider-error-pause.js";
39
39
  import { resumeAutoAfterProviderDelay } from "../bootstrap/provider-error-resume.js";
40
40
  import { join, basename } from "node:path";
41
- import { existsSync, cpSync, readdirSync } from "node:fs";
41
+ import { existsSync, cpSync } from "node:fs";
42
42
  import {
43
43
  logWarning,
44
44
  logError,
@@ -50,13 +50,14 @@ import {
50
50
  } from "../workflow-logger.js";
51
51
  import { gsdRoot } from "../paths.js";
52
52
  import { atomicWriteSync } from "../atomic-write.js";
53
- import { verifyExpectedArtifact, diagnoseExpectedArtifact, buildLoopRemediationSteps } from "../auto-recovery.js";
53
+ import { verifyExpectedArtifact, diagnoseExpectedArtifact, buildLoopRemediationSteps, refreshRecoveryDbForArtifact } from "../auto-recovery.js";
54
54
  import { writeUnitRuntimeRecord } from "../unit-runtime.js";
55
55
  import { withTimeout, FINALIZE_PRE_TIMEOUT_MS, FINALIZE_POST_TIMEOUT_MS } from "./finalize-timeout.js";
56
56
  import { getEligibleSlices } from "../slice-parallel-eligibility.js";
57
57
  import { startSliceParallel } from "../slice-parallel-orchestrator.js";
58
- import { isDbAvailable, getMilestoneSlices, refreshOpenDatabaseFromDisk } from "../gsd-db.js";
58
+ import { isDbAvailable, getMilestoneSlices } from "../gsd-db.js";
59
59
  import type { MinimalModelRegistry } from "../context-budget.js";
60
+ import type { PostflightResult, PreflightResult } from "../clean-root-preflight.js";
60
61
  import { ensurePlanV2Graph, isEmptyPlanV2GraphResult, isMissingFinalizedContextResult } from "../uok/plan-v2.js";
61
62
  import { resolveUokFlags } from "../uok/flags.js";
62
63
  import { UokGateRunner } from "../uok/gate-runner.js";
@@ -76,10 +77,15 @@ function isSamePathLocal(a: string, b: string): boolean {
76
77
  return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
77
78
  }
78
79
 
79
- function refreshPlanSliceRecoveryDbIfNeeded(unitType: string): boolean {
80
- if (unitType !== "plan-slice") return true;
81
- if (!isDbAvailable()) return true;
82
- return refreshOpenDatabaseFromDisk();
80
+ export function shouldDegradeEmptyWorktreeToProjectRoot(
81
+ worktreeClassification: ReturnType<typeof classifyProject>,
82
+ projectRootClassification: ReturnType<typeof classifyProject>,
83
+ ): boolean {
84
+ return (
85
+ worktreeClassification.kind === "greenfield" &&
86
+ projectRootClassification.kind !== "greenfield" &&
87
+ projectRootClassification.kind !== "invalid-repo"
88
+ );
83
89
  }
84
90
 
85
91
  // ─── Session timeout auto-resume state ────────────────────────────────────────
@@ -215,6 +221,117 @@ async function closeoutAndStop(
215
221
  await deps.stopAuto(ctx, pi, reason);
216
222
  }
217
223
 
224
+ async function stopOnPostflightRecoveryNeeded(
225
+ ic: IterationContext,
226
+ result: PostflightResult,
227
+ milestoneId: string,
228
+ ): Promise<{ action: "break"; reason: string } | null> {
229
+ if (!result.needsManualRecovery) return null;
230
+ const { ctx, pi, deps } = ic;
231
+ const reason = `Post-merge stash restore failed for milestone ${milestoneId}`;
232
+ ctx.ui.notify(
233
+ `${reason}. Resolve the working tree before resuming auto-mode. ${result.message}`,
234
+ "error",
235
+ );
236
+ await deps.stopAuto(ctx, pi, reason);
237
+ return { action: "break", reason: "postflight-stash-restore-failed" };
238
+ }
239
+
240
+ async function restorePreflightStashOrStop(
241
+ ic: IterationContext,
242
+ preflight: PreflightResult,
243
+ milestoneId: string,
244
+ ): Promise<{ action: "break"; reason: string } | null> {
245
+ if (!preflight.stashPushed) return null;
246
+ const { ctx, s, deps } = ic;
247
+ const result = deps.postflightPopStash(
248
+ s.originalBasePath || s.basePath,
249
+ milestoneId,
250
+ preflight.stashMarker,
251
+ ctx.ui.notify.bind(ctx.ui),
252
+ );
253
+ return stopOnPostflightRecoveryNeeded(ic, result, milestoneId);
254
+ }
255
+
256
+ /**
257
+ * Run a milestone merge surrounded by preflight stash + always-on postflight
258
+ * pop. The previous code popped the stash only after a successful merge, which
259
+ * leaked `gsd-preflight-stash:M00x:*` entries whenever `mergeAndExit` threw —
260
+ * leaving the user's pre-merge working tree silently stashed away after a
261
+ * merge-conflict or other merge error. This helper restores the stash on
262
+ * every exit path, then surfaces the merge or stash failure (in priority
263
+ * order) as the loop's stop reason.
264
+ *
265
+ * Returns a `break` action when auto-mode must stop, or `null` when the merge
266
+ * succeeded and the stash (if any) was restored cleanly.
267
+ */
268
+ export async function _runMilestoneMergeWithStashRestore(
269
+ ic: IterationContext,
270
+ milestoneId: string,
271
+ ): Promise<{ action: "break"; reason: string } | null> {
272
+ const { ctx, pi, s, deps } = ic;
273
+
274
+ const preflight = deps.preflightCleanRoot(
275
+ s.originalBasePath || s.basePath,
276
+ milestoneId,
277
+ ctx.ui.notify.bind(ctx.ui),
278
+ );
279
+
280
+ let mergeError: unknown = null;
281
+ try {
282
+ deps.resolver.mergeAndExit(milestoneId, ctx.ui);
283
+ s.milestoneMergedInPhases = true;
284
+ } catch (mergeErr) {
285
+ mergeError = mergeErr;
286
+ }
287
+
288
+ // Always attempt to restore the stashed working tree, even on merge error.
289
+ // postflightPopStash itself does not throw; failures surface via the
290
+ // PostflightResult.needsManualRecovery flag.
291
+ let stashResult: PostflightResult | null = null;
292
+ if (preflight.stashPushed) {
293
+ stashResult = deps.postflightPopStash(
294
+ s.originalBasePath || s.basePath,
295
+ milestoneId,
296
+ preflight.stashMarker,
297
+ ctx.ui.notify.bind(ctx.ui),
298
+ );
299
+ }
300
+
301
+ // Merge failure takes priority over stash recovery — the merge is the
302
+ // authoritative gate. If the stash also needed manual recovery, the user
303
+ // already saw the postflightPopStash notify above.
304
+ if (mergeError) {
305
+ if (mergeError instanceof MergeConflictError) {
306
+ ctx.ui.notify(
307
+ `Merge conflict: ${mergeError.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
308
+ "error",
309
+ );
310
+ await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${milestoneId}`);
311
+ return { action: "break", reason: "merge-conflict" };
312
+ }
313
+ logError("engine", "Milestone merge failed with non-conflict error", {
314
+ milestone: milestoneId,
315
+ error: String(mergeError),
316
+ });
317
+ ctx.ui.notify(
318
+ `Merge failed: ${mergeError instanceof Error ? mergeError.message : String(mergeError)}. Resolve and run /gsd auto to resume.`,
319
+ "error",
320
+ );
321
+ await deps.stopAuto(
322
+ ctx,
323
+ pi,
324
+ `Merge error on milestone ${milestoneId}: ${String(mergeError)}`,
325
+ );
326
+ return { action: "break", reason: "merge-failed" };
327
+ }
328
+
329
+ if (stashResult) {
330
+ return stopOnPostflightRecoveryNeeded(ic, stashResult, milestoneId);
331
+ }
332
+ return null;
333
+ }
334
+
218
335
  async function emitCancelledUnitEnd(
219
336
  ic: IterationContext,
220
337
  unitType: string,
@@ -651,41 +768,11 @@ export async function runPreDispatch(
651
768
  loopState.recentUnits.length = 0;
652
769
  loopState.stuckRecoveryAttempts = 0;
653
770
 
654
- // Worktree lifecycle on milestone transition — merge current, enter next
655
- // #2909: preflight warn + stash dirty working tree before merge
656
- const preflightTransition = deps.preflightCleanRoot(
657
- s.originalBasePath || s.basePath,
658
- s.currentMilestoneId!,
659
- ctx.ui.notify.bind(ctx.ui),
660
- );
661
- try {
662
- deps.resolver.mergeAndExit(s.currentMilestoneId!, ctx.ui);
663
- } catch (mergeErr) {
664
- if (mergeErr instanceof MergeConflictError) {
665
- // Real code conflicts — stop the loop instead of retrying forever (#2330)
666
- ctx.ui.notify(
667
- `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
668
- "error",
669
- );
670
- await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
671
- return { action: "break", reason: "merge-conflict" };
672
- }
673
- // Non-conflict merge errors — stop auto to avoid advancing with unmerged work
674
- logError("engine", "Milestone merge failed with non-conflict error", { milestone: s.currentMilestoneId!, error: String(mergeErr) });
675
- ctx.ui.notify(
676
- `Merge failed: ${mergeErr instanceof Error ? mergeErr.message : String(mergeErr)}. Resolve and run /gsd auto to resume.`,
677
- "error",
678
- );
679
- await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
680
- return { action: "break", reason: "merge-failed" };
681
- }
682
- // #2909: postflight — restore stashed changes after successful merge
683
- if (preflightTransition.stashPushed) {
684
- deps.postflightPopStash(
685
- s.originalBasePath || s.basePath,
686
- s.currentMilestoneId!,
687
- ctx.ui.notify.bind(ctx.ui),
688
- );
771
+ // Worktree lifecycle on milestone transition — merge current, enter next.
772
+ // #2909 / #5538-followup: preflight stash + always-on postflight pop.
773
+ {
774
+ const stop = await _runMilestoneMergeWithStashRestore(ic, s.currentMilestoneId!);
775
+ if (stop) return stop;
689
776
  }
690
777
 
691
778
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
@@ -763,44 +850,11 @@ export async function runPreDispatch(
763
850
  m.status !== "complete" && m.status !== "parked",
764
851
  );
765
852
  if (incomplete.length === 0 && state.registry.length > 0) {
766
- // All milestones complete — merge milestone branch before stopping
853
+ // All milestones complete — merge milestone branch before stopping.
767
854
  if (s.currentMilestoneId) {
768
- // #2909: preflight warn + stash dirty working tree before merge
769
- const preflightAllComplete = deps.preflightCleanRoot(
770
- s.originalBasePath || s.basePath,
771
- s.currentMilestoneId,
772
- ctx.ui.notify.bind(ctx.ui),
773
- );
774
- try {
775
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
776
- // Prevent stopAuto from attempting the same merge (#2645)
777
- s.milestoneMergedInPhases = true;
778
- } catch (mergeErr) {
779
- if (mergeErr instanceof MergeConflictError) {
780
- ctx.ui.notify(
781
- `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
782
- "error",
783
- );
784
- await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
785
- return { action: "break", reason: "merge-conflict" };
786
- }
787
- logError("engine", "Milestone merge failed with non-conflict error", { milestone: s.currentMilestoneId!, error: String(mergeErr) });
788
- ctx.ui.notify(
789
- `Merge failed: ${mergeErr instanceof Error ? mergeErr.message : String(mergeErr)}. Resolve and run /gsd auto to resume.`,
790
- "error",
791
- );
792
- await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
793
- return { action: "break", reason: "merge-failed" };
794
- }
795
- // #2909: postflight — restore stashed changes after successful merge
796
- if (preflightAllComplete.stashPushed) {
797
- deps.postflightPopStash(
798
- s.originalBasePath || s.basePath,
799
- s.currentMilestoneId,
800
- ctx.ui.notify.bind(ctx.ui),
801
- );
802
- }
803
-
855
+ // #2909 / #5538-followup: preflight stash + always-on postflight pop.
856
+ const stop = await _runMilestoneMergeWithStashRestore(ic, s.currentMilestoneId);
857
+ if (stop) return stop;
804
858
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
805
859
  }
806
860
  deps.sendDesktopNotification(
@@ -891,44 +945,11 @@ export async function runPreDispatch(
891
945
 
892
946
  // Terminal: complete
893
947
  if (state.phase === "complete") {
894
- // Milestone merge on complete (before closeout so branch state is clean)
948
+ // Milestone merge on complete (before closeout so branch state is clean).
895
949
  if (s.currentMilestoneId) {
896
- // #2909: preflight warn + stash dirty working tree before merge
897
- const preflightComplete = deps.preflightCleanRoot(
898
- s.originalBasePath || s.basePath,
899
- s.currentMilestoneId,
900
- ctx.ui.notify.bind(ctx.ui),
901
- );
902
- try {
903
- deps.resolver.mergeAndExit(s.currentMilestoneId, ctx.ui);
904
- // Prevent stopAuto from attempting the same merge (#2645)
905
- s.milestoneMergedInPhases = true;
906
- } catch (mergeErr) {
907
- if (mergeErr instanceof MergeConflictError) {
908
- ctx.ui.notify(
909
- `Merge conflict: ${mergeErr.conflictedFiles.join(", ")}. Resolve conflicts manually and run /gsd auto to resume.`,
910
- "error",
911
- );
912
- await deps.stopAuto(ctx, pi, `Merge conflict on milestone ${s.currentMilestoneId}`);
913
- return { action: "break", reason: "merge-conflict" };
914
- }
915
- logError("engine", "Milestone merge failed with non-conflict error", { milestone: s.currentMilestoneId!, error: String(mergeErr) });
916
- ctx.ui.notify(
917
- `Merge failed: ${mergeErr instanceof Error ? mergeErr.message : String(mergeErr)}. Resolve and run /gsd auto to resume.`,
918
- "error",
919
- );
920
- await deps.stopAuto(ctx, pi, `Merge error on milestone ${s.currentMilestoneId}: ${String(mergeErr)}`);
921
- return { action: "break", reason: "merge-failed" };
922
- }
923
- // #2909: postflight — restore stashed changes after successful merge
924
- if (preflightComplete.stashPushed) {
925
- deps.postflightPopStash(
926
- s.originalBasePath || s.basePath,
927
- s.currentMilestoneId,
928
- ctx.ui.notify.bind(ctx.ui),
929
- );
930
- }
931
-
950
+ // #2909 / #5538-followup: preflight stash + always-on postflight pop.
951
+ const stop = await _runMilestoneMergeWithStashRestore(ic, s.currentMilestoneId);
952
+ if (stop) return stop;
932
953
  // PR creation (auto_pr) is handled inside mergeMilestoneToMain (#2302)
933
954
  }
934
955
  deps.sendDesktopNotification(
@@ -1051,6 +1072,65 @@ export async function runDispatch(
1051
1072
  let prompt = dispatchResult.prompt;
1052
1073
  const pauseAfterUatDispatch = dispatchResult.pauseAfterDispatch ?? false;
1053
1074
 
1075
+ // Resolve hooks and prior-slice gating before health/stuck accounting so
1076
+ // those checks run against the final dispatch unit.
1077
+ const preDispatchResult = deps.runPreDispatchHooks(
1078
+ unitType,
1079
+ unitId,
1080
+ prompt,
1081
+ s.basePath,
1082
+ );
1083
+ if (preDispatchResult.firedHooks.length > 0) {
1084
+ ctx.ui.notify(
1085
+ `Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`,
1086
+ "info",
1087
+ );
1088
+ deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "pre-dispatch-hook", data: { firedHooks: preDispatchResult.firedHooks, action: preDispatchResult.action } });
1089
+ }
1090
+ if (preDispatchResult.action === "skip") {
1091
+ ctx.ui.notify(
1092
+ `Skipping ${unitType} ${unitId} (pre-dispatch hook).`,
1093
+ "info",
1094
+ );
1095
+ await new Promise((r) => setImmediate(r));
1096
+ return { action: "continue" };
1097
+ }
1098
+ if (preDispatchResult.action === "replace") {
1099
+ prompt = preDispatchResult.prompt ?? prompt;
1100
+ if (preDispatchResult.unitType) unitType = preDispatchResult.unitType;
1101
+ } else if (preDispatchResult.prompt) {
1102
+ prompt = preDispatchResult.prompt;
1103
+ }
1104
+
1105
+ const guardBasePath = _resolveDispatchGuardBasePath(s);
1106
+ const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(
1107
+ guardBasePath,
1108
+ deps.getMainBranch(guardBasePath),
1109
+ unitType,
1110
+ unitId,
1111
+ );
1112
+ if (priorSliceBlocker) {
1113
+ await deps.stopAuto(ctx, pi, priorSliceBlocker);
1114
+ debugLog("autoLoop", { phase: "exit", reason: "prior-slice-blocker" });
1115
+ return { action: "break", reason: "prior-slice-blocker" };
1116
+ }
1117
+
1118
+ // Execute-task needs a real writable checkout. The same health check also
1119
+ // exists in runUnitPhase, but the stuck-window detector runs before that
1120
+ // phase. Check here too so repeated derivations of a broken worktree stop
1121
+ // with the actionable worktree error instead of the generic stuck-loop error.
1122
+ if (s.basePath && unitType === "execute-task") {
1123
+ const gitMarker = join(s.basePath, ".git");
1124
+ const hasGit = deps.existsSync(gitMarker);
1125
+ if (!hasGit) {
1126
+ const msg = `Worktree health check failed: ${s.basePath} has no .git — refusing to dispatch ${unitType} ${unitId}`;
1127
+ debugLog("autoLoop", { phase: "dispatch-worktree-health-fail", basePath: s.basePath, hasGit });
1128
+ ctx.ui.notify(msg, "error");
1129
+ await deps.stopAuto(ctx, pi, msg);
1130
+ return { action: "break", reason: "worktree-invalid" };
1131
+ }
1132
+ }
1133
+
1054
1134
  // ── Sliding-window stuck detection with graduated recovery ──
1055
1135
  const derivedKey = `${unitType}/${unitId}`;
1056
1136
 
@@ -1097,17 +1177,24 @@ export async function runDispatch(
1097
1177
  level: 1,
1098
1178
  action: "artifact-found",
1099
1179
  });
1100
- ctx.ui.notify(
1101
- `Stuck recovery: artifact for ${unitType} ${unitId} found on disk. Invalidating caches.`,
1102
- "info",
1103
- );
1104
- if (!refreshPlanSliceRecoveryDbIfNeeded(unitType)) {
1180
+ const recoveryDb = refreshRecoveryDbForArtifact(unitType, unitId);
1181
+ if (!recoveryDb.ok) {
1105
1182
  ctx.ui.notify(
1106
- `Stuck recovery found ${unitType} ${unitId} artifacts, but the DB refresh failed. Keeping stuck state for retry.`,
1183
+ recoveryDb.fatal
1184
+ ? `${recoveryDb.message} Pausing auto-mode for manual recovery.`
1185
+ : `${recoveryDb.message} Keeping stuck state for retry.`,
1107
1186
  "warning",
1108
1187
  );
1188
+ if (recoveryDb.fatal) {
1189
+ await deps.pauseAuto(ctx, pi);
1190
+ return { action: "break", reason: recoveryDb.reason };
1191
+ }
1109
1192
  return { action: "continue" };
1110
1193
  }
1194
+ ctx.ui.notify(
1195
+ `Stuck recovery: artifact for ${unitType} ${unitId} found on disk. Invalidating caches.`,
1196
+ "info",
1197
+ );
1111
1198
  deps.invalidateAllCaches();
1112
1199
  loopState.recentUnits.length = 0;
1113
1200
  loopState.stuckRecoveryAttempts = 0;
@@ -1132,19 +1219,26 @@ export async function runDispatch(
1132
1219
  level: 2,
1133
1220
  action: "artifact-found",
1134
1221
  });
1135
- ctx.ui.notify(
1136
- `Stuck recovery: artifact for ${unitType} ${unitId} found on disk after cache invalidation. Continuing.`,
1137
- "info",
1138
- );
1139
- if (refreshPlanSliceRecoveryDbIfNeeded(unitType)) {
1222
+ const recoveryDb = refreshRecoveryDbForArtifact(unitType, unitId);
1223
+ if (recoveryDb.ok) {
1224
+ ctx.ui.notify(
1225
+ `Stuck recovery: artifact for ${unitType} ${unitId} found on disk after cache invalidation. Continuing.`,
1226
+ "info",
1227
+ );
1140
1228
  loopState.recentUnits.length = 0;
1141
1229
  loopState.stuckRecoveryAttempts = 0;
1142
1230
  return { action: "continue" };
1143
1231
  }
1144
1232
  ctx.ui.notify(
1145
- `Stuck recovery found ${unitType} ${unitId} artifacts, but the DB refresh failed. Stopping for manual recovery.`,
1233
+ recoveryDb.fatal
1234
+ ? `${recoveryDb.message} Pausing auto-mode for manual recovery.`
1235
+ : `${recoveryDb.message} Stopping for manual recovery.`,
1146
1236
  "warning",
1147
1237
  );
1238
+ if (recoveryDb.fatal) {
1239
+ await deps.pauseAuto(ctx, pi);
1240
+ return { action: "break", reason: recoveryDb.reason };
1241
+ }
1148
1242
  }
1149
1243
  debugLog("autoLoop", {
1150
1244
  phase: "stuck-detected",
@@ -1178,48 +1272,6 @@ export async function runDispatch(
1178
1272
  }
1179
1273
  }
1180
1274
 
1181
- // Pre-dispatch hooks
1182
- const preDispatchResult = deps.runPreDispatchHooks(
1183
- unitType,
1184
- unitId,
1185
- prompt,
1186
- s.basePath,
1187
- );
1188
- if (preDispatchResult.firedHooks.length > 0) {
1189
- ctx.ui.notify(
1190
- `Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`,
1191
- "info",
1192
- );
1193
- deps.emitJournalEvent({ ts: new Date().toISOString(), flowId: ic.flowId, seq: ic.nextSeq(), eventType: "pre-dispatch-hook", data: { firedHooks: preDispatchResult.firedHooks, action: preDispatchResult.action } });
1194
- }
1195
- if (preDispatchResult.action === "skip") {
1196
- ctx.ui.notify(
1197
- `Skipping ${unitType} ${unitId} (pre-dispatch hook).`,
1198
- "info",
1199
- );
1200
- await new Promise((r) => setImmediate(r));
1201
- return { action: "continue" };
1202
- }
1203
- if (preDispatchResult.action === "replace") {
1204
- prompt = preDispatchResult.prompt ?? prompt;
1205
- if (preDispatchResult.unitType) unitType = preDispatchResult.unitType;
1206
- } else if (preDispatchResult.prompt) {
1207
- prompt = preDispatchResult.prompt;
1208
- }
1209
-
1210
- const guardBasePath = _resolveDispatchGuardBasePath(s);
1211
- const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(
1212
- guardBasePath,
1213
- deps.getMainBranch(guardBasePath),
1214
- unitType,
1215
- unitId,
1216
- );
1217
- if (priorSliceBlocker) {
1218
- await deps.stopAuto(ctx, pi, priorSliceBlocker);
1219
- debugLog("autoLoop", { phase: "exit", reason: "prior-slice-blocker" });
1220
- return { action: "break", reason: "prior-slice-blocker" };
1221
- }
1222
-
1223
1275
  return {
1224
1276
  action: "next",
1225
1277
  data: {
@@ -1484,8 +1536,9 @@ export async function runUnitPhase(
1484
1536
  // Verify the working directory is a valid git checkout with project
1485
1537
  // files before dispatching work. A broken worktree causes agents to
1486
1538
  // hallucinate summaries since they cannot read or write any files.
1487
- // Uses the shared PROJECT_FILES list from detection.ts to support all
1488
- // ecosystems (Rust, Go, Python, Java, etc.), not just JS.
1539
+ // Uses project classification so project presence is not conflated with
1540
+ // ecosystem marker detection. Static/minimal repos become untyped-existing.
1541
+ let projectClassification: ReturnType<typeof classifyProject> | null = null;
1489
1542
  if (s.basePath && unitType === "execute-task") {
1490
1543
  const gitMarker = join(s.basePath, ".git");
1491
1544
  const hasGit = deps.existsSync(gitMarker);
@@ -1496,30 +1549,52 @@ export async function runUnitPhase(
1496
1549
  await deps.stopAuto(ctx, pi, msg);
1497
1550
  return { action: "break", reason: "worktree-invalid" };
1498
1551
  }
1499
- const hasProjectFile = PROJECT_FILES.some((f) => deps.existsSync(join(s.basePath, f)));
1500
- const hasSrcDir = deps.existsSync(join(s.basePath, "src"));
1501
- // Xcode bundles have project-specific names (*.xcodeproj, *.xcworkspace)
1502
- // that cannot be matched by exact filename — scan the directory by suffix.
1503
- let hasXcodeBundle = false;
1504
- try {
1505
- const entries = deps.existsSync(s.basePath) ? readdirSync(s.basePath) : [];
1506
- hasXcodeBundle = entries.some((e: string) => e.endsWith(".xcodeproj") || e.endsWith(".xcworkspace"));
1507
- } catch (err) {
1508
- debugLog("runUnitPhase", { phase: "xcode-bundle-scan-failed", basePath: s.basePath, error: String(err) });
1552
+ projectClassification = classifyProject(s.basePath);
1553
+ if (projectClassification.kind === "invalid-repo") {
1554
+ const msg = `Worktree health check failed: ${s.basePath} classified as invalid-repo (${projectClassification.reason}) — refusing to dispatch ${unitType} ${unitId}`;
1555
+ debugLog("runUnitPhase", { phase: "worktree-health-invalid-repo", basePath: s.basePath, classification: projectClassification });
1556
+ if (projectClassification.reason === "missing .git" && hasGit) {
1557
+ ctx.ui.notify(
1558
+ `Warning: ${s.basePath} project classification could not confirm .git; assuming it has no project content yet — proceeding as greenfield project because worktree health reported .git present`,
1559
+ "warning",
1560
+ );
1561
+ } else {
1562
+ ctx.ui.notify(msg, "error");
1563
+ await deps.stopAuto(ctx, pi, msg);
1564
+ return { action: "break", reason: "worktree-invalid" };
1565
+ }
1566
+ } else if (projectClassification.kind === "greenfield") {
1567
+ const projectRoot = s.canonicalProjectRoot;
1568
+ if (!isSamePathLocal(s.basePath, projectRoot)) {
1569
+ const projectRootClassification = classifyProject(projectRoot);
1570
+ if (shouldDegradeEmptyWorktreeToProjectRoot(projectClassification, projectRootClassification)) {
1571
+ debugLog("runUnitPhase", {
1572
+ phase: "worktree-health-degrade-to-project-root",
1573
+ worktreePath: s.basePath,
1574
+ projectRoot,
1575
+ worktreeClassification: projectClassification,
1576
+ projectRootClassification,
1577
+ });
1578
+ ctx.ui.notify(
1579
+ `Warning: ${s.basePath} has no project content, but ${projectRoot} does. Continuing in project root because the milestone worktree cannot represent untracked project files.`,
1580
+ "warning",
1581
+ );
1582
+ s.basePath = projectRoot;
1583
+ s.isolationDegraded = true;
1584
+ projectClassification = projectRootClassification;
1585
+ }
1586
+ }
1509
1587
  }
1510
- // Monorepo support (#2347): if no project files in the worktree directory,
1511
- // walk parent directories up to the filesystem root. In monorepos,
1512
- // package.json / Cargo.toml etc. live in a parent directory.
1513
- const hasProjectFileInParent =
1514
- !hasProjectFile && !hasSrcDir && !hasXcodeBundle
1515
- ? hasProjectFileInAncestor(s.basePath, deps.existsSync)
1516
- : false;
1517
- if (!hasProjectFile && !hasSrcDir && !hasXcodeBundle && !hasProjectFileInParent) {
1518
- // Greenfield projects won't have project files yet — the first task creates them.
1519
- // Log a warning but allow execution to proceed. The .git check above is sufficient
1520
- // to ensure we're in a valid working directory.
1521
- debugLog("runUnitPhase", { phase: "worktree-health-warn-greenfield", basePath: s.basePath, hasProjectFile, hasSrcDir, hasXcodeBundle });
1522
- ctx.ui.notify(`Warning: ${s.basePath} has no recognized project files — proceeding as greenfield project`, "warning");
1588
+
1589
+ if (projectClassification.kind === "greenfield") {
1590
+ debugLog("runUnitPhase", { phase: "worktree-health-greenfield", basePath: s.basePath, classification: projectClassification });
1591
+ ctx.ui.notify(`Warning: ${s.basePath} has no project content yet — proceeding as greenfield project`, "warning");
1592
+ } else if (projectClassification.kind === "untyped-existing") {
1593
+ debugLog("runUnitPhase", { phase: "worktree-health-untyped-existing", basePath: s.basePath, classification: projectClassification });
1594
+ ctx.ui.notify(
1595
+ `Notice: ${s.basePath} has existing project content but no recognized tooling markers — using generic file-level workflow guidance`,
1596
+ "info",
1597
+ );
1523
1598
  }
1524
1599
  }
1525
1600
 
@@ -1598,6 +1673,17 @@ export async function runUnitPhase(
1598
1673
  // Prompt injection
1599
1674
  let finalPrompt = prompt;
1600
1675
 
1676
+ if (unitType === "execute-task") {
1677
+ projectClassification ??= classifyProject(s.basePath);
1678
+ if (projectClassification.kind === "untyped-existing") {
1679
+ const samples = projectClassification.contentFiles.slice(0, 8).join(", ") || "project files";
1680
+ finalPrompt +=
1681
+ "\n\n**Project classification:** Existing untyped project. No recognized build/tooling markers were detected, " +
1682
+ "so use generic file-level workflow guidance. Task plans and completion summaries must list every concrete " +
1683
+ `project file changed in \`files\` or \`expected_output\`. Detected content sample: ${samples}.`;
1684
+ }
1685
+ }
1686
+
1601
1687
  if (s.pendingVerificationRetry) {
1602
1688
  const retryCtx = s.pendingVerificationRetry;
1603
1689
  s.pendingVerificationRetry = null;
@@ -2251,6 +2337,13 @@ export async function runFinalize(
2251
2337
 
2252
2338
  // Both pre and post verification completed without timeout — reset counter
2253
2339
  loopState.consecutiveFinalizeTimeouts = 0;
2340
+ if (preUnitSnapshot) {
2341
+ writeUnitRuntimeRecord(s.basePath, preUnitSnapshot.type, preUnitSnapshot.id, preUnitSnapshot.startedAt, {
2342
+ phase: "finalized",
2343
+ lastProgressAt: Date.now(),
2344
+ lastProgressKind: "finalize-success",
2345
+ });
2346
+ }
2254
2347
  s.currentUnit = null;
2255
2348
  clearCurrentPhase();
2256
2349