gsd-pi 2.78.1-dev.b0759e59b → 2.78.1-dev.d8826a445

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 (300) hide show
  1. package/README.md +8 -5
  2. package/dist/headless-recover.d.ts +23 -0
  3. package/dist/headless-recover.js +93 -0
  4. package/dist/headless.js +9 -0
  5. package/dist/help-text.js +1 -0
  6. package/dist/resources/.managed-resources-content-hash +1 -1
  7. package/dist/resources/extensions/browser-tools/tools/intent.js +8 -1
  8. package/dist/resources/extensions/gsd/auto/phases.js +7 -2
  9. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  10. package/dist/resources/extensions/gsd/auto-dispatch.js +7 -58
  11. package/dist/resources/extensions/gsd/auto-post-unit.js +14 -28
  12. package/dist/resources/extensions/gsd/auto-start.js +1 -8
  13. package/dist/resources/extensions/gsd/auto-worktree.js +244 -216
  14. package/dist/resources/extensions/gsd/auto.js +86 -7
  15. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +1 -1
  16. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -77
  17. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -16
  18. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -55
  19. package/dist/resources/extensions/gsd/commands-codebase.js +2 -2
  20. package/dist/resources/extensions/gsd/commands-handlers.js +5 -5
  21. package/dist/resources/extensions/gsd/commands-logs.js +2 -2
  22. package/dist/resources/extensions/gsd/commands-scan.js +2 -2
  23. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  24. package/dist/resources/extensions/gsd/commands-workflow-templates.js +5 -5
  25. package/dist/resources/extensions/gsd/db-writer.js +106 -95
  26. package/dist/resources/extensions/gsd/delegation-policy.js +155 -0
  27. package/dist/resources/extensions/gsd/dispatch-guard.js +6 -10
  28. package/dist/resources/extensions/gsd/doctor-engine-checks.js +2 -2
  29. package/dist/resources/extensions/gsd/gsd-db.js +268 -8
  30. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  31. package/dist/resources/extensions/gsd/guided-flow.js +141 -32
  32. package/dist/resources/extensions/gsd/markdown-renderer.js +14 -51
  33. package/dist/resources/extensions/gsd/metrics.js +287 -1
  34. package/dist/resources/extensions/gsd/parallel-merge.js +14 -13
  35. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +5 -2
  36. package/dist/resources/extensions/gsd/paths.js +114 -9
  37. package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  38. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -3
  39. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  40. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  41. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  42. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  43. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  44. package/dist/resources/extensions/gsd/queue-order.js +6 -1
  45. package/dist/resources/extensions/gsd/rethink.js +2 -2
  46. package/dist/resources/extensions/gsd/state.js +91 -372
  47. package/dist/resources/extensions/gsd/templates/project.md +10 -0
  48. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -5
  49. package/dist/resources/extensions/gsd/tools/complete-slice.js +7 -12
  50. package/dist/resources/extensions/gsd/tools/complete-task.js +19 -31
  51. package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -5
  52. package/dist/resources/extensions/gsd/workflow-manifest.js +2 -1
  53. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +3 -21
  54. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -2
  55. package/dist/resources/extensions/gsd/workflow-reconcile.js +3 -3
  56. package/dist/resources/extensions/gsd/workspace.js +59 -0
  57. package/dist/resources/extensions/gsd/worktree-command.js +4 -3
  58. package/dist/resources/extensions/gsd/worktree-resolver.js +15 -2
  59. package/dist/resources/extensions/gsd/write-intercept.js +3 -3
  60. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  61. package/dist/web/standalone/.next/BUILD_ID +1 -1
  62. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  63. package/dist/web/standalone/.next/build-manifest.json +2 -2
  64. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  65. package/dist/web/standalone/.next/required-server-files.json +1 -1
  66. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  67. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  68. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  69. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  70. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  71. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  72. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  73. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  74. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  75. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  76. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  77. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  78. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  79. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  80. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  81. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  82. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  83. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  84. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  85. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  86. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  87. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  88. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  89. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  90. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  91. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  92. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  93. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  94. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  95. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  96. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  97. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  98. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  99. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  100. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  101. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  102. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  103. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  104. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  105. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  106. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  107. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  108. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  109. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  110. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  111. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  112. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  113. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  114. package/dist/web/standalone/.next/server/app/index.html +1 -1
  115. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  122. package/dist/web/standalone/.next/server/chunks/6336.js +1 -0
  123. package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
  124. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  125. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  126. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  127. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  128. package/dist/web/standalone/server.js +1 -1
  129. package/package.json +1 -1
  130. package/packages/mcp-server/README.md +2 -11
  131. package/packages/mcp-server/dist/remote-questions.d.ts +27 -0
  132. package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -1
  133. package/packages/mcp-server/dist/remote-questions.js +28 -0
  134. package/packages/mcp-server/dist/remote-questions.js.map +1 -1
  135. package/packages/mcp-server/dist/server.d.ts +28 -0
  136. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  137. package/packages/mcp-server/dist/server.js +94 -4
  138. package/packages/mcp-server/dist/server.js.map +1 -1
  139. package/packages/mcp-server/dist/workflow-tools.d.ts +6 -0
  140. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  141. package/packages/mcp-server/dist/workflow-tools.js +56 -2
  142. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  143. package/packages/mcp-server/src/mcp-server.test.ts +226 -0
  144. package/packages/mcp-server/src/parse-workflow-args.test.ts +80 -0
  145. package/packages/mcp-server/src/remote-questions.test.ts +103 -0
  146. package/packages/mcp-server/src/remote-questions.ts +35 -0
  147. package/packages/mcp-server/src/server.ts +129 -6
  148. package/packages/mcp-server/src/workflow-tools.ts +62 -3
  149. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  150. package/src/resources/extensions/browser-tools/tools/intent.ts +13 -2
  151. package/src/resources/extensions/gsd/auto/phases.ts +8 -2
  152. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  153. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -62
  154. package/src/resources/extensions/gsd/auto-post-unit.ts +15 -27
  155. package/src/resources/extensions/gsd/auto-start.ts +1 -8
  156. package/src/resources/extensions/gsd/auto-worktree.ts +286 -251
  157. package/src/resources/extensions/gsd/auto.ts +102 -7
  158. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +1 -1
  159. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +9 -84
  160. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +17 -17
  161. package/src/resources/extensions/gsd/bootstrap/tests/write-gate-basepath.test.ts +103 -0
  162. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -55
  163. package/src/resources/extensions/gsd/commands-codebase.ts +2 -2
  164. package/src/resources/extensions/gsd/commands-handlers.ts +5 -5
  165. package/src/resources/extensions/gsd/commands-logs.ts +2 -2
  166. package/src/resources/extensions/gsd/commands-scan.ts +2 -2
  167. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  168. package/src/resources/extensions/gsd/commands-workflow-templates.ts +5 -5
  169. package/src/resources/extensions/gsd/db-writer.ts +123 -94
  170. package/src/resources/extensions/gsd/delegation-policy.ts +197 -0
  171. package/src/resources/extensions/gsd/dispatch-guard.ts +6 -11
  172. package/src/resources/extensions/gsd/doctor-engine-checks.ts +2 -2
  173. package/src/resources/extensions/gsd/gsd-db.ts +269 -8
  174. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  175. package/src/resources/extensions/gsd/guided-flow.ts +181 -32
  176. package/src/resources/extensions/gsd/markdown-renderer.ts +13 -64
  177. package/src/resources/extensions/gsd/metrics.ts +321 -1
  178. package/src/resources/extensions/gsd/parallel-merge.ts +14 -13
  179. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +5 -2
  180. package/src/resources/extensions/gsd/paths.ts +122 -9
  181. package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -4
  182. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -3
  183. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +8 -1
  184. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +22 -7
  185. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +6 -2
  186. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +8 -1
  187. package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -0
  188. package/src/resources/extensions/gsd/queue-order.ts +6 -1
  189. package/src/resources/extensions/gsd/rethink.ts +2 -2
  190. package/src/resources/extensions/gsd/state.ts +91 -389
  191. package/src/resources/extensions/gsd/templates/project.md +10 -0
  192. package/src/resources/extensions/gsd/tests/artifact-corruption-2630.test.ts +1 -0
  193. package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +14 -14
  194. package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +6 -0
  195. package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +21 -34
  196. package/src/resources/extensions/gsd/tests/auto-session-scope.test.ts +331 -0
  197. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +176 -0
  198. package/src/resources/extensions/gsd/tests/complete-task-rollback-evidence.test.ts +6 -7
  199. package/src/resources/extensions/gsd/tests/complete-task.test.ts +8 -6
  200. package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +12 -27
  201. package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +18 -5
  202. package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
  203. package/src/resources/extensions/gsd/tests/db-writer-path-containment.test.ts +152 -0
  204. package/src/resources/extensions/gsd/tests/db-writer-root-artifact.test.ts +221 -0
  205. package/src/resources/extensions/gsd/tests/db-writer-scope.test.ts +230 -0
  206. package/src/resources/extensions/gsd/tests/db-writer.test.ts +14 -16
  207. package/src/resources/extensions/gsd/tests/delegation-policy.test.ts +151 -0
  208. package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +6 -5
  209. package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +10 -38
  210. package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +136 -56
  211. package/src/resources/extensions/gsd/tests/derive-state-draft.test.ts +3 -0
  212. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +119 -61
  213. package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -0
  214. package/src/resources/extensions/gsd/tests/dispatch-backgroundable-annotation.test.ts +55 -0
  215. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +6 -20
  216. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +4 -5
  217. package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +14 -15
  218. package/src/resources/extensions/gsd/tests/draft-promotion.test.ts +3 -23
  219. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +11 -16
  220. package/src/resources/extensions/gsd/tests/escalation.test.ts +2 -1
  221. package/src/resources/extensions/gsd/tests/gate-1b-orphan-discrimination.test.ts +193 -0
  222. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound-corrections.test.ts +246 -0
  223. package/src/resources/extensions/gsd/tests/gate-1b-recovery-bound.test.ts +218 -0
  224. package/src/resources/extensions/gsd/tests/gsd-db-failed-open-restore.test.ts +117 -0
  225. package/src/resources/extensions/gsd/tests/gsd-db-workspace-scope.test.ts +226 -0
  226. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +2 -1
  227. package/src/resources/extensions/gsd/tests/gsd-root-canonical.test.ts +66 -0
  228. package/src/resources/extensions/gsd/tests/gsd-root-home-guard.test.ts +68 -5
  229. package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +15 -36
  230. package/src/resources/extensions/gsd/tests/guided-flow-prompt-consolidation.test.ts +4 -4
  231. package/src/resources/extensions/gsd/tests/handler-worktree-write-isolation.test.ts +57 -0
  232. package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +15 -15
  233. package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +15 -5
  234. package/src/resources/extensions/gsd/tests/integration/workspace-collapse-integration.test.ts +371 -0
  235. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +14 -8
  236. package/src/resources/extensions/gsd/tests/md-importer.test.ts +2 -1
  237. package/src/resources/extensions/gsd/tests/memory-store.test.ts +3 -2
  238. package/src/resources/extensions/gsd/tests/metrics-atomic-merge.test.ts +222 -0
  239. package/src/resources/extensions/gsd/tests/metrics-lock-hardening.test.ts +400 -0
  240. package/src/resources/extensions/gsd/tests/metrics-lock-not-acquired.test.ts +141 -0
  241. package/src/resources/extensions/gsd/tests/metrics-lock-retry-sleep.test.ts +287 -0
  242. package/src/resources/extensions/gsd/tests/metrics-prune-cache-invalidation.test.ts +149 -0
  243. package/src/resources/extensions/gsd/tests/metrics-scope.test.ts +378 -0
  244. package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +329 -0
  245. package/src/resources/extensions/gsd/tests/park-milestone.test.ts +2 -0
  246. package/src/resources/extensions/gsd/tests/path-cache-decoupled.test.ts +209 -0
  247. package/src/resources/extensions/gsd/tests/path-normalization-unified.test.ts +175 -0
  248. package/src/resources/extensions/gsd/tests/paths-cache.test.ts +170 -0
  249. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +120 -0
  250. package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +25 -16
  251. package/src/resources/extensions/gsd/tests/projection-regression.test.ts +1 -0
  252. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +150 -7
  253. package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +184 -0
  254. package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +6 -1
  255. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +28 -16
  256. package/src/resources/extensions/gsd/tests/replan-slice.test.ts +3 -0
  257. package/src/resources/extensions/gsd/tests/resolve-ts.mjs +4 -0
  258. package/src/resources/extensions/gsd/tests/resume-missing-worktree-warning.test.ts +209 -0
  259. package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +3 -4
  260. package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +10 -56
  261. package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +15 -16
  262. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
  263. package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +23 -27
  264. package/src/resources/extensions/gsd/tests/steer-worktree-path.test.ts +13 -14
  265. package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +4 -3
  266. package/src/resources/extensions/gsd/tests/sync-layer-scope.test.ts +453 -0
  267. package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +10 -33
  268. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +162 -0
  269. package/src/resources/extensions/gsd/tests/teardown-cleanup-parity.test.ts +102 -0
  270. package/src/resources/extensions/gsd/tests/teardown-failure-clears-registry.test.ts +186 -0
  271. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +1 -1
  272. package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +7 -8
  273. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -15
  274. package/src/resources/extensions/gsd/tests/validator-scope-parity.test.ts +239 -0
  275. package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +12 -7
  276. package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +4 -4
  277. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +26 -3
  278. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +9 -15
  279. package/src/resources/extensions/gsd/tests/workspace.test.ts +190 -0
  280. package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +13 -0
  281. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +65 -71
  282. package/src/resources/extensions/gsd/tests/worktree-sync-tasks.test.ts +26 -151
  283. package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +35 -35
  284. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -52
  285. package/src/resources/extensions/gsd/tests/write-intercept.test.ts +1 -1
  286. package/src/resources/extensions/gsd/tools/complete-milestone.ts +7 -5
  287. package/src/resources/extensions/gsd/tools/complete-slice.ts +7 -14
  288. package/src/resources/extensions/gsd/tools/complete-task.ts +19 -34
  289. package/src/resources/extensions/gsd/tools/validate-milestone.ts +7 -5
  290. package/src/resources/extensions/gsd/workflow-manifest.ts +4 -1
  291. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -18
  292. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -2
  293. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  294. package/src/resources/extensions/gsd/workspace.ts +95 -0
  295. package/src/resources/extensions/gsd/worktree-command.ts +4 -3
  296. package/src/resources/extensions/gsd/worktree-resolver.ts +16 -2
  297. package/src/resources/extensions/gsd/write-intercept.ts +3 -3
  298. package/dist/web/standalone/.next/server/chunks/8527.js +0 -1
  299. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_buildManifest.js +0 -0
  300. /package/dist/web/standalone/.next/static/{rk1EN3FQTE6Z1yalkW_GE → AT5qi39nKXkdmQIOIoh0f}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -310,7 +310,9 @@ This is what makes GSD different. Run it, walk away, come back to built software
310
310
  /gsd auto
311
311
  ```
312
312
 
313
- Auto mode is a state machine driven by files on disk. It reads `.gsd/STATE.md`, determines the next unit of work, creates a fresh agent session, injects a focused prompt with all relevant context pre-inlined, and lets the LLM execute. When the LLM finishes, auto mode reads disk state again and dispatches the next unit.
313
+ Auto mode is a state machine driven by the GSD database at the project root. It derives the next unit of work from authoritative SQLite state, creates a fresh agent session, injects a focused prompt with all relevant context pre-inlined, and lets the LLM execute. When the LLM finishes, auto mode persists the result to the database, refreshes markdown projections such as `STATE.md`, and dispatches the next unit.
314
+
315
+ The database is authoritative for milestones, slices, tasks, requirements, decisions, summaries, and completion status. Markdown under `.gsd/` is a rendered projection for review, prompts, and git-friendly history; it is not a runtime fallback unless you explicitly run a recovery/import command. In worktree mode, project-root DB state remains authoritative and worktree markdown projections are not synced back as state.
314
316
 
315
317
  **What happens under the hood:**
316
318
 
@@ -499,6 +501,7 @@ Every dispatch is carefully constructed. The LLM never wastes tool calls on orie
499
501
 
500
502
  | Artifact | Purpose |
501
503
  | ------------------ | --------------------------------------------------------------- |
504
+ | `gsd.db` | Authoritative runtime state for hierarchy and completion |
502
505
  | `PROJECT.md` | Living doc — what the project is right now |
503
506
  | `REQUIREMENTS.md` | Project-level capability contract and out-of-scope list |
504
507
  | `DECISIONS.md` | Append-only register of architectural decisions |
@@ -506,7 +509,7 @@ Every dispatch is carefully constructed. The LLM never wastes tool calls on orie
506
509
  | `RUNTIME.md` | Runtime context — API endpoints, env vars, services (v2.39) |
507
510
  | `runtime/research-decision.json` | Deep-mode marker for project research vs skip |
508
511
  | `research/*.md` | Optional deep-mode project research: stack, features, architecture, pitfalls |
509
- | `STATE.md` | Quick-glance dashboard always read first |
512
+ | `STATE.md` | Quick-glance dashboard rendered from the database |
510
513
  | `M001-ROADMAP.md` | Milestone plan with slice checkboxes, risk levels, dependencies |
511
514
  | `M001-CONTEXT.md` | User decisions from the discuss phase |
512
515
  | `M001-RESEARCH.md` | Codebase and ecosystem research |
@@ -708,7 +711,7 @@ The best practice for working in teams is to ensure unique milestone names acros
708
711
  .gsd/completed-units*.json
709
712
  # State manifest — workflow state for recovery
710
713
  .gsd/state-manifest.json
711
- # Derived state cache — regenerated from plan/roadmap files on disk
714
+ # Derived state projection — regenerated from the authoritative database
712
715
  .gsd/STATE.md
713
716
  # Per-developer token/cost accumulator
714
717
  .gsd/metrics.json
@@ -720,7 +723,7 @@ The best practice for working in teams is to ensure unique milestone names acros
720
723
  .gsd/worktrees/
721
724
  # Parallel orchestration IPC and worker status
722
725
  .gsd/parallel/
723
- # SQLite database and WAL sidecars — checkpoint state, forensics data
726
+ # SQLite database and WAL sidecars — authoritative runtime state, local only
724
727
  .gsd/gsd.db*
725
728
  # Daily-rotated event journal — structured event log for forensics
726
729
  .gsd/journal/
@@ -785,7 +788,7 @@ gsd (CLI binary)
785
788
  - **`pkg/` shim directory** — `PI_PACKAGE_DIR` points here (not project root) to avoid Pi's theme resolution collision with our `src/` directory. Contains only `piConfig` and theme assets.
786
789
  - **Two-file loader pattern** — `loader.ts` sets all env vars with zero SDK imports, then dynamic-imports `cli.ts` which does static SDK imports. This ensures `PI_PACKAGE_DIR` is set before any SDK code evaluates.
787
790
  - **Always-overwrite sync** — `npm update -g` takes effect immediately. Bundled extensions and agents are synced to `~/.gsd/agent/` on every launch, not just first run.
788
- - **State lives on disk** — `.gsd/` is the source of truth. Auto mode reads it, writes it, and advances based on what it finds. No in-memory state survives across sessions.
791
+ - **DB-authoritative state** — the project-root GSD database is the runtime source of truth. `.gsd/` markdown files are rendered projections for review, prompt context, and git history. No in-memory state survives across sessions.
789
792
 
790
793
  ---
791
794
 
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Headless Recover — `gsd headless recover`
3
+ *
4
+ * Non-interactive parallel of the `/gsd recover` slash command. Clears the
5
+ * milestones / slices / tasks tables and re-imports them from the on-disk
6
+ * markdown projections (ROADMAP.md, PLAN.md, SUMMARY.md, …) via
7
+ * migrateHierarchyToDb. Mutating: this is the one headless subcommand that
8
+ * writes to the DB. Required for CI / automation flows that need to
9
+ * reconcile DB state from markdown without launching an LLM session or a
10
+ * TTY-bound interactive runtime.
11
+ *
12
+ * Output: `gsd-recover: recovered <N>M/<N>S/<N>T hierarchy\n` to stderr on
13
+ * success — same marker emitted by handleRecover (commands-maintenance.ts)
14
+ * so callers can distinguish the success path from a silent no-op.
15
+ *
16
+ * Exit codes:
17
+ * 0 — recovery succeeded
18
+ * 1 — `.gsd/` missing, DB could not be opened, or migration threw
19
+ */
20
+ export interface RecoverResult {
21
+ exitCode: number;
22
+ }
23
+ export declare function handleRecover(basePath: string): Promise<RecoverResult>;
@@ -0,0 +1,93 @@
1
+ // gsd-pi — Headless Recover entrypoint
2
+ /**
3
+ * Headless Recover — `gsd headless recover`
4
+ *
5
+ * Non-interactive parallel of the `/gsd recover` slash command. Clears the
6
+ * milestones / slices / tasks tables and re-imports them from the on-disk
7
+ * markdown projections (ROADMAP.md, PLAN.md, SUMMARY.md, …) via
8
+ * migrateHierarchyToDb. Mutating: this is the one headless subcommand that
9
+ * writes to the DB. Required for CI / automation flows that need to
10
+ * reconcile DB state from markdown without launching an LLM session or a
11
+ * TTY-bound interactive runtime.
12
+ *
13
+ * Output: `gsd-recover: recovered <N>M/<N>S/<N>T hierarchy\n` to stderr on
14
+ * success — same marker emitted by handleRecover (commands-maintenance.ts)
15
+ * so callers can distinguish the success path from a silent no-op.
16
+ *
17
+ * Exit codes:
18
+ * 0 — recovery succeeded
19
+ * 1 — `.gsd/` missing, DB could not be opened, or migration threw
20
+ */
21
+ import { createJiti } from '@mariozechner/jiti';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { resolveGsdAgentExtensionsDir, shouldUseAgentExtensionsDir } from './headless-query.js';
24
+ import { resolveBundledGsdExtensionModule } from './bundled-resource-path.js';
25
+ import { join } from 'node:path';
26
+ import { existsSync } from 'node:fs';
27
+ const jiti = createJiti(fileURLToPath(import.meta.url), { interopDefault: true, debug: false });
28
+ const agentExtensionsDir = resolveGsdAgentExtensionsDir();
29
+ const { useAgentDir } = shouldUseAgentExtensionsDir({ env: process.env });
30
+ const gsdExtensionPath = (...segments) => useAgentDir
31
+ ? resolveAgentExtensionModule(agentExtensionsDir, segments)
32
+ : resolveBundledGsdExtensionModule(import.meta.url, segments.join('/'));
33
+ function resolveAgentExtensionModule(agentDir, segments) {
34
+ const requested = join(agentDir, ...segments);
35
+ if (existsSync(requested))
36
+ return requested;
37
+ if (segments.length === 1 && segments[0].endsWith('.ts')) {
38
+ const jsPath = join(agentDir, segments[0].replace(/\.ts$/, '.js'));
39
+ if (existsSync(jsPath))
40
+ return jsPath;
41
+ }
42
+ return requested;
43
+ }
44
+ async function loadExtensionModules() {
45
+ const stateModule = await jiti.import(gsdExtensionPath('state.ts'), {});
46
+ const dbModule = await jiti.import(gsdExtensionPath('gsd-db.ts'), {});
47
+ const importerModule = await jiti.import(gsdExtensionPath('md-importer.ts'), {});
48
+ const dynamicToolsModule = await jiti.import(gsdExtensionPath('bootstrap/dynamic-tools.ts'), {});
49
+ return {
50
+ ensureDbOpen: dynamicToolsModule.ensureDbOpen,
51
+ isDbAvailable: dbModule.isDbAvailable,
52
+ clearEngineHierarchy: dbModule.clearEngineHierarchy,
53
+ transaction: dbModule.transaction,
54
+ migrateHierarchyToDb: importerModule.migrateHierarchyToDb,
55
+ invalidateStateCache: stateModule.invalidateStateCache,
56
+ };
57
+ }
58
+ export async function handleRecover(basePath) {
59
+ const gsdDir = join(basePath, '.gsd');
60
+ if (!existsSync(gsdDir)) {
61
+ process.stderr.write(`[headless] recover: no .gsd/ directory at ${basePath}\n`);
62
+ return { exitCode: 1 };
63
+ }
64
+ let modules;
65
+ try {
66
+ modules = await loadExtensionModules();
67
+ }
68
+ catch (err) {
69
+ const msg = err instanceof Error ? err.message : String(err);
70
+ process.stderr.write(`[headless] recover: failed to load extension modules: ${msg}\n`);
71
+ return { exitCode: 1 };
72
+ }
73
+ const opened = await modules.ensureDbOpen(basePath);
74
+ if (!opened || !modules.isDbAvailable()) {
75
+ process.stderr.write(`[headless] recover: failed to open or create the GSD database at ${basePath}\n`);
76
+ return { exitCode: 1 };
77
+ }
78
+ let counts;
79
+ try {
80
+ counts = modules.transaction(() => {
81
+ modules.clearEngineHierarchy();
82
+ return modules.migrateHierarchyToDb(basePath);
83
+ });
84
+ }
85
+ catch (err) {
86
+ const msg = err instanceof Error ? err.message : String(err);
87
+ process.stderr.write(`[headless] recover failed: ${msg}\n`);
88
+ return { exitCode: 1 };
89
+ }
90
+ modules.invalidateStateCache();
91
+ process.stderr.write(`gsd-recover: recovered ${counts.milestones}M/${counts.slices}S/${counts.tasks}T hierarchy\n`);
92
+ return { exitCode: 0 };
93
+ }
package/dist/headless.js CHANGED
@@ -265,6 +265,15 @@ async function runHeadlessOnce(options, restartCount) {
265
265
  const result = await handleQuery(process.cwd());
266
266
  return { exitCode: result.exitCode, interrupted: false };
267
267
  }
268
+ // Recover: rebuild DB hierarchy from on-disk markdown projections, no RPC
269
+ // child needed. This is the one mutating headless subcommand — required for
270
+ // CI / automation that needs to reconcile DB state from markdown without
271
+ // launching an interactive TTY-bound runtime.
272
+ if (options.command === 'recover') {
273
+ const { handleRecover } = await import('./headless-recover.js');
274
+ const result = await handleRecover(process.cwd());
275
+ process.exit(result.exitCode);
276
+ }
268
277
  // Doctor: read-only health check, no RPC child needed (#4904 live-regression).
269
278
  // The interactive `/gsd doctor` command lives in the GSD extension; this CLI
270
279
  // path lets non-interactive callers (CI, recovery scripts, the live-regression
package/dist/help-text.js CHANGED
@@ -156,6 +156,7 @@ const SUBCOMMAND_HELP = {
156
156
  ' gsd headless --answers answers.json auto With pre-supplied answers',
157
157
  ' gsd headless --events agent_end,extension_ui_request auto Filtered event stream',
158
158
  ' gsd headless query Instant JSON state snapshot',
159
+ ' gsd headless recover Rebuild DB hierarchy from markdown (mutating)',
159
160
  '',
160
161
  'Exit codes: 0 = success, 1 = error/timeout, 10 = blocked, 11 = cancelled',
161
162
  ].join('\n'),
@@ -1 +1 @@
1
- 44db11fcd2543b94
1
+ 3cb2810818585c65
@@ -1,5 +1,4 @@
1
1
  import { Type } from "@sinclair/typebox";
2
- import { StringEnum } from "@gsd/pi-ai";
3
2
  import { diffCompactStates } from "../core.js";
4
3
  import { setLastActionBeforeState, setLastActionAfterState, } from "../state.js";
5
4
  // ---------------------------------------------------------------------------
@@ -15,6 +14,14 @@ const INTENTS = [
15
14
  "auth_action",
16
15
  "back_navigation",
17
16
  ];
17
+ function StringEnum(values, options) {
18
+ return Type.Unsafe({
19
+ type: "string",
20
+ enum: values,
21
+ ...(options?.description && { description: options.description }),
22
+ ...(options?.default && { default: options.default }),
23
+ });
24
+ }
18
25
  // ---------------------------------------------------------------------------
19
26
  // Scoring evaluate script — runs entirely in-browser via page.evaluate()
20
27
  // ---------------------------------------------------------------------------
@@ -12,7 +12,7 @@ import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from ".
12
12
  import { detectStuck } from "./detect-stuck.js";
13
13
  import { runUnit } from "./run-unit.js";
14
14
  import { debugLog } from "../debug-logger.js";
15
- import { resolveWorktreeProjectRoot } from "../worktree-root.js";
15
+ import { resolveWorktreeProjectRoot, normalizeWorktreePathForCompare } from "../worktree-root.js";
16
16
  import { PROJECT_FILES, hasProjectFileInAncestor } from "../detection.js";
17
17
  import { MergeConflictError } from "../git-service.js";
18
18
  import { setCurrentPhase, clearCurrentPhase } from "../../shared/gsd-phase-state.js";
@@ -37,6 +37,11 @@ import { parseUnitId } from "../unit-id.js";
37
37
  import { createCheckpoint, cleanupCheckpoint, rollbackToCheckpoint } from "../safety/git-checkpoint.js";
38
38
  import { resolveSafetyHarnessConfig } from "../safety/safety-harness.js";
39
39
  import { getWorkflowTransportSupportError, getRequiredWorkflowToolsForAutoUnit, supportsStructuredQuestions, } from "../workflow-mcp.js";
40
+ // ─── Path Comparison Helper ───────────────────────────────────────────────
41
+ /** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
42
+ function isSamePathLocal(a, b) {
43
+ return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
44
+ }
40
45
  // ─── Session timeout auto-resume state ────────────────────────────────────────
41
46
  let consecutiveSessionTimeouts = 0;
42
47
  const MAX_SESSION_TIMEOUT_AUTO_RESUMES = 3;
@@ -280,7 +285,7 @@ export async function runPreDispatch(ic, loopState) {
280
285
  }
281
286
  // Sync project root artifacts into worktree
282
287
  if (s.originalBasePath &&
283
- s.basePath !== s.originalBasePath &&
288
+ !isSamePathLocal(s.basePath, s.originalBasePath) &&
284
289
  s.currentMilestoneId) {
285
290
  deps.syncProjectRootToWorktree(s.originalBasePath, s.basePath, s.currentMilestoneId);
286
291
  }
@@ -32,6 +32,8 @@ export class AutoSession {
32
32
  // ── Paths ────────────────────────────────────────────────────────────────
33
33
  basePath = "";
34
34
  originalBasePath = "";
35
+ // TODO(C8): remove basePath/originalBasePath once all readers use s.scope
36
+ scope = null;
35
37
  previousProjectRootEnv = null;
36
38
  hadProjectRootEnv = false;
37
39
  projectRootEnvCaptured = false;
@@ -173,6 +175,7 @@ export class AutoSession {
173
175
  // Paths
174
176
  this.basePath = "";
175
177
  this.originalBasePath = "";
178
+ this.scope = null;
176
179
  this.previousProjectRootEnv = null;
177
180
  this.hadProjectRootEnv = false;
178
181
  this.projectRootEnvCaptured = false;
@@ -9,7 +9,7 @@
9
9
  * without modifying orchestration code.
10
10
  */
11
11
  import { loadFile, extractUatType, loadActiveOverrides } from "./files.js";
12
- import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted, getMilestone, updateMilestoneStatus } from "./gsd-db.js";
12
+ import { isDbAvailable, getMilestoneSlices, getPendingGates, markAllGatesOmitted, getMilestone } from "./gsd-db.js";
13
13
  import { isClosedStatus } from "./status-guards.js";
14
14
  import { extractVerdict, isAcceptableUatVerdict } from "./verdict-parser.js";
15
15
  import { gsdRoot, resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveTaskFile, relSliceFile, buildMilestoneFileName, } from "./paths.js";
@@ -19,7 +19,6 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "
19
19
  import { logWarning, logError } from "./workflow-logger.js";
20
20
  import { join } from "node:path";
21
21
  import { hasImplementationArtifacts } from "./auto-recovery.js";
22
- import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
23
22
  import { buildDiscussMilestonePrompt, buildDiscussProjectPrompt, buildDiscussRequirementsPrompt, buildResearchDecisionPrompt, buildResearchProjectPrompt, buildResearchMilestonePrompt, buildPlanMilestonePrompt, buildResearchSlicePrompt, buildPlanSlicePrompt, buildRefineSlicePrompt, buildExecuteTaskPrompt, buildCompleteSlicePrompt, buildCompleteMilestonePrompt, buildValidateMilestonePrompt, buildReplanSlicePrompt, buildRunUatPrompt, buildReassessRoadmapPrompt, buildRewriteDocsPrompt, buildReactiveExecutePrompt, buildGateEvaluatePrompt, buildParallelResearchSlicesPrompt, checkNeedsReassessment, checkNeedsRunUat, } from "./auto-prompts.js";
24
23
  import { resolveModelWithFallbacksForUnit } from "./preferences-models.js";
25
24
  import { resolveUokFlags } from "./uok/flags.js";
@@ -32,6 +31,7 @@ import { ensureWorkflowPreferencesCaptured } from "./planning-depth.js";
32
31
  import { MILESTONE_ID_RE } from "./milestone-ids.js";
33
32
  import { PROJECT_RESEARCH_INFLIGHT_MARKER, } from "./project-research-policy.js";
34
33
  import { isWorkflowPrefsCaptured, resolveDeepProjectSetupState, } from "./deep-project-setup-policy.js";
34
+ import { annotateBackgroundable } from "./delegation-policy.js";
35
35
  let reassessmentChecker = checkNeedsReassessment;
36
36
  let researchProjectPromptBuilder = buildResearchProjectPrompt;
37
37
  function shouldBypassMilestoneDepthGateInAuto(prefs) {
@@ -720,13 +720,9 @@ export const DISPATCH_RULES = [
720
720
  // while a slice is still `is_sketch=1`, fall through to a standard
721
721
  // plan-slice so the loop doesn't dead-end.
722
722
  //
723
- // Note on the flag-OFF downgrade: plan-slice does not explicitly clear
724
- // `is_sketch`. After it writes PLAN.md, the auto-heal in state.ts's
725
- // `deriveStateFromDb` (via `autoHealSketchFlags`) flips the flag on the
726
- // next iteration. That implicit coupling is the sole mechanism that
727
- // reconciles `is_sketch=1` on the plan-slice path — do not remove the
728
- // auto-heal without either adding an explicit `setSliceSketchFlag(..., false)`
729
- // call here or doing so inside the plan-slice tool handler.
723
+ // Note on the flag-OFF downgrade: DB slice metadata is authoritative.
724
+ // PLAN.md is only a projection, so plan-slice/refine-slice handlers must
725
+ // explicitly clear `is_sketch` when a sketch becomes a full plan.
730
726
  name: "refining → refine-slice",
731
727
  match: async ({ state, mid, midTitle, basePath, prefs, sessionContextWindow, modelRegistry, sessionProvider }) => {
732
728
  if (state.phase !== "refining")
@@ -1037,14 +1033,6 @@ export const DISPATCH_RULES = [
1037
1033
  return { action: "skip" };
1038
1034
  }
1039
1035
  }
1040
- const existingSummary = resolveMilestoneFile(basePath, mid, "SUMMARY");
1041
- let summaryOutcome = "unknown";
1042
- if (existingSummary) {
1043
- const summaryContent = await loadFile(existingSummary);
1044
- if (summaryContent) {
1045
- summaryOutcome = classifyMilestoneSummaryContent(summaryContent);
1046
- }
1047
- }
1048
1036
  // Safety guard (#2675): block completion when VALIDATION verdict is
1049
1037
  // needs-remediation. The state machine treats needs-remediation as
1050
1038
  // terminal (to prevent validate-milestone loops per #832), but
@@ -1121,45 +1109,6 @@ export const DISPATCH_RULES = [
1121
1109
  catch (err) { /* fall through — don't block on DB errors */
1122
1110
  logWarning("dispatch", `verification class check failed: ${err instanceof Error ? err.message : String(err)}`);
1123
1111
  }
1124
- // Disk/DB mismatch handling (#4658): SUMMARY presence alone is not enough.
1125
- // Apply post-gate policy:
1126
- // - success summary: reconcile DB and skip re-dispatch
1127
- // - failure summary: pause/fail-closed
1128
- // - unknown summary: pause/fail-closed
1129
- if (existingSummary) {
1130
- const milestone = isDbAvailable() ? getMilestone(mid) : null;
1131
- const status = milestone?.status ?? (isDbAvailable() ? "missing" : "unavailable");
1132
- if (summaryOutcome === "success") {
1133
- if (!isDbAvailable()) {
1134
- logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB is unavailable — skipping duplicate complete-milestone dispatch`);
1135
- return { action: "skip" };
1136
- }
1137
- try {
1138
- updateMilestoneStatus(mid, "complete", new Date().toISOString());
1139
- logWarning("dispatch", `Milestone ${mid} SUMMARY indicates completion while DB status was "${status}" — reconciled DB to complete (#4658)`);
1140
- return { action: "skip" };
1141
- }
1142
- catch (err) {
1143
- return {
1144
- action: "stop",
1145
- level: "warning",
1146
- reason: `Milestone ${mid} SUMMARY indicates completion but DB reconciliation failed (${err instanceof Error ? err.message : String(err)}). Auto-mode paused for manual review.`,
1147
- };
1148
- }
1149
- }
1150
- if (summaryOutcome === "failure") {
1151
- return {
1152
- action: "stop",
1153
- level: "warning",
1154
- reason: `Milestone ${mid} has a failure-path SUMMARY while DB status is "${status}". Auto-mode will not promote completion from failure artifacts. Re-run complete-milestone only after blockers are resolved and verification passes.`,
1155
- };
1156
- }
1157
- return {
1158
- action: "stop",
1159
- level: "warning",
1160
- reason: `Milestone ${mid} has an ambiguous SUMMARY while DB status is "${status}". Auto-mode paused instead of promoting completion from file presence alone.`,
1161
- };
1162
- }
1163
1112
  return {
1164
1113
  action: "dispatch",
1165
1114
  unitType: "complete-milestone",
@@ -1204,7 +1153,7 @@ export async function resolveDispatch(ctx) {
1204
1153
  // Delegate to registry when available
1205
1154
  try {
1206
1155
  const registry = getRegistry();
1207
- return await registry.evaluateDispatch(ctx);
1156
+ return annotateBackgroundable(await registry.evaluateDispatch(ctx));
1208
1157
  }
1209
1158
  catch (err) {
1210
1159
  // Registry not initialized — fall back to inline loop
@@ -1215,7 +1164,7 @@ export async function resolveDispatch(ctx) {
1215
1164
  if (result) {
1216
1165
  if (result.action !== "skip")
1217
1166
  result.matchedRule = rule.name;
1218
- return result;
1167
+ return annotateBackgroundable(result);
1219
1168
  }
1220
1169
  }
1221
1170
  // No rule matched — unhandled phase.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Post-unit processing for auto-loop — auto-commit, doctor run,
3
- * state rebuild, worktree sync, DB dual-write, hooks, triage, and
3
+ * state rebuild, projection checks, DB tool closeout, hooks, triage, and
4
4
  * quick-task dispatch.
5
5
  *
6
6
  * Split into two functions called sequentially by auto-loop with
@@ -24,7 +24,8 @@ import { runTurnGitAction, } from "./git-service.js";
24
24
  import { verifyExpectedArtifact, resolveExpectedArtifactPath, writeBlockerPlaceholder, diagnoseExpectedArtifact, } from "./auto-recovery.js";
25
25
  import { regenerateIfMissing } from "./workflow-projections.js";
26
26
  import { syncStateToProjectRoot } from "./auto-worktree.js";
27
- import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, updateSliceStatus, _getAdapter } from "./gsd-db.js";
27
+ import { normalizeWorktreePathForCompare } from "./worktree-root.js";
28
+ import { isDbAvailable, getTask, getSlice, getMilestone, updateTaskStatus, _getAdapter } from "./gsd-db.js";
28
29
  import { renderPlanCheckboxes } from "./markdown-renderer.js";
29
30
  import { consumeSignal } from "./session-status-io.js";
30
31
  import { checkPostUnitHooks, isRetryPending, consumeRetryTrigger, persistHookState, resolveHookArtifactPath, } from "./post-unit-hooks.js";
@@ -51,6 +52,11 @@ import { detectAbandonMilestone } from "./abandon-detect.js";
51
52
  import { isDeterministicPolicyError } from "./auto-tool-tracking.js";
52
53
  import { clearProjectResearchInflightMarker, finalizeProjectResearchTimeout, } from "./project-research-policy.js";
53
54
  import { validateArtifact } from "./schemas/validate.js";
55
+ // ─── Path Comparison Helper ───────────────────────────────────────────────
56
+ /** Compare two paths for physical identity, tolerating trailing slashes and symlinks. */
57
+ function isSamePathLocal(a, b) {
58
+ return normalizeWorktreePathForCompare(a) === normalizeWorktreePathForCompare(b);
59
+ }
54
60
  /** Maximum verification retry attempts before escalating to blocker placeholder (#2653). */
55
61
  const MAX_VERIFICATION_RETRIES = 3;
56
62
  /** Keep failure toasts short while still showing concrete examples. */
@@ -109,9 +115,8 @@ import { autoCommitCurrentBranch } from "./worktree.js";
109
115
  * the completion tool. A "rogue" file is one that exists on disk but has
110
116
  * no corresponding DB row with status "complete".
111
117
  *
112
- * This is a safety-net diagnostic (D003). The existing migrateFromMarkdown()
113
- * in postUnitPostVerification() eventually ingests rogue files, but explicit
114
- * detection provides immediate diagnostics so operators know the prompt failed.
118
+ * This is a safety-net diagnostic (D003). Runtime detection never imports
119
+ * markdown into the DB; explicit migration/import/recovery commands own that.
115
120
  */
116
121
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
122
  function hasNonEmptyFields(row, fields) {
@@ -145,15 +150,7 @@ export function detectRogueFileWrites(unitType, unitId, basePath) {
145
150
  return [];
146
151
  const dbRow = getSlice(mid, sid);
147
152
  if (!dbRow || dbRow.status !== "complete") {
148
- // Auto-remediate: SUMMARY exists on disk but DB is stale — sync DB to
149
- // match filesystem instead of reporting as rogue (#3633).
150
- try {
151
- updateSliceStatus(mid, sid, "complete", new Date().toISOString());
152
- }
153
- catch {
154
- // If DB update fails, fall back to rogue detection so the issue is visible
155
- rogues.push({ path: summaryPath, unitType, unitId });
156
- }
153
+ rogues.push({ path: summaryPath, unitType, unitId });
157
154
  }
158
155
  }
159
156
  else if (unitType === "plan-milestone") {
@@ -519,7 +516,7 @@ export async function postUnitPreVerification(pctx, opts) {
519
516
  await rebuildState(s.basePath);
520
517
  });
521
518
  // Sync worktree state back to project root (skipped for lightweight sidecars)
522
- if (!opts?.skipWorktreeSync && s.originalBasePath && s.originalBasePath !== s.basePath) {
519
+ if (!opts?.skipWorktreeSync && s.originalBasePath && !isSamePathLocal(s.originalBasePath, s.basePath)) {
523
520
  await runSafely("postUnit", "worktree-sync", () => {
524
521
  syncStateToProjectRoot(s.basePath, s.originalBasePath, s.currentMilestoneId);
525
522
  });
@@ -628,7 +625,7 @@ export async function postUnitPreVerification(pctx, opts) {
628
625
  ctx.ui.notify(`slice-cadence merge conflict in ${sid}: ${err.conflictedFiles.join(", ")}. ` +
629
626
  `Resolve manually on main and run \`/gsd auto\` to resume.`, "error");
630
627
  // Stop auto AND signal the outer postUnit flow to exit early.
631
- // Without the flag, subsequent hooks (triage, rogue detection,
628
+ // Without the flag, subsequent hooks (triage,
632
629
  // DB writes) would keep running against a conflicted main
633
630
  // checkout after the loop was already told to stop.
634
631
  const { stopAuto } = await import("./auto.js");
@@ -648,7 +645,7 @@ export async function postUnitPreVerification(pctx, opts) {
648
645
  }
649
646
  });
650
647
  // Exit early after stopAuto so the rest of post-unit processing
651
- // (triage, rogue detection, hook dispatch, DB writes) doesn't run
648
+ // (triage, hook dispatch, DB writes) doesn't run
652
649
  // against a conflicted main checkout. Return "dispatched" to match
653
650
  // the convention used by other stop/pauseAuto paths in this function
654
651
  // (see signal handling earlier: stop/pause also return "dispatched").
@@ -689,17 +686,6 @@ export async function postUnitPreVerification(pctx, opts) {
689
686
  logError("engine", "triage resolution failed", { error: err.message });
690
687
  }
691
688
  }
692
- // Rogue file detection — safety net for LLM bypassing completion tools (D003)
693
- try {
694
- const rogueFiles = detectRogueFileWrites(s.currentUnit.type, s.currentUnit.id, s.basePath);
695
- for (const rogue of rogueFiles) {
696
- logWarning("engine", "rogue file write detected", { path: rogue.path, unitId: rogue.unitId });
697
- ctx.ui.notify(`Rogue file write detected: ${rogue.path}`, "warning");
698
- }
699
- }
700
- catch (e) {
701
- debugLog("postUnit", { phase: "rogue-detection", error: String(e) });
702
- }
703
689
  // ── Safety harness: post-unit validation ──
704
690
  try {
705
691
  const { loadEffectiveGSDPreferences } = await import("./preferences.js");
@@ -649,19 +649,12 @@ export async function bootstrapAutoSession(s, ctx, pi, base, verboseMode, reques
649
649
  const gsdDbPath = resolveProjectRootDbPath(s.basePath);
650
650
  const gsdDirPath = join(s.basePath, ".gsd");
651
651
  if (existsSync(gsdDirPath) && !existsSync(gsdDbPath)) {
652
- const hasDecisions = existsSync(join(gsdDirPath, "DECISIONS.md"));
653
- const hasRequirements = existsSync(join(gsdDirPath, "REQUIREMENTS.md"));
654
- const hasMilestones = existsSync(join(gsdDirPath, "milestones"));
655
652
  try {
656
653
  const { openDatabase: openDb } = await import("./gsd-db.js");
657
654
  openDb(gsdDbPath);
658
- if (hasDecisions || hasRequirements || hasMilestones) {
659
- const { migrateFromMarkdown } = await import("./md-importer.js");
660
- migrateFromMarkdown(s.basePath);
661
- }
662
655
  }
663
656
  catch (err) {
664
- logError("engine", `auto-migration failed: ${err.message}`);
657
+ logError("engine", `failed to initialize project database: ${err.message}`);
665
658
  }
666
659
  }
667
660
  if (existsSync(gsdDbPath) && !isDbAvailable()) {