gsd-pi 2.81.0-dev.72a81bdf3 → 2.82.0-dev.20138ae42

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 (463) hide show
  1. package/README.md +50 -31
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/GSD-WORKFLOW.md +10 -1
  4. package/dist/resources/extensions/browser-tools/tools/screenshot.js +1 -0
  5. package/dist/resources/extensions/browser-tools/tools/zoom.js +1 -0
  6. package/dist/resources/extensions/claude-code-cli/partial-builder.js +2 -1
  7. package/dist/resources/extensions/cmux/index.js +5 -0
  8. package/dist/resources/extensions/gsd/auto/infra-errors.js +9 -3
  9. package/dist/resources/extensions/gsd/auto/loop.js +5 -5
  10. package/dist/resources/extensions/gsd/auto/orchestrator.js +124 -6
  11. package/dist/resources/extensions/gsd/auto/phases.js +30 -1
  12. package/dist/resources/extensions/gsd/auto/workflow-memory-pressure.js +12 -0
  13. package/dist/resources/extensions/gsd/auto-dashboard.js +66 -1
  14. package/dist/resources/extensions/gsd/auto-dispatch.js +13 -6
  15. package/dist/resources/extensions/gsd/auto-model-selection.js +2 -0
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +233 -127
  17. package/dist/resources/extensions/gsd/auto-prompts.js +13 -5
  18. package/dist/resources/extensions/gsd/auto-recovery.js +31 -1
  19. package/dist/resources/extensions/gsd/auto-start.js +85 -12
  20. package/dist/resources/extensions/gsd/auto-verification.js +28 -22
  21. package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
  22. package/dist/resources/extensions/gsd/auto.js +158 -55
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +25 -6
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +9 -8
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +9 -2
  26. package/dist/resources/extensions/gsd/bootstrap/subagent-input.js +21 -9
  27. package/dist/resources/extensions/gsd/bootstrap/system-context.js +55 -12
  28. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +16 -2
  29. package/dist/resources/extensions/gsd/clean-root-preflight.js +170 -8
  30. package/dist/resources/extensions/gsd/commands/catalog.js +4 -1
  31. package/dist/resources/extensions/gsd/commands/handlers/core.js +38 -1
  32. package/dist/resources/extensions/gsd/commands-bootstrap.js +5 -0
  33. package/dist/resources/extensions/gsd/commands-handlers.js +15 -2
  34. package/dist/resources/extensions/gsd/context-store.js +112 -0
  35. package/dist/resources/extensions/gsd/crash-recovery.js +31 -5
  36. package/dist/resources/extensions/gsd/db/unit-dispatches.js +3 -2
  37. package/dist/resources/extensions/gsd/db-writer.js +150 -84
  38. package/dist/resources/extensions/gsd/dispatch-guard.js +2 -2
  39. package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  40. package/dist/resources/extensions/gsd/doctor-git-checks.js +41 -6
  41. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +28 -11
  42. package/dist/resources/extensions/gsd/doctor.js +2 -28
  43. package/dist/resources/extensions/gsd/export-html.js +27 -425
  44. package/dist/resources/extensions/gsd/git-service.js +39 -1
  45. package/dist/resources/extensions/gsd/gsd-db.js +1 -0
  46. package/dist/resources/extensions/gsd/guided-flow.js +93 -111
  47. package/dist/resources/extensions/gsd/guided-unit-context.js +23 -0
  48. package/dist/resources/extensions/gsd/knowledge-backfill.js +144 -0
  49. package/dist/resources/extensions/gsd/knowledge-capture.js +136 -0
  50. package/dist/resources/extensions/gsd/knowledge-parser.js +154 -0
  51. package/dist/resources/extensions/gsd/knowledge-projection.js +210 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +6 -1
  53. package/dist/resources/extensions/gsd/md-importer.js +1 -1
  54. package/dist/resources/extensions/gsd/memory-backfill.js +73 -17
  55. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +222 -0
  56. package/dist/resources/extensions/gsd/migrate/command.js +5 -0
  57. package/dist/resources/extensions/gsd/migrate/parsers.js +10 -0
  58. package/dist/resources/extensions/gsd/migrate/preview.js +9 -0
  59. package/dist/resources/extensions/gsd/migrate/transformer.js +51 -4
  60. package/dist/resources/extensions/gsd/migrate/writer.js +11 -1
  61. package/dist/resources/extensions/gsd/migration-auto-check.js +12 -17
  62. package/dist/resources/extensions/gsd/milestone-actions.js +11 -4
  63. package/dist/resources/extensions/gsd/native-git-bridge.js +48 -12
  64. package/dist/resources/extensions/gsd/pending-auto-start.js +52 -0
  65. package/dist/resources/extensions/gsd/post-execution-checks.js +73 -2
  66. package/dist/resources/extensions/gsd/pre-execution-checks.js +28 -1
  67. package/dist/resources/extensions/gsd/prompt-loader.js +1 -1
  68. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  69. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  71. package/dist/resources/extensions/gsd/prompts/discuss.md +9 -9
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  73. package/dist/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  75. package/dist/resources/extensions/gsd/prompts/queue.md +4 -4
  76. package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  77. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  78. package/dist/resources/extensions/gsd/prompts/system.md +2 -2
  79. package/dist/resources/extensions/gsd/provider-switch-observer.js +146 -0
  80. package/dist/resources/extensions/gsd/smart-entry-routing.js +36 -0
  81. package/dist/resources/extensions/gsd/state-reconciliation/drift/merge-state.js +6 -1
  82. package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +9 -14
  83. package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +19 -24
  84. package/dist/resources/extensions/gsd/status-guards.js +4 -0
  85. package/dist/resources/extensions/gsd/templates/knowledge.md +2 -2
  86. package/dist/resources/extensions/gsd/templates/plan.md +8 -5
  87. package/dist/resources/extensions/gsd/templates/task-plan.md +4 -2
  88. package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -8
  89. package/dist/resources/extensions/gsd/tools/complete-slice.js +6 -8
  90. package/dist/resources/extensions/gsd/tools/plan-milestone.js +7 -1
  91. package/dist/resources/extensions/gsd/tools/plan-slice.js +89 -14
  92. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +119 -0
  93. package/dist/resources/extensions/gsd/unit-context-manifest.js +32 -10
  94. package/dist/resources/extensions/gsd/validation.js +23 -1
  95. package/dist/resources/extensions/gsd/verification-gate.js +68 -7
  96. package/dist/resources/extensions/gsd/verification-verdict.js +26 -0
  97. package/dist/resources/extensions/gsd/workflow-projections.js +6 -8
  98. package/dist/resources/extensions/gsd/worktree-lifecycle.js +54 -10
  99. package/dist/resources/extensions/shared/html-shell.js +388 -0
  100. package/dist/resources/extensions/subagent/index.js +448 -78
  101. package/dist/resources/extensions/subagent/launch.js +77 -0
  102. package/dist/resources/extensions/subagent/run-store.js +148 -0
  103. package/dist/resources/extensions/visual-brief/artifact-policy.js +29 -0
  104. package/dist/resources/extensions/visual-brief/extension-manifest.json +8 -0
  105. package/dist/resources/extensions/visual-brief/index.js +5 -0
  106. package/dist/resources/extensions/visual-brief/page-contract.js +124 -0
  107. package/dist/resources/extensions/visual-brief/prompts.js +140 -0
  108. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  109. package/dist/web/standalone/.next/BUILD_ID +1 -1
  110. package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
  111. package/dist/web/standalone/.next/build-manifest.json +3 -3
  112. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  113. package/dist/web/standalone/.next/react-loadable-manifest.json +3 -3
  114. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  115. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  116. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  124. package/dist/web/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -7
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -7
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -5
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -5
  134. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  135. package/dist/web/standalone/.next/server/app/index.html +1 -1
  136. package/dist/web/standalone/.next/server/app/index.rsc +4 -7
  137. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -7
  139. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -5
  141. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -5
  142. package/dist/web/standalone/.next/server/app/page.js +2 -2
  143. package/dist/web/standalone/.next/server/app/page.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
  146. package/dist/web/standalone/.next/server/chunks/4266.js +2 -0
  147. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  148. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  150. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  151. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  152. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  153. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  154. package/dist/web/standalone/.next/static/chunks/2973.33f26573894b6153.js +2 -0
  155. package/dist/web/standalone/.next/static/chunks/{8359.e059d86b255fce1c.js → 8359.7eb3bb8f8ecf4c01.js} +2 -2
  156. package/dist/web/standalone/.next/static/chunks/app/layout-8c10ec293ae0f1d5.js +1 -0
  157. package/dist/web/standalone/.next/static/chunks/{webpack-de742b64187e13fe.js → webpack-9a4db269f9ed63ad.js} +1 -1
  158. package/dist/web/standalone/.next/static/css/746ee28c929d1880.css +1 -0
  159. package/package.json +6 -5
  160. package/packages/contracts/dist/rpc.test.js +7 -0
  161. package/packages/contracts/dist/rpc.test.js.map +1 -1
  162. package/packages/contracts/dist/workflow.d.ts +21 -0
  163. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  164. package/packages/contracts/dist/workflow.js +24 -0
  165. package/packages/contracts/dist/workflow.js.map +1 -1
  166. package/packages/contracts/src/rpc.test.ts +8 -0
  167. package/packages/contracts/src/workflow.ts +24 -0
  168. package/packages/daemon/package.json +2 -2
  169. package/packages/mcp-server/README.md +14 -3
  170. package/packages/mcp-server/dist/workflow-tools.d.ts +0 -3
  171. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  172. package/packages/mcp-server/dist/workflow-tools.js +80 -0
  173. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  174. package/packages/mcp-server/package.json +2 -2
  175. package/packages/mcp-server/src/workflow-tools-parity.test.ts +244 -0
  176. package/packages/mcp-server/src/workflow-tools.test.ts +23 -1
  177. package/packages/mcp-server/src/workflow-tools.ts +168 -0
  178. package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
  179. package/packages/native/package.json +1 -1
  180. package/packages/native/tsconfig.json +2 -1
  181. package/packages/native/tsconfig.tsbuildinfo +1 -1
  182. package/packages/pi-agent-core/package.json +1 -1
  183. package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
  184. package/packages/pi-ai/dist/index.d.ts +2 -2
  185. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  186. package/packages/pi-ai/dist/index.js +1 -1
  187. package/packages/pi-ai/dist/index.js.map +1 -1
  188. package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  189. package/packages/pi-ai/dist/providers/openai-codex-responses.js +82 -1
  190. package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  191. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts +2 -0
  192. package/packages/pi-ai/dist/providers/openai-codex-responses.test.d.ts.map +1 -0
  193. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js +52 -0
  194. package/packages/pi-ai/dist/providers/openai-codex-responses.test.js.map +1 -0
  195. package/packages/pi-ai/dist/providers/simple-options.d.ts +2 -4
  196. package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  197. package/packages/pi-ai/dist/providers/simple-options.js +5 -6
  198. package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
  199. package/packages/pi-ai/dist/providers/simple-options.test.d.ts +2 -0
  200. package/packages/pi-ai/dist/providers/simple-options.test.d.ts.map +1 -0
  201. package/packages/pi-ai/dist/providers/simple-options.test.js +50 -0
  202. package/packages/pi-ai/dist/providers/simple-options.test.js.map +1 -0
  203. package/packages/pi-ai/dist/providers/transform-messages.d.ts +11 -0
  204. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  205. package/packages/pi-ai/dist/providers/transform-messages.js +20 -0
  206. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  207. package/packages/pi-ai/package.json +1 -1
  208. package/packages/pi-ai/src/index.ts +7 -2
  209. package/packages/pi-ai/src/providers/openai-codex-responses.test.ts +63 -0
  210. package/packages/pi-ai/src/providers/openai-codex-responses.ts +91 -1
  211. package/packages/pi-ai/src/providers/simple-options.test.ts +60 -0
  212. package/packages/pi-ai/src/providers/simple-options.ts +5 -6
  213. package/packages/pi-ai/src/providers/transform-messages.ts +24 -0
  214. package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
  215. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts +2 -0
  216. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.d.ts.map +1 -0
  217. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js +66 -0
  218. package/packages/pi-coding-agent/dist/core/agent-session-thinking-level.test.js.map +1 -0
  219. package/packages/pi-coding-agent/dist/core/agent-session.js +1 -1
  220. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  221. package/packages/pi-coding-agent/dist/core/system-prompt.js +4 -4
  222. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  223. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  224. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +24 -6
  225. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  226. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts +2 -0
  227. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.d.ts.map +1 -0
  228. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js +17 -0
  229. package/packages/pi-coding-agent/dist/tests/system-prompt-file-safety.test.js.map +1 -0
  230. package/packages/pi-coding-agent/package.json +1 -1
  231. package/packages/pi-coding-agent/src/core/agent-session-thinking-level.test.ts +79 -0
  232. package/packages/pi-coding-agent/src/core/agent-session.ts +1 -1
  233. package/packages/pi-coding-agent/src/core/system-prompt.ts +4 -4
  234. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +23 -7
  235. package/packages/pi-coding-agent/src/tests/system-prompt-file-safety.test.ts +22 -0
  236. package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
  237. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  238. package/packages/pi-tui/dist/tui.js +5 -0
  239. package/packages/pi-tui/dist/tui.js.map +1 -1
  240. package/packages/pi-tui/package.json +1 -1
  241. package/packages/pi-tui/src/tui.ts +6 -0
  242. package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
  243. package/packages/rpc-client/package.json +1 -1
  244. package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
  245. package/pkg/package.json +1 -1
  246. package/src/resources/GSD-WORKFLOW.md +10 -1
  247. package/src/resources/extensions/browser-tools/tools/screenshot.ts +1 -0
  248. package/src/resources/extensions/browser-tools/tools/zoom.ts +1 -0
  249. package/src/resources/extensions/claude-code-cli/partial-builder.ts +2 -1
  250. package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +19 -2
  251. package/src/resources/extensions/cmux/index.ts +6 -0
  252. package/src/resources/extensions/gsd/auto/contracts.ts +59 -16
  253. package/src/resources/extensions/gsd/auto/infra-errors.ts +9 -3
  254. package/src/resources/extensions/gsd/auto/loop.ts +8 -5
  255. package/src/resources/extensions/gsd/auto/orchestrator.ts +129 -6
  256. package/src/resources/extensions/gsd/auto/phases.ts +36 -1
  257. package/src/resources/extensions/gsd/auto/workflow-memory-pressure.ts +13 -0
  258. package/src/resources/extensions/gsd/auto-dashboard.ts +72 -1
  259. package/src/resources/extensions/gsd/auto-dispatch.ts +14 -6
  260. package/src/resources/extensions/gsd/auto-model-selection.ts +2 -1
  261. package/src/resources/extensions/gsd/auto-post-unit.ts +266 -139
  262. package/src/resources/extensions/gsd/auto-prompts.ts +13 -5
  263. package/src/resources/extensions/gsd/auto-recovery.ts +29 -0
  264. package/src/resources/extensions/gsd/auto-start.ts +92 -9
  265. package/src/resources/extensions/gsd/auto-verification.ts +36 -34
  266. package/src/resources/extensions/gsd/auto-worktree.ts +119 -1
  267. package/src/resources/extensions/gsd/auto.ts +167 -53
  268. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +33 -6
  269. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +9 -8
  270. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +10 -2
  271. package/src/resources/extensions/gsd/bootstrap/subagent-input.ts +19 -7
  272. package/src/resources/extensions/gsd/bootstrap/system-context.ts +58 -15
  273. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +19 -3
  274. package/src/resources/extensions/gsd/clean-root-preflight.ts +174 -8
  275. package/src/resources/extensions/gsd/commands/catalog.ts +4 -1
  276. package/src/resources/extensions/gsd/commands/handlers/core.ts +41 -1
  277. package/src/resources/extensions/gsd/commands-bootstrap.ts +10 -0
  278. package/src/resources/extensions/gsd/commands-handlers.ts +19 -2
  279. package/src/resources/extensions/gsd/context-store.ts +120 -1
  280. package/src/resources/extensions/gsd/crash-recovery.ts +30 -4
  281. package/src/resources/extensions/gsd/db/unit-dispatches.ts +4 -3
  282. package/src/resources/extensions/gsd/db-writer.ts +167 -84
  283. package/src/resources/extensions/gsd/dispatch-guard.ts +2 -2
  284. package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
  285. package/src/resources/extensions/gsd/doctor-git-checks.ts +44 -6
  286. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +25 -13
  287. package/src/resources/extensions/gsd/doctor-types.ts +2 -0
  288. package/src/resources/extensions/gsd/doctor.ts +2 -27
  289. package/src/resources/extensions/gsd/export-html.ts +27 -427
  290. package/src/resources/extensions/gsd/git-service.ts +45 -1
  291. package/src/resources/extensions/gsd/gsd-db.ts +3 -0
  292. package/src/resources/extensions/gsd/guided-flow.ts +126 -128
  293. package/src/resources/extensions/gsd/guided-unit-context.ts +30 -0
  294. package/src/resources/extensions/gsd/knowledge-backfill.ts +164 -0
  295. package/src/resources/extensions/gsd/knowledge-capture.ts +160 -0
  296. package/src/resources/extensions/gsd/knowledge-parser.ts +174 -0
  297. package/src/resources/extensions/gsd/knowledge-projection.ts +241 -0
  298. package/src/resources/extensions/gsd/markdown-renderer.ts +6 -1
  299. package/src/resources/extensions/gsd/md-importer.ts +1 -1
  300. package/src/resources/extensions/gsd/memory-backfill.ts +89 -17
  301. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +277 -0
  302. package/src/resources/extensions/gsd/migrate/command.ts +5 -0
  303. package/src/resources/extensions/gsd/migrate/parsers.ts +11 -0
  304. package/src/resources/extensions/gsd/migrate/preview.ts +10 -0
  305. package/src/resources/extensions/gsd/migrate/transformer.ts +58 -4
  306. package/src/resources/extensions/gsd/migrate/writer.ts +14 -1
  307. package/src/resources/extensions/gsd/migration-auto-check.ts +15 -23
  308. package/src/resources/extensions/gsd/milestone-actions.ts +10 -4
  309. package/src/resources/extensions/gsd/native-git-bridge.ts +54 -12
  310. package/src/resources/extensions/gsd/pending-auto-start.ts +79 -0
  311. package/src/resources/extensions/gsd/post-execution-checks.ts +87 -2
  312. package/src/resources/extensions/gsd/pre-execution-checks.ts +32 -1
  313. package/src/resources/extensions/gsd/prompt-loader.ts +1 -1
  314. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  315. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
  316. package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -8
  317. package/src/resources/extensions/gsd/prompts/discuss.md +9 -9
  318. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +4 -4
  319. package/src/resources/extensions/gsd/prompts/guided-discuss-requirements.md +3 -3
  320. package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -4
  321. package/src/resources/extensions/gsd/prompts/queue.md +4 -4
  322. package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
  323. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  324. package/src/resources/extensions/gsd/prompts/system.md +2 -2
  325. package/src/resources/extensions/gsd/provider-switch-observer.ts +185 -0
  326. package/src/resources/extensions/gsd/smart-entry-routing.ts +77 -0
  327. package/src/resources/extensions/gsd/state-reconciliation/drift/merge-state.ts +8 -1
  328. package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +12 -15
  329. package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +17 -25
  330. package/src/resources/extensions/gsd/status-guards.ts +5 -0
  331. package/src/resources/extensions/gsd/templates/knowledge.md +2 -2
  332. package/src/resources/extensions/gsd/templates/plan.md +8 -5
  333. package/src/resources/extensions/gsd/templates/task-plan.md +4 -2
  334. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +71 -0
  335. package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +116 -0
  336. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +129 -0
  337. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +487 -4
  338. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +12 -11
  339. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +53 -2
  340. package/src/resources/extensions/gsd/tests/auto-post-unit-step-message.test.ts +12 -1
  341. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +15 -1
  342. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +4 -4
  343. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +1 -0
  344. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +69 -1
  345. package/src/resources/extensions/gsd/tests/brief-command.test.ts +89 -0
  346. package/src/resources/extensions/gsd/tests/browser-tools-compatibility-declarations.test.ts +62 -0
  347. package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +107 -2
  348. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +11 -2
  349. package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +16 -0
  350. package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +4 -1
  351. package/src/resources/extensions/gsd/tests/complete-slice.test.ts +5 -9
  352. package/src/resources/extensions/gsd/tests/complete-task.test.ts +3 -1
  353. package/src/resources/extensions/gsd/tests/context-store-decisions-from-memories.test.ts +312 -0
  354. package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +43 -2
  355. package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +208 -0
  356. package/src/resources/extensions/gsd/tests/db-writer.test.ts +13 -8
  357. package/src/resources/extensions/gsd/tests/decisions-projection-from-memories.test.ts +453 -0
  358. package/src/resources/extensions/gsd/tests/decisions-stop-table-writes.test.ts +348 -0
  359. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +59 -2
  360. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +39 -0
  361. package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +27 -0
  362. package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +38 -0
  363. package/src/resources/extensions/gsd/tests/export-html-enhancements.test.ts +8 -0
  364. package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +8 -4
  365. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +11 -7
  366. package/src/resources/extensions/gsd/tests/guided-discuss-project-prompt-rendering.test.ts +2 -0
  367. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +106 -0
  368. package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +59 -11
  369. package/src/resources/extensions/gsd/tests/guided-flow.test.ts +21 -0
  370. package/src/resources/extensions/gsd/tests/guided-tool-contract.test.ts +65 -0
  371. package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +7 -7
  372. package/src/resources/extensions/gsd/tests/hook-model-resolution.test.ts +5 -0
  373. package/src/resources/extensions/gsd/tests/infra-error.test.ts +2 -2
  374. package/src/resources/extensions/gsd/tests/infra-errors-cooldown.test.ts +9 -0
  375. package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +44 -0
  376. package/src/resources/extensions/gsd/tests/integration/doctor-runtime.test.ts +20 -0
  377. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +103 -1
  378. package/src/resources/extensions/gsd/tests/integration/integration-lifecycle.test.ts +13 -5
  379. package/src/resources/extensions/gsd/tests/integration/migrate-command.test.ts +48 -3
  380. package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +6 -1
  381. package/src/resources/extensions/gsd/tests/knowledge-backfill-projection.test.ts +323 -0
  382. package/src/resources/extensions/gsd/tests/knowledge-capture.test.ts +242 -0
  383. package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -2
  384. package/src/resources/extensions/gsd/tests/load-knowledge-block-rules-only.test.ts +209 -0
  385. package/src/resources/extensions/gsd/tests/memory-consolidation-scanner.test.ts +316 -0
  386. package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +5 -1
  387. package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +24 -1
  388. package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +6 -1
  389. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +26 -18
  390. package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +63 -2
  391. package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +121 -1
  392. package/src/resources/extensions/gsd/tests/park-db-sync.test.ts +55 -1
  393. package/src/resources/extensions/gsd/tests/pending-autostart-scope.test.ts +29 -5
  394. package/src/resources/extensions/gsd/tests/plan-milestone-sketch-render.test.ts +157 -0
  395. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +26 -0
  396. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  397. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +225 -1
  398. package/src/resources/extensions/gsd/tests/plan-task.test.ts +17 -0
  399. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +79 -1
  400. package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +86 -0
  401. package/src/resources/extensions/gsd/tests/post-unit-git-failure.test.ts +1 -1
  402. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +53 -0
  403. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +8 -0
  404. package/src/resources/extensions/gsd/tests/prompt-loader.test.ts +23 -0
  405. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +20 -1
  406. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +252 -0
  407. package/src/resources/extensions/gsd/tests/remediation-completion-guard.test.ts +46 -2
  408. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +16 -4
  409. package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +10 -0
  410. package/src/resources/extensions/gsd/tests/smart-entry-routing.test.ts +113 -0
  411. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +53 -2
  412. package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +6 -0
  413. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +119 -23
  414. package/src/resources/extensions/gsd/tests/stuck-state-via-db.test.ts +64 -1
  415. package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +7 -3
  416. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +86 -7
  417. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +110 -1
  418. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +78 -0
  419. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +1 -1
  420. package/src/resources/extensions/gsd/tests/workflow-memory-pressure.test.ts +21 -1
  421. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +1 -1
  422. package/src/resources/extensions/gsd/tests/worktree-git-pathspec.test.ts +39 -0
  423. package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +64 -12
  424. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +25 -0
  425. package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +54 -0
  426. package/src/resources/extensions/gsd/tools/complete-milestone.ts +8 -10
  427. package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -8
  428. package/src/resources/extensions/gsd/tools/plan-milestone.ts +5 -1
  429. package/src/resources/extensions/gsd/tools/plan-slice.ts +98 -12
  430. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +135 -0
  431. package/src/resources/extensions/gsd/types.ts +1 -1
  432. package/src/resources/extensions/gsd/unit-context-manifest.ts +47 -11
  433. package/src/resources/extensions/gsd/validation.ts +23 -1
  434. package/src/resources/extensions/gsd/verification-gate.ts +78 -6
  435. package/src/resources/extensions/gsd/verification-verdict.ts +47 -0
  436. package/src/resources/extensions/gsd/workflow-logger.ts +4 -0
  437. package/src/resources/extensions/gsd/workflow-projections.ts +6 -8
  438. package/src/resources/extensions/gsd/worktree-lifecycle.ts +61 -10
  439. package/src/resources/extensions/shared/html-shell.ts +412 -0
  440. package/src/resources/extensions/subagent/index.ts +567 -103
  441. package/src/resources/extensions/subagent/launch.ts +131 -0
  442. package/src/resources/extensions/subagent/run-store.ts +218 -0
  443. package/src/resources/extensions/subagent/tests/launch.test.ts +115 -0
  444. package/src/resources/extensions/subagent/tests/run-store.test.ts +111 -0
  445. package/src/resources/extensions/visual-brief/artifact-policy.ts +41 -0
  446. package/src/resources/extensions/visual-brief/extension-manifest.json +8 -0
  447. package/src/resources/extensions/visual-brief/index.ts +8 -0
  448. package/src/resources/extensions/visual-brief/page-contract.ts +136 -0
  449. package/src/resources/extensions/visual-brief/prompts.ts +183 -0
  450. package/src/resources/extensions/visual-brief/tests/visual-brief.test.ts +212 -0
  451. package/dist/web/standalone/.next/server/chunks/5822.js +0 -2
  452. package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +0 -1
  453. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +0 -1
  454. package/dist/web/standalone/.next/static/css/54ec2745c1da488b.css +0 -1
  455. package/dist/web/standalone/.next/static/css/de70bee13400563f.css +0 -1
  456. package/dist/web/standalone/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
  457. package/dist/web/standalone/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  458. package/dist/web/standalone/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  459. package/dist/web/standalone/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  460. package/dist/web/standalone/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  461. package/dist/web/standalone/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  462. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_buildManifest.js +0 -0
  463. /package/dist/web/standalone/.next/static/{rIkMv4YSNlfSeqmGqWVns → xRy4LqKSNKdT7y6ATYyEl}/_ssgManifest.js +0 -0
@@ -47,6 +47,118 @@ export function queryDecisions(opts) {
47
47
  return [];
48
48
  }
49
49
  }
50
+ /**
51
+ * Internal: shared core for the two memory-sourced decision queries. Reads
52
+ * memory rows tagged with `sourceDecisionId` and reconstructs `Decision[]`
53
+ * from their `structured_fields` JSON.
54
+ *
55
+ * @param includeSuperseded — when false, drops rows whose
56
+ * `structured_fields.superseded_by` is non-null. The supersedes-chain is
57
+ * captured by the backfill (`memory-backfill.ts`) and kept in sync by
58
+ * the backfill's drift auto-heal pass.
59
+ */
60
+ function readDecisionsFromMemories(opts, includeSuperseded) {
61
+ if (!isDbAvailable())
62
+ return [];
63
+ const adapter = _getAdapter();
64
+ if (!adapter)
65
+ return [];
66
+ try {
67
+ const clauses = [
68
+ "category = 'architecture'",
69
+ "structured_fields LIKE '%\"sourceDecisionId\":\"%'",
70
+ ];
71
+ const params = {};
72
+ if (opts?.milestoneId) {
73
+ // when_context is a free-text JSON value; substring match preserves the
74
+ // semantics of `when_context LIKE '%milestoneId%'` on the legacy table.
75
+ clauses.push("json_extract(structured_fields, '$.when_context') LIKE :milestone_pattern");
76
+ params[':milestone_pattern'] = `%${opts.milestoneId}%`;
77
+ }
78
+ if (opts?.scope) {
79
+ // Stage 1 used `json_extract` in main (post-merge); preserve that
80
+ // style here. Exact equality on the JSON value avoids the prefix
81
+ // collision risk LIKE patterns had (scope=M001 vs scope=M001-S01).
82
+ clauses.push("json_extract(structured_fields, '$.scope') = :scope");
83
+ params[':scope'] = opts.scope;
84
+ }
85
+ const sql = `SELECT seq, structured_fields FROM memories WHERE ${clauses.join(' AND ')} ORDER BY seq`;
86
+ const rows = adapter.prepare(sql).all(params);
87
+ const decisions = [];
88
+ for (const row of rows) {
89
+ const seq = row['seq'];
90
+ const sfRaw = row['structured_fields'];
91
+ if (!sfRaw)
92
+ continue;
93
+ let sf;
94
+ try {
95
+ sf = JSON.parse(sfRaw);
96
+ }
97
+ catch {
98
+ continue;
99
+ }
100
+ const sourceId = sf['sourceDecisionId'];
101
+ if (typeof sourceId !== 'string' || sourceId.length === 0)
102
+ continue;
103
+ // Decision-level superseded status lives in structured_fields.superseded_by
104
+ // (written by mirrorDecisionToMemory / memory-backfill.ts). The top-level
105
+ // memories.superseded_by column is intentionally never set for decision mirrors,
106
+ // so active-only filtering must be done here in the JS loop.
107
+ const supersededBy = typeof sf['superseded_by'] === 'string' ? sf['superseded_by'] : null;
108
+ if (!includeSuperseded && supersededBy)
109
+ continue;
110
+ decisions.push({
111
+ seq,
112
+ id: sourceId,
113
+ when_context: typeof sf['when_context'] === 'string' ? sf['when_context'] : '',
114
+ scope: typeof sf['scope'] === 'string' ? sf['scope'] : '',
115
+ decision: typeof sf['decision'] === 'string' ? sf['decision'] : '',
116
+ choice: typeof sf['choice'] === 'string' ? sf['choice'] : '',
117
+ rationale: typeof sf['rationale'] === 'string' ? sf['rationale'] : '',
118
+ revisable: typeof sf['revisable'] === 'string' ? sf['revisable'] : '',
119
+ made_by: (typeof sf['made_by'] === 'string' ? sf['made_by'] : 'agent'),
120
+ superseded_by: supersededBy,
121
+ });
122
+ }
123
+ return decisions;
124
+ }
125
+ catch {
126
+ return [];
127
+ }
128
+ }
129
+ /**
130
+ * ADR-013 Phase 6 cutover (Stage 1): read **active** decisions from the
131
+ * `memories` table instead of the legacy `decisions` table. Returns the
132
+ * same `Decision[]` shape as `queryDecisions` so downstream formatters
133
+ * work unchanged.
134
+ *
135
+ * Filter semantics match `queryDecisions` exactly:
136
+ * - active only (skips rows where `structured_fields.superseded_by` is set)
137
+ * - `milestoneId`: substring match on `structured_fields.when_context`
138
+ * - `scope`: exact match on `structured_fields.scope`
139
+ *
140
+ * Used by the prompt-inline path (`inlineDecisionsFromDb` in
141
+ * `auto-prompts.ts`). For the projection regen (which renders superseded
142
+ * rows too), see `getAllDecisionsFromMemories`.
143
+ */
144
+ export function queryDecisionsFromMemories(opts) {
145
+ return readDecisionsFromMemories(opts, /* includeSuperseded */ false);
146
+ }
147
+ /**
148
+ * ADR-013 Phase 6 cutover (Stage 2a): read **all** decisions (active +
149
+ * superseded) from the `memories` table. Used by the DECISIONS.md
150
+ * projection regen in `saveDecisionToDb`, which must render the full
151
+ * supersedes-chain for the canonical register format.
152
+ *
153
+ * Equivalent to `SELECT * FROM decisions ORDER BY seq` over the legacy
154
+ * table — but sourced from memories so the legacy table can be retired
155
+ * in Stage 3. Includes `superseded_by` reconstructed from
156
+ * `structured_fields.superseded_by` (populated by the backfill's drift
157
+ * auto-heal pass).
158
+ */
159
+ export function getAllDecisionsFromMemories() {
160
+ return readDecisionsFromMemories(undefined, /* includeSuperseded */ true);
161
+ }
50
162
  /**
51
163
  * Query active (non-superseded) requirements with optional filters.
52
164
  * - milestoneId: combined with sliceId for precise filtering (e.g. %M005/S01%)
@@ -23,7 +23,8 @@
23
23
  import { emitJournalEvent, queryJournal, } from "./journal.js";
24
24
  import { readFileSync, unlinkSync, existsSync } from "node:fs";
25
25
  import { join } from "node:path";
26
- import { findStaleWorkerForProject, getAllAutoWorkers, } from "./db/auto-workers.js";
26
+ import { findStaleWorkerForProject, getAllAutoWorkers, markWorkerCrashed, } from "./db/auto-workers.js";
27
+ import { markLatestActiveForWorkerCanceled } from "./db/unit-dispatches.js";
27
28
  import { getRuntimeKv, setRuntimeKv, deleteRuntimeKv } from "./db/runtime-kv.js";
28
29
  import { _getAdapter, isDbAvailable } from "./gsd-db.js";
29
30
  import { gsdRoot, normalizeRealPath } from "./paths.js";
@@ -34,6 +35,16 @@ const SESSION_FILE_KV_KEY = "session_file";
34
35
  function lockPath(basePath) {
35
36
  return join(gsdRoot(basePath), effectiveLockFile());
36
37
  }
38
+ function clearLegacyLockFile(basePath) {
39
+ try {
40
+ const p = lockPath(basePath);
41
+ if (existsSync(p))
42
+ unlinkSync(p);
43
+ }
44
+ catch {
45
+ // Best-effort.
46
+ }
47
+ }
37
48
  function readLegacyLock(basePath) {
38
49
  try {
39
50
  const p = lockPath(basePath);
@@ -166,21 +177,36 @@ export function writeLock(basePath, unitType, unitId, sessionFile) {
166
177
  * stale session-file pointer.
167
178
  */
168
179
  export function clearLock(basePath) {
180
+ clearLegacyLockFile(basePath);
181
+ if (!isDbAvailable())
182
+ return;
169
183
  try {
170
- const p = lockPath(basePath);
171
- if (existsSync(p))
172
- unlinkSync(p);
184
+ const projectRoot = normalizeRealPath(basePath);
185
+ const worker = findActiveWorkerForCurrentProcess(projectRoot);
186
+ if (!worker)
187
+ return;
188
+ deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
173
189
  }
174
190
  catch {
175
191
  // Best-effort.
176
192
  }
193
+ }
194
+ /**
195
+ * Clear a stale DB-backed worker lock after readCrashLock/findStaleWorkerForProject
196
+ * has identified a dead worker. Unlike clearLock(), this targets the stale
197
+ * worker row instead of the current process's active worker.
198
+ */
199
+ export function clearStaleWorkerLock(basePath) {
200
+ clearLegacyLockFile(basePath);
177
201
  if (!isDbAvailable())
178
202
  return;
179
203
  try {
180
204
  const projectRoot = normalizeRealPath(basePath);
181
- const worker = findActiveWorkerForCurrentProcess(projectRoot);
205
+ const worker = findStaleWorkerForProject(projectRoot);
182
206
  if (!worker)
183
207
  return;
208
+ markLatestActiveForWorkerCanceled(worker.worker_id, "crash-recovered");
209
+ markWorkerCrashed(worker.worker_id);
184
210
  deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
185
211
  }
186
212
  catch {
@@ -391,16 +391,17 @@ export function getRecentUnitKeysForProjectRoot(projectRootRealpath, limit = 20)
391
391
  if (!isDbAvailable())
392
392
  return [];
393
393
  const db = _getAdapter();
394
- const rows = db.prepare(`SELECT ud.unit_id
394
+ const rows = db.prepare(`SELECT ud.unit_type, ud.unit_id
395
395
  FROM unit_dispatches ud
396
396
  INNER JOIN workers w ON w.worker_id = ud.worker_id
397
397
  WHERE w.project_root_realpath = :project_root_realpath
398
+ AND w.status != 'crashed'
398
399
  ORDER BY ud.started_at DESC, ud.id DESC
399
400
  LIMIT :limit`).all({
400
401
  ":project_root_realpath": projectRootRealpath,
401
402
  ":limit": limit,
402
403
  });
403
- return rows.reverse().map((r) => ({ key: r.unit_id }));
404
+ return rows.reverse().map((r) => ({ key: `${r.unit_type}/${r.unit_id}` }));
404
405
  }
405
406
  /**
406
407
  * Fetch dispatches for a milestone filtered by status. Useful for janitors
@@ -210,16 +210,62 @@ export async function nextDecisionId() {
210
210
  return 'D001';
211
211
  }
212
212
  }
213
- /** Synchronous variant for use inside db.transaction(). */
214
- function nextDecisionIdSync(adapter) {
213
+ /**
214
+ * ADR-013 Stage 3: compute the next `D###` identifier across both the legacy
215
+ * `decisions` table AND the `memories.structured_fields.sourceDecisionId`
216
+ * surface. Returns the max numeric suffix from either side + 1, three-digit
217
+ * padded.
218
+ *
219
+ * Used by `saveDecisionToDb` once writes to the `decisions` table stop —
220
+ * new decisions live only in memories, but historical IDs sit in both
221
+ * places during the cutover bake. The cross-surface max keeps IDs
222
+ * monotonic and avoids collisions on the next save.
223
+ */
224
+ function nextDecisionIdAcrossSurfaces(adapter) {
215
225
  if (!adapter)
216
226
  return 'D001';
217
- const row = adapter
218
- .prepare('SELECT MAX(CAST(SUBSTR(id, 2) AS INTEGER)) as max_num FROM decisions')
219
- .get();
220
- const maxNum = row ? row['max_num'] : null;
221
- if (maxNum == null || isNaN(maxNum))
222
- return 'D001';
227
+ let maxNum = 0;
228
+ // Legacy table best-effort.
229
+ try {
230
+ const row = adapter
231
+ .prepare('SELECT MAX(CAST(SUBSTR(id, 2) AS INTEGER)) as max_num FROM decisions')
232
+ .get();
233
+ const candidate = row ? row['max_num'] : null;
234
+ if (typeof candidate === 'number' && Number.isFinite(candidate)) {
235
+ maxNum = Math.max(maxNum, candidate);
236
+ }
237
+ }
238
+ catch {
239
+ // fall through to memory-only
240
+ }
241
+ // Memory surface: scan structuredFields.sourceDecisionId for D### values.
242
+ // SQLite LIKE on the JSON-stringified field is sufficient — rows tagged
243
+ // with sourceDecisionId are bounded by the decisions count.
244
+ try {
245
+ const rows = adapter
246
+ .prepare("SELECT structured_fields FROM memories WHERE structured_fields LIKE '%\"sourceDecisionId\":\"D%'")
247
+ .all();
248
+ for (const row of rows) {
249
+ if (!row.structured_fields)
250
+ continue;
251
+ let sf;
252
+ try {
253
+ sf = JSON.parse(row.structured_fields);
254
+ }
255
+ catch {
256
+ continue;
257
+ }
258
+ const sourceId = sf['sourceDecisionId'];
259
+ if (typeof sourceId !== 'string' || !sourceId.startsWith('D'))
260
+ continue;
261
+ const num = parseInt(sourceId.slice(1), 10);
262
+ if (Number.isFinite(num) && num > maxNum)
263
+ maxNum = num;
264
+ }
265
+ }
266
+ catch {
267
+ // best-effort
268
+ }
223
269
  const next = maxNum + 1;
224
270
  return `D${String(next).padStart(3, '0')}`;
225
271
  }
@@ -376,38 +422,55 @@ export async function saveDecisionToDb(fields, basePath) {
376
422
  try {
377
423
  const db = await import('./gsd-db.js');
378
424
  const adapter = db._getAdapter();
379
- const id = db.transaction(() => {
380
- const nextId = nextDecisionIdSync(adapter);
381
- db.upsertDecision({
382
- id: nextId,
383
- when_context: fields.when_context ?? '',
384
- scope: fields.scope,
385
- decision: fields.decision,
386
- choice: fields.choice,
387
- rationale: fields.rationale,
388
- revisable: fields.revisable ?? 'Yes',
389
- made_by: fields.made_by ?? 'agent',
390
- source: fields.source ?? 'discussion',
391
- superseded_by: null,
425
+ const normalized = {
426
+ ...fields,
427
+ when_context: fields.when_context ?? '',
428
+ revisable: fields.revisable ?? 'Yes',
429
+ made_by: fields.made_by ?? 'agent',
430
+ source: fields.source ?? 'discussion',
431
+ };
432
+ // ADR-013 Stage 3 (destructive): writes to the `decisions` table stop
433
+ // here. New decisions live only in the `memories` table; the projection
434
+ // regen below sources from memories (Stage 2a). The decisions table
435
+ // remains for backwards-compat reads (queryDecisions, md-importer,
436
+ // commands-inspect, workflow-manifest) until #5756 drops it.
437
+ //
438
+ // Reversal: a code revert of this change restores the upsertDecision
439
+ // call. Memory rows written between merge and revert stay durable; the
440
+ // legacy table simply doesn't grow during the cutover window.
441
+ const id = nextDecisionIdAcrossSurfaces(adapter);
442
+ // The mirror-to-memories write is what persists the new decision. Must
443
+ // run before the projection regen — the regen sources from memories
444
+ // (Stage 2a) and would otherwise miss the just-saved decision. Pass
445
+ // the normalized field set so defaults (revisable, made_by, source)
446
+ // are recorded on the memory row.
447
+ await mirrorDecisionToMemory(id, normalized);
448
+ // Fetch all decisions (including superseded for the full register).
449
+ // ADR-013 Stage 2a: source from the `memories` table. The Phase 5
450
+ // dual-write keeps memories in sync with each decision save; the backfill
451
+ // (memory-backfill.ts) absorbs the historical chain and drift-heals
452
+ // superseded_by on every session start.
453
+ const { getAllDecisionsFromMemories } = await import('./context-store.js');
454
+ let allDecisions = getAllDecisionsFromMemories();
455
+ if (!allDecisions.some(d => d.id === id)) {
456
+ logWarning('projection', 'just-saved decision missing from memories after mirror; injecting fallback for projection', {
457
+ fn: 'saveDecisionToDb',
458
+ decisionId: id,
392
459
  });
393
- return nextId;
394
- });
395
- // Fetch all decisions (including superseded for the full register)
396
- let allDecisions = [];
397
- if (adapter) {
398
- const rows = adapter.prepare('SELECT * FROM decisions ORDER BY seq').all();
399
- allDecisions = rows.map(row => ({
400
- seq: row['seq'],
401
- id: row['id'],
402
- when_context: row['when_context'],
403
- scope: row['scope'],
404
- decision: row['decision'],
405
- choice: row['choice'],
406
- rationale: row['rationale'],
407
- revisable: row['revisable'],
408
- made_by: row['made_by'] ?? 'agent',
409
- superseded_by: row['superseded_by'] ?? null,
410
- }));
460
+ const nextSeq = allDecisions.reduce((max, d) => Math.max(max, d.seq ?? 0), 0) + 1;
461
+ const fallback = {
462
+ seq: nextSeq,
463
+ id,
464
+ when_context: normalized.when_context,
465
+ scope: normalized.scope,
466
+ decision: normalized.decision,
467
+ choice: normalized.choice,
468
+ rationale: normalized.rationale,
469
+ revisable: normalized.revisable,
470
+ made_by: normalized.made_by,
471
+ superseded_by: null,
472
+ };
473
+ allDecisions = [...allDecisions, fallback];
411
474
  }
412
475
  const filePath = resolveGsdRootFile(basePath, 'DECISIONS');
413
476
  // Check if existing DECISIONS.md has freeform (non-table) content.
@@ -460,51 +523,6 @@ export async function saveDecisionToDb(fields, basePath) {
460
523
  invalidateStateCache();
461
524
  clearPathCache();
462
525
  clearParseCache();
463
- // ADR-013 dual-write: keep the memory store in sync with every decision
464
- // persisted via the legacy gsd_save_decision path. Without this, prompts
465
- // that still call gsd_save_decision (discuss.md, plan-milestone.md,
466
- // plan-slice.md, et al.) would create decisions rows invisible to
467
- // memory_query and loadMemoryBlock.
468
- // Best-effort — never throw, never roll back the decision on failure.
469
- try {
470
- const { createMemory } = await import('./memory-store.js');
471
- const decisionText = (fields.decision ?? '').trim();
472
- const choiceText = (fields.choice ?? '').trim();
473
- const rationaleText = (fields.rationale ?? '').trim();
474
- const contentParts = [];
475
- if (decisionText)
476
- contentParts.push(decisionText);
477
- if (choiceText)
478
- contentParts.push(`Chose: ${choiceText}.`);
479
- if (rationaleText)
480
- contentParts.push(`Rationale: ${rationaleText}.`);
481
- const content = contentParts.join(' ').slice(0, 600);
482
- if (content) {
483
- createMemory({
484
- category: 'architecture',
485
- content,
486
- scope: fields.scope || 'project',
487
- confidence: 0.85,
488
- structuredFields: {
489
- sourceDecisionId: id,
490
- when_context: fields.when_context ?? '',
491
- scope: fields.scope,
492
- decision: fields.decision,
493
- choice: fields.choice,
494
- rationale: fields.rationale,
495
- made_by: fields.made_by ?? 'agent',
496
- revisable: fields.revisable ?? '',
497
- },
498
- });
499
- }
500
- }
501
- catch (mirrorErr) {
502
- logError('manifest', 'memory-store mirror write failed (non-fatal)', {
503
- fn: 'saveDecisionToDb',
504
- decisionId: id,
505
- error: String(mirrorErr.message),
506
- });
507
- }
508
526
  return { id };
509
527
  }
510
528
  catch (err) {
@@ -515,6 +533,54 @@ export async function saveDecisionToDb(fields, basePath) {
515
533
  release();
516
534
  }
517
535
  }
536
+ /**
537
+ * ADR-013 dual-write — mirror a freshly-saved decision into the `memories`
538
+ * table so the memory store remains the single source of truth for the
539
+ * DECISIONS.md projection (Stage 2a) and for prompt-inline reads (Stage 1).
540
+ *
541
+ * Best-effort mirror: logs failures without throwing to avoid blocking saves.
542
+ * Caller invokes this AFTER the decisions-table write completes and
543
+ * BEFORE the projection regen — the regen sources from memories and would
544
+ * otherwise miss the just-saved decision.
545
+ */
546
+ async function mirrorDecisionToMemory(id, normalizedFields) {
547
+ try {
548
+ const { createMemory } = await import('./memory-store.js');
549
+ const { synthesizeDecisionMemoryContent } = await import('./memory-backfill.js');
550
+ const content = synthesizeDecisionMemoryContent(normalizedFields);
551
+ if (!content)
552
+ return false;
553
+ createMemory({
554
+ category: 'architecture',
555
+ content,
556
+ scope: normalizedFields.scope || 'project',
557
+ confidence: 0.85,
558
+ structuredFields: {
559
+ sourceDecisionId: id,
560
+ when_context: normalizedFields.when_context,
561
+ scope: normalizedFields.scope,
562
+ decision: normalizedFields.decision,
563
+ choice: normalizedFields.choice,
564
+ rationale: normalizedFields.rationale,
565
+ made_by: normalizedFields.made_by,
566
+ revisable: normalizedFields.revisable,
567
+ // New decisions are always written as active; md-importer can later
568
+ // set superseded_by on the source decision row, and the backfill's
569
+ // drift auto-heal pass propagates that update to this memory.
570
+ superseded_by: null,
571
+ },
572
+ });
573
+ return true;
574
+ }
575
+ catch (mirrorErr) {
576
+ logError('manifest', 'memory-store mirror write failed', {
577
+ fn: 'saveDecisionToDb',
578
+ decisionId: id,
579
+ error: String(mirrorErr.message),
580
+ });
581
+ return false;
582
+ }
583
+ }
518
584
  /**
519
585
  * Extract a milestone/slice reference from a deferral decision.
520
586
  *
@@ -4,7 +4,7 @@ import { findMilestoneIds } from "./guided-flow.js";
4
4
  import { parseUnitId } from "./unit-id.js";
5
5
  import { isDbAvailable, getMilestoneSlices, getMilestone } from "./gsd-db.js";
6
6
  import { parseRoadmap } from "./parsers-legacy.js";
7
- import { isClosedStatus } from "./status-guards.js";
7
+ import { isClosedStatus, isSkippedForDispatch } from "./status-guards.js";
8
8
  import { classifyMilestoneSummaryContent } from "./milestone-summary-classifier.js";
9
9
  import { readFileSync } from "node:fs";
10
10
  const SLICE_DISPATCH_TYPES = new Set([
@@ -49,7 +49,7 @@ export function getPriorSliceCompletionBlocker(base, _mainBranch, unitType, unit
49
49
  // DB-backed projects must not treat SUMMARY.md as authoritative.
50
50
  if (isDbAvailable()) {
51
51
  const milestoneRow = getMilestone(mid);
52
- if (milestoneRow && isClosedStatus(milestoneRow.status))
52
+ if (milestoneRow && isSkippedForDispatch(milestoneRow.status))
53
53
  continue;
54
54
  }
55
55
  else {
@@ -100,7 +100,7 @@ Setting `prefer_skills: []` does **not** disable skill discovery — it just mea
100
100
 
101
101
  - `skill_rules`: situational rules with a human-readable `when` trigger and one or more of `use`, `prefer`, or `avoid`.
102
102
 
103
- - `custom_instructions`: extra durable instructions related to skill use. For operational project knowledge (recurring rules, gotchas, patterns), use `.gsd/KNOWLEDGE.md` instead it's injected into every agent prompt automatically and agents can append to it during execution.
103
+ - `custom_instructions`: extra durable instructions related to skill use. For operational project knowledge, use `.gsd/KNOWLEDGE.md` instead. Rules are file-canonical; patterns and lessons are persisted to the `memories` table and projected back into `KNOWLEDGE.md` on the next session start.
104
104
 
105
105
  - `language`: preferred response language for all GSD interactions. Accepts any language name or code — `"Chinese"`, `"zh"`, `"German"`, `"de"`, `"日本語"`, etc. When set, GSD injects "Always respond in \<language\>" into every agent's system prompt, including after `/clear`. Quickest way to set it: `/gsd language <name>`. To clear: `/gsd language off`.
106
106
 
@@ -1,3 +1,5 @@
1
+ // GSD-2 doctor git health checks
2
+ import { spawnSync } from "node:child_process";
1
3
  import { existsSync, readdirSync, realpathSync, rmSync, statSync } from "node:fs";
2
4
  import { join, sep } from "node:path";
3
5
  import { loadFile } from "./files.js";
@@ -48,6 +50,23 @@ function isSameOrNestedPath(candidate, container) {
48
50
  return normalizedCandidate === normalizedContainer ||
49
51
  normalizedCandidate.startsWith(`${normalizedContainer}/`);
50
52
  }
53
+ function getSnapshotDiffCheckFailure(basePath) {
54
+ const failures = [];
55
+ for (const args of [["--cached"], []]) {
56
+ const result = spawnSync("git", ["diff", "--check", ...args], {
57
+ cwd: basePath,
58
+ encoding: "utf-8",
59
+ });
60
+ if (result.status === 0)
61
+ continue;
62
+ const output = [result.stdout, result.stderr, result.error?.message]
63
+ .filter(Boolean)
64
+ .join("\n")
65
+ .trim();
66
+ failures.push(output || `git diff --check ${args.join(" ")} failed`);
67
+ }
68
+ return failures.length > 0 ? failures.join("\n") : null;
69
+ }
51
70
  async function isCompletedMilestoneTerminal(basePath, milestoneId) {
52
71
  const summaryPath = resolveMilestoneFile(basePath, milestoneId, "SUMMARY");
53
72
  if (!summaryPath)
@@ -401,16 +420,32 @@ export async function checkGitHealth(basePath, issues, fixesApplied, shouldFix,
401
420
  message: `Uncommitted changes detected with no commit in ${mins} minute${mins === 1 ? "" : "s"} (threshold: ${thresholdMinutes}m). Snapshotting tracked files.`,
402
421
  fixable: true,
403
422
  });
423
+ const diffCheckFailure = getSnapshotDiffCheckFailure(basePath);
424
+ if (diffCheckFailure) {
425
+ issues.push({
426
+ severity: "error",
427
+ code: "conflict_markers_in_tracked_files",
428
+ scope: "project",
429
+ unitId: "project",
430
+ message: `Cannot create gsd snapshot: tracked changes contain conflict markers or whitespace errors. Resolve conflicts manually before auto-mode can proceed.\n${diffCheckFailure}`,
431
+ fixable: false,
432
+ });
433
+ }
404
434
  if (shouldFix("stale_uncommitted_changes")) {
405
435
  try {
406
- nativeAddTracked(basePath);
407
- const commitMsg = `gsd snapshot: uncommitted changes after ${mins}m inactivity`;
408
- const result = nativeCommit(basePath, commitMsg);
409
- if (result) {
410
- fixesApplied.push(`created gsd snapshot after ${mins}m of uncommitted changes`);
436
+ if (diffCheckFailure) {
437
+ fixesApplied.push("gsd snapshot skipped - conflict markers detected in tracked files");
411
438
  }
412
439
  else {
413
- fixesApplied.push("gsd snapshot skipped — nothing to commit after staging tracked files");
440
+ nativeAddTracked(basePath);
441
+ const commitMsg = `gsd snapshot: uncommitted changes after ${mins}m inactivity`;
442
+ const result = nativeCommit(basePath, commitMsg);
443
+ if (result) {
444
+ fixesApplied.push(`created gsd snapshot after ${mins}m of uncommitted changes`);
445
+ }
446
+ else {
447
+ fixesApplied.push("gsd snapshot skipped — nothing to commit after staging tracked files");
448
+ }
414
449
  }
415
450
  }
416
451
  catch {
@@ -5,7 +5,7 @@ import { milestonesDir, gsdRoot, resolveGsdRootFile } from "./paths.js";
5
5
  import { deriveState, isGhostMilestone, isReusableGhostMilestone } from "./state.js";
6
6
  import { saveFile } from "./files.js";
7
7
  import { nativeIsRepo, nativeForEachRef, nativeUpdateRef } from "./native-git-bridge.js";
8
- import { readCrashLock, isLockProcessAlive, clearLock } from "./crash-recovery.js";
8
+ import { readCrashLock, isLockProcessAlive, clearStaleWorkerLock } from "./crash-recovery.js";
9
9
  import { getActiveAutoWorkers } from "./db/auto-workers.js";
10
10
  import { normalizeRealPath } from "./paths.js";
11
11
  import { ensureGitignore, isGsdGitignored } from "./gitignore.js";
@@ -46,7 +46,7 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
46
46
  fixable: true,
47
47
  });
48
48
  if (shouldFix("stale_crash_lock")) {
49
- clearLock(basePath);
49
+ clearStaleWorkerLock(basePath);
50
50
  fixesApplied.push("cleared stale auto-mode worker state");
51
51
  }
52
52
  }
@@ -70,15 +70,32 @@ export async function checkRuntimeHealth(basePath, issues, fixesApplied, shouldF
70
70
  // heartbeat for this project?" — readCrashLock returns null for
71
71
  // healthy live workers (it surfaces stale ones only), so we must
72
72
  // consult getActiveAutoWorkers directly.
73
- const projectRoot = normalizeRealPath(basePath);
74
- const activeWorkers = getActiveAutoWorkers().filter((w) => w.project_root_realpath === projectRoot && isLockProcessAlive({
75
- pid: w.pid,
76
- startedAt: w.started_at,
77
- unitType: "starting",
78
- unitId: "bootstrap",
79
- unitStartedAt: w.started_at,
80
- }));
81
- const lockHolderAlive = activeWorkers.length > 0;
73
+ let lockHolderAlive = false;
74
+ try {
75
+ const projectRoot = normalizeRealPath(basePath);
76
+ for (const worker of getActiveAutoWorkers()) {
77
+ if (worker.project_root_realpath !== projectRoot)
78
+ continue;
79
+ try {
80
+ if (isLockProcessAlive({
81
+ pid: worker.pid,
82
+ startedAt: worker.started_at,
83
+ unitType: "starting",
84
+ unitId: "bootstrap",
85
+ unitStartedAt: worker.started_at,
86
+ })) {
87
+ lockHolderAlive = true;
88
+ break;
89
+ }
90
+ }
91
+ catch {
92
+ // Ignore malformed worker rows or transient PID probe failures.
93
+ }
94
+ }
95
+ }
96
+ catch {
97
+ // If worker lookup fails, continue with the stranded lock diagnosis.
98
+ }
82
99
  if (!lockHolderAlive) {
83
100
  issues.push({
84
101
  severity: "error",