@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545

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 (375) hide show
  1. package/dist/cli-web-branch.d.ts +2 -0
  2. package/dist/cli-web-branch.js +9 -2
  3. package/dist/help-text.js +5 -0
  4. package/dist/resources/.managed-resources-content-hash +1 -1
  5. package/dist/resources/extensions/ask-user-questions.js +78 -23
  6. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
  7. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
  8. package/dist/resources/extensions/github-sync/templates.js +3 -3
  9. package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
  10. package/dist/resources/extensions/gsd/auto/loop.js +74 -56
  11. package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
  12. package/dist/resources/extensions/gsd/auto/phases.js +28 -3
  13. package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
  14. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  15. package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
  16. package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
  17. package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
  18. package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
  19. package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
  20. package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
  21. package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
  22. package/dist/resources/extensions/gsd/auto-start.js +12 -23
  23. package/dist/resources/extensions/gsd/auto-timers.js +16 -2
  24. package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
  25. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
  26. package/dist/resources/extensions/gsd/auto-verification.js +7 -7
  27. package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
  28. package/dist/resources/extensions/gsd/auto.js +11 -7
  29. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
  30. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
  31. package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
  32. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
  33. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
  34. package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
  35. package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
  36. package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
  37. package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
  38. package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
  39. package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
  40. package/dist/resources/extensions/gsd/commands-ship.js +2 -2
  41. package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
  42. package/dist/resources/extensions/gsd/db-workspace.js +103 -0
  43. package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
  44. package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
  45. package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  46. package/dist/resources/extensions/gsd/doctor.js +16 -9
  47. package/dist/resources/extensions/gsd/error-classifier.js +1 -1
  48. package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
  49. package/dist/resources/extensions/gsd/gsd-db.js +12 -0
  50. package/dist/resources/extensions/gsd/guided-flow.js +34 -468
  51. package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
  52. package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
  53. package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
  54. package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
  55. package/dist/resources/extensions/gsd/md-importer.js +4 -3
  56. package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
  57. package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
  58. package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
  59. package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
  60. package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
  61. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
  62. package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
  63. package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
  64. package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
  65. package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
  66. package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
  67. package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
  68. package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
  69. package/dist/resources/extensions/gsd/preferences.js +147 -29
  70. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  71. package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
  72. package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  73. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  74. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  75. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  76. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  77. package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
  78. package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
  79. package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
  80. package/dist/resources/extensions/gsd/question-transport.js +86 -0
  81. package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
  82. package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
  83. package/dist/resources/extensions/gsd/state.js +13 -5
  84. package/dist/resources/extensions/gsd/templates/plan.md +7 -0
  85. package/dist/resources/extensions/gsd/templates/project.md +1 -0
  86. package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
  87. package/dist/resources/extensions/gsd/templates/uat.md +5 -1
  88. package/dist/resources/extensions/gsd/tool-contract.js +52 -8
  89. package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
  90. package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
  91. package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
  92. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
  93. package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
  94. package/dist/resources/extensions/gsd/uat-policy.js +16 -10
  95. package/dist/resources/extensions/gsd/uat-run.js +9 -14
  96. package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
  97. package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
  98. package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
  99. package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
  100. package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
  101. package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
  102. package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
  103. package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
  104. package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
  105. package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
  106. package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
  107. package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
  108. package/dist/resources/extensions/shared/interview-ui.js +2 -2
  109. package/dist/resources/shared/claude-runtime-floor.js +182 -0
  110. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  111. package/dist/update-cmd.js +20 -0
  112. package/dist/web/standalone/.next/BUILD_ID +1 -1
  113. package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
  114. package/dist/web/standalone/.next/build-manifest.json +3 -3
  115. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  116. package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
  117. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  122. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  126. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  127. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  128. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  129. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  130. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  131. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  132. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  133. package/dist/web/standalone/.next/server/app/index.html +1 -1
  134. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  135. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  136. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  137. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  138. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  139. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  140. package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
  141. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  142. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  144. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  145. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  146. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  147. package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
  148. package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
  149. package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
  150. package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
  151. package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
  152. package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
  153. package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
  154. package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
  155. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  156. package/dist/web-mode.d.ts +2 -0
  157. package/dist/web-mode.js +20 -8
  158. package/package.json +2 -1
  159. package/packages/cloud-mcp-gateway/package.json +2 -2
  160. package/packages/contracts/package.json +1 -1
  161. package/packages/daemon/package.json +4 -4
  162. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
  163. package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
  164. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
  165. package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
  166. package/packages/gsd-agent-core/package.json +5 -5
  167. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  168. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
  169. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  170. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
  171. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
  172. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
  173. package/packages/gsd-agent-modes/package.json +7 -7
  174. package/packages/mcp-server/dist/server.d.ts +10 -0
  175. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  176. package/packages/mcp-server/dist/server.js +8 -0
  177. package/packages/mcp-server/dist/server.js.map +1 -1
  178. package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
  179. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  180. package/packages/mcp-server/dist/workflow-tools.js +2 -1
  181. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  182. package/packages/mcp-server/package.json +3 -3
  183. package/packages/native/package.json +1 -1
  184. package/packages/pi-agent-core/package.json +1 -1
  185. package/packages/pi-ai/dist/models.generated.d.ts +8 -93
  186. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  187. package/packages/pi-ai/dist/models.generated.js +35 -120
  188. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  189. package/packages/pi-ai/package.json +1 -1
  190. package/packages/pi-coding-agent/package.json +7 -7
  191. package/packages/pi-tui/dist/components/input.js +1 -1
  192. package/packages/pi-tui/dist/components/input.js.map +1 -1
  193. package/packages/pi-tui/dist/keys.d.ts.map +1 -1
  194. package/packages/pi-tui/dist/keys.js +39 -30
  195. package/packages/pi-tui/dist/keys.js.map +1 -1
  196. package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
  197. package/packages/pi-tui/dist/stdin-buffer.js +22 -0
  198. package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
  199. package/packages/pi-tui/package.json +2 -2
  200. package/packages/rpc-client/package.json +2 -2
  201. package/pkg/package.json +1 -1
  202. package/src/resources/extensions/ask-user-questions.ts +87 -24
  203. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
  204. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
  205. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
  206. package/src/resources/extensions/github-sync/templates.ts +3 -3
  207. package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
  208. package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
  209. package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
  210. package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
  211. package/src/resources/extensions/gsd/auto/loop.ts +83 -61
  212. package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
  213. package/src/resources/extensions/gsd/auto/phases.ts +35 -3
  214. package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
  215. package/src/resources/extensions/gsd/auto/session.ts +4 -0
  216. package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
  217. package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
  218. package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
  219. package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
  220. package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
  221. package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
  222. package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
  223. package/src/resources/extensions/gsd/auto-start.ts +17 -20
  224. package/src/resources/extensions/gsd/auto-timers.ts +16 -2
  225. package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
  226. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
  227. package/src/resources/extensions/gsd/auto-verification.ts +7 -8
  228. package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
  229. package/src/resources/extensions/gsd/auto.ts +15 -8
  230. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
  231. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
  232. package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
  233. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
  234. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
  235. package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
  236. package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
  237. package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
  238. package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
  239. package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
  240. package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
  241. package/src/resources/extensions/gsd/commands-ship.ts +2 -2
  242. package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
  243. package/src/resources/extensions/gsd/db-workspace.ts +170 -0
  244. package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
  245. package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
  246. package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
  247. package/src/resources/extensions/gsd/doctor.ts +15 -5
  248. package/src/resources/extensions/gsd/error-classifier.ts +1 -1
  249. package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
  250. package/src/resources/extensions/gsd/gsd-db.ts +12 -0
  251. package/src/resources/extensions/gsd/guided-flow.ts +47 -558
  252. package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
  253. package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
  254. package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
  255. package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
  256. package/src/resources/extensions/gsd/md-importer.ts +3 -3
  257. package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
  258. package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
  259. package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
  260. package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
  261. package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
  262. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
  263. package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
  264. package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
  265. package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
  266. package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
  267. package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
  268. package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
  269. package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
  270. package/src/resources/extensions/gsd/preferences-types.ts +16 -0
  271. package/src/resources/extensions/gsd/preferences.ts +173 -28
  272. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
  273. package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
  274. package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
  275. package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
  276. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
  277. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
  278. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  279. package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
  280. package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
  281. package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
  282. package/src/resources/extensions/gsd/question-transport.ts +138 -0
  283. package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
  284. package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
  285. package/src/resources/extensions/gsd/state.ts +15 -5
  286. package/src/resources/extensions/gsd/templates/plan.md +7 -0
  287. package/src/resources/extensions/gsd/templates/project.md +1 -0
  288. package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
  289. package/src/resources/extensions/gsd/templates/uat.md +5 -1
  290. package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
  291. package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
  292. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
  293. package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
  294. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
  295. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
  296. package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
  297. package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
  298. package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
  299. package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
  300. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
  301. package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
  302. package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
  303. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
  304. package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
  305. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
  306. package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
  307. package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
  308. package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
  309. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
  310. package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
  311. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
  312. package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
  313. package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
  314. package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
  315. package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
  316. package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
  317. package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
  318. package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
  319. package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
  320. package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
  321. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
  322. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
  323. package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
  324. package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
  325. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
  326. package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
  327. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
  328. package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
  329. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
  330. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
  331. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
  332. package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
  333. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
  334. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
  335. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
  336. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
  337. package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
  338. package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
  339. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
  340. package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
  341. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
  342. package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
  343. package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
  344. package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
  345. package/src/resources/extensions/gsd/tool-contract.ts +86 -8
  346. package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
  347. package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
  348. package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
  349. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
  350. package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
  351. package/src/resources/extensions/gsd/uat-policy.ts +19 -10
  352. package/src/resources/extensions/gsd/uat-run.ts +10 -14
  353. package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
  354. package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
  355. package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
  356. package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
  357. package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
  358. package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
  359. package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
  360. package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
  361. package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
  362. package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
  363. package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
  364. package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
  365. package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
  366. package/src/resources/extensions/shared/interview-ui.ts +15 -2
  367. package/src/resources/shared/claude-runtime-floor.ts +248 -0
  368. package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
  369. package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
  370. package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
  371. package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
  372. package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
  373. package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
  374. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
  375. /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
@@ -9,6 +9,7 @@ import { deriveState } from "./state.js";
9
9
  import { gsdProjectionRoot, gsdRoot } from "./paths.js";
10
10
  import { nativeBranchList, nativeDetectMainBranch, nativeBranchListMerged, nativeBranchDelete, nativeForEachRef, nativeUpdateRef } from "./native-git-bridge.js";
11
11
  import { logWarning } from "./workflow-logger.js";
12
+ import { backupWorkflowDatabaseSnapshot, refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
12
13
  export async function handleCleanupBranches(ctx, basePath) {
13
14
  let branches;
14
15
  try {
@@ -511,7 +512,7 @@ async function confirmRecover(ctx, args, markdown, beforeDb, dataLoss) {
511
512
  * Prints counts of recovered items and the resulting project phase.
512
513
  */
513
514
  export async function handleRecover(ctx, basePath, args = "") {
514
- const { isDbAvailable: dbAvailable, clearEngineHierarchy, transaction: dbTransaction, backupDatabaseSnapshot } = await import("./gsd-db.js");
515
+ const { isDbAvailable: dbAvailable, clearEngineHierarchy, transaction: dbTransaction } = await import("./gsd-db.js");
515
516
  const { migrateHierarchyToDb } = await import("./md-importer.js");
516
517
  const { invalidateStateCache } = await import("./state.js");
517
518
  const { countDbHierarchy, countMarkdownHierarchy, recoverWouldDeleteDbRows } = await import("./migration-auto-check.js");
@@ -531,7 +532,7 @@ export async function handleRecover(ctx, basePath, args = "") {
531
532
  return;
532
533
  try {
533
534
  // 0. Snapshot the DB before the destructive clear so recover is reversible.
534
- const backupPath = backupDatabaseSnapshot("pre-recover");
535
+ const backupPath = backupWorkflowDatabaseSnapshot("pre-recover");
535
536
  // 1. Delete + re-populate inside a single transaction for atomicity.
536
537
  // clearEngineHierarchy() uses transaction() internally but transaction()
537
538
  // is re-entrant, so wrapping in dbTransaction() keeps the whole
@@ -655,6 +656,49 @@ function parseRebuildTarget(args) {
655
656
  return "database";
656
657
  return "usage";
657
658
  }
659
+ /**
660
+ * Re-render markdown planning projections from the authoritative DB.
661
+ *
662
+ * Quarantines open-unit SUMMARY files that contradict DB status before
663
+ * rendering. Safe to call after milestone merge/transition or during startup
664
+ * self-heal when the DB holds rows markdown lacks.
665
+ */
666
+ export async function rebuildMarkdownProjectionsFromDb(basePath) {
667
+ const { deleteArtifactByPath } = await import("./gsd-db.js");
668
+ const { detectArtifactDbDrift } = await import("./state-reconciliation/drift/artifact-db.js");
669
+ const { renderAllFromDb } = await import("./markdown-renderer.js");
670
+ const { invalidateStateCache } = await import("./state.js");
671
+ invalidateStateCache();
672
+ refreshWorkflowDatabaseFromDisk();
673
+ const state = await deriveState(basePath);
674
+ const drifts = detectArtifactDbDrift(state, { basePath, state });
675
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
676
+ const quarantined = [];
677
+ const seen = new Set();
678
+ for (const drift of drifts) {
679
+ if (drift.kind !== "artifact-db-status-divergence")
680
+ continue;
681
+ if (drift.artifactType !== "SUMMARY" || !drift.artifactPath)
682
+ continue;
683
+ const absPath = resolveDiskArtifactPath(basePath, drift.artifactPath);
684
+ if (seen.has(absPath) || !existsSync(absPath))
685
+ continue;
686
+ seen.add(absPath);
687
+ const artifactDbPath = artifactPathForDb(basePath, absPath);
688
+ const target = quarantineProjectionFile(basePath, absPath, stamp);
689
+ deleteArtifactByPath(artifactDbPath);
690
+ quarantined.push(target);
691
+ }
692
+ const rendered = await renderAllFromDb(basePath);
693
+ invalidateStateCache();
694
+ return {
695
+ rendered: rendered.rendered,
696
+ skipped: rendered.skipped,
697
+ errors: rendered.errors,
698
+ quarantined: quarantined.length,
699
+ quarantinedPaths: quarantined,
700
+ };
701
+ }
658
702
  /**
659
703
  * `gsd rebuild markdown` — Re-render markdown projections from the authoritative DB.
660
704
  *
@@ -663,10 +707,7 @@ function parseRebuildTarget(args) {
663
707
  * under `.gsd/quarantine/projections/` before DB projections are rendered.
664
708
  */
665
709
  export async function handleRebuild(ctx, basePath, args = "") {
666
- const { isDbAvailable: dbAvailable, deleteArtifactByPath } = await import("./gsd-db.js");
667
- const { detectArtifactDbDrift } = await import("./state-reconciliation/drift/artifact-db.js");
668
- const { renderAllFromDb } = await import("./markdown-renderer.js");
669
- const { invalidateStateCache } = await import("./state.js");
710
+ const { isDbAvailable: dbAvailable } = await import("./gsd-db.js");
670
711
  const target = parseRebuildTarget(args);
671
712
  if (target === "usage") {
672
713
  ctx.ui.notify([
@@ -690,53 +731,32 @@ export async function handleRebuild(ctx, basePath, args = "") {
690
731
  return;
691
732
  }
692
733
  try {
693
- invalidateStateCache();
694
- const state = await deriveState(basePath);
695
- const drifts = detectArtifactDbDrift(state, { basePath, state });
696
- const stamp = new Date().toISOString().replace(/[:.]/g, "-");
697
- const quarantined = [];
698
- const seen = new Set();
699
- for (const drift of drifts) {
700
- if (drift.kind !== "artifact-db-status-divergence")
701
- continue;
702
- if (drift.artifactType !== "SUMMARY" || !drift.artifactPath)
703
- continue;
704
- const absPath = resolveDiskArtifactPath(basePath, drift.artifactPath);
705
- if (seen.has(absPath) || !existsSync(absPath))
706
- continue;
707
- seen.add(absPath);
708
- const artifactDbPath = artifactPathForDb(basePath, absPath);
709
- const target = quarantineProjectionFile(basePath, absPath, stamp);
710
- deleteArtifactByPath(artifactDbPath);
711
- quarantined.push(target);
712
- }
713
- const rendered = await renderAllFromDb(basePath);
714
- invalidateStateCache();
734
+ const result = await rebuildMarkdownProjectionsFromDb(basePath);
715
735
  const lines = [
716
736
  "gsd rebuild markdown: rebuilt markdown projections from the canonical DB",
717
- ` Rendered: ${rendered.rendered}`,
718
- ` Skipped: ${rendered.skipped}`,
719
- ` Quarantined: ${quarantined.length}`,
737
+ ` Rendered: ${result.rendered}`,
738
+ ` Skipped: ${result.skipped}`,
739
+ ` Quarantined: ${result.quarantined}`,
720
740
  ];
721
- if (rendered.errors.length > 0) {
722
- lines.push(` Errors: ${rendered.errors.length}`);
723
- for (const err of rendered.errors.slice(0, 5)) {
741
+ if (result.errors.length > 0) {
742
+ lines.push(` Errors: ${result.errors.length}`);
743
+ for (const err of result.errors.slice(0, 5)) {
724
744
  lines.push(` - ${err}`);
725
745
  }
726
- if (rendered.errors.length > 5) {
727
- lines.push(` - ${rendered.errors.length - 5} more`);
746
+ if (result.errors.length > 5) {
747
+ lines.push(` - ${result.errors.length - 5} more`);
728
748
  }
729
749
  }
730
- if (quarantined.length > 0) {
750
+ if (result.quarantined > 0) {
731
751
  lines.push("", " Quarantine:");
732
- for (const target of quarantined.slice(0, 5)) {
752
+ for (const target of result.quarantinedPaths.slice(0, 5)) {
733
753
  lines.push(` - ${target}`);
734
754
  }
735
- if (quarantined.length > 5) {
736
- lines.push(` - ${quarantined.length - 5} more`);
755
+ if (result.quarantined > 5) {
756
+ lines.push(` - ${result.quarantined - 5} more`);
737
757
  }
738
758
  }
739
- ctx.ui.notify(lines.join("\n"), rendered.errors.length > 0 ? "warning" : "success");
759
+ ctx.ui.notify(lines.join("\n"), result.errors.length > 0 ? "warning" : "success");
740
760
  }
741
761
  catch (err) {
742
762
  const msg = err instanceof Error ? err.message : String(err);
@@ -10,7 +10,7 @@ import { nativeGetCurrentBranch, nativeDetectMainBranch } from "./native-git-bri
10
10
  import { formatDuration } from "../shared/format-utils.js";
11
11
  import { parseEvalReviewFrontmatter } from "./eval-review-schema.js";
12
12
  import { currentDirectoryRoot } from "./commands/context.js";
13
- import { buildPrEvidence } from "./pr-evidence.js";
13
+ import { buildPullRequestEvidence } from "./pull-request-process.js";
14
14
  function git(basePath, args) {
15
15
  return execFileSync("git", args, { cwd: basePath, encoding: "utf-8" }).trim();
16
16
  }
@@ -140,7 +140,7 @@ function generatePRContent(basePath, milestoneId, milestoneTitle) {
140
140
  metrics.push(`**Models:** ${byModel.map((m) => `${m.model} (${m.units} units)`).join(", ")}`);
141
141
  }
142
142
  }
143
- return buildPrEvidence({
143
+ return buildPullRequestEvidence({
144
144
  milestoneId,
145
145
  milestoneTitle,
146
146
  changeType: "feat",
@@ -1,11 +1,14 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: Handles manual milestone validation verdict overrides.
3
3
  import { loadFile } from "./files.js";
4
- import { resolveMilestoneFile } from "./paths.js";
4
+ import { gsdProjectionRoot, resolveMilestoneFile } from "./paths.js";
5
+ import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
6
+ import { join } from "node:path";
5
7
  import { deriveState } from "./state.js";
6
8
  import { executeValidateMilestone } from "./tools/workflow-tool-executors.js";
7
9
  import { ensureDbOpen } from "./bootstrap/dynamic-tools.js";
8
10
  import { getLatestAssessmentByScope } from "./gsd-db.js";
11
+ import { checkpointWorkflowDatabase } from "./db-workspace.js";
9
12
  import { VALIDATION_VERDICTS, extractVerdict, isValidMilestoneVerdict, } from "./verdict-parser.js";
10
13
  const USAGE = 'Usage: /gsd verdict <pass|needs-attention|needs-remediation> [--milestone Mxxx] [--rationale "..."]';
11
14
  function tokenize(raw) {
@@ -86,8 +89,14 @@ export function parseValidationFile(content) {
86
89
  };
87
90
  }
88
91
  async function loadExistingValidation(basePath, milestoneId) {
92
+ const canonicalBase = resolveCanonicalMilestoneRoot(basePath, milestoneId);
93
+ const canonicalValidationPath = join(gsdProjectionRoot(canonicalBase), "milestones", milestoneId, `${milestoneId}-VALIDATION.md`);
94
+ const canonicalContent = await loadFile(canonicalValidationPath);
95
+ if (canonicalContent) {
96
+ return { content: canonicalContent, source: canonicalValidationPath };
97
+ }
89
98
  const validationPath = resolveMilestoneFile(basePath, milestoneId, "VALIDATION");
90
- if (validationPath) {
99
+ if (validationPath && validationPath !== canonicalValidationPath) {
91
100
  const content = await loadFile(validationPath);
92
101
  if (content)
93
102
  return { content, source: validationPath };
@@ -157,6 +166,7 @@ export async function handleVerdict(rawArgs, ctx, basePath) {
157
166
  ctx.ui.notify(msg, "error");
158
167
  return;
159
168
  }
169
+ checkpointWorkflowDatabase();
160
170
  const prevVerdict = current.verdict ?? "unknown";
161
171
  const effectiveVerdict = extractEffectiveVerdict(result.details, parsed.verdict);
162
172
  if (effectiveVerdict !== parsed.verdict) {
@@ -0,0 +1,103 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Workspace-facing Interface for opening and maintaining the workflow database.
3
+ import { existsSync } from "node:fs";
4
+ import { dirname } from "node:path";
5
+ import { backupDatabaseSnapshot, checkpointDatabase, closeAllDatabases, closeDatabase, closeDatabaseByWorkspace, getDbPath, getDbStatus, getDbProvider, isDbAvailable, openDatabase, openDatabaseByScope, openDatabaseByWorkspace, refreshOpenDatabaseFromDisk, vacuumDatabase, wasDbOpenAttempted, } from "./gsd-db.js";
6
+ import { resolveGsdPathContract } from "./paths.js";
7
+ import { setLogBasePath } from "./workflow-logger.js";
8
+ export function resolveWorkflowDatabaseLocation(basePath) {
9
+ const contract = resolveGsdPathContract(basePath);
10
+ return {
11
+ projectRoot: dirname(dirname(contract.projectDb)),
12
+ projectGsd: contract.projectGsd,
13
+ projectDb: contract.projectDb,
14
+ };
15
+ }
16
+ /**
17
+ * Resolve the correct DB path for the current working directory.
18
+ * If `basePath` is inside a `.gsd/worktrees/<MID>/` directory, returns
19
+ * the project root's `.gsd/gsd.db` (shared WAL — R012). Otherwise returns
20
+ * `<basePath>/.gsd/gsd.db`.
21
+ */
22
+ export function resolveProjectRootDbPath(basePath) {
23
+ return resolveWorkflowDatabaseLocation(basePath).projectDb;
24
+ }
25
+ export function openWorkflowDatabase(basePath) {
26
+ const location = resolveWorkflowDatabaseLocation(basePath);
27
+ if (!existsSync(location.projectGsd)) {
28
+ return { ok: false, reason: "missing-gsd-dir", location };
29
+ }
30
+ const existed = existsSync(location.projectDb);
31
+ try {
32
+ const opened = openDatabase(location.projectDb);
33
+ if (!opened) {
34
+ return { ok: false, reason: "open-failed", location };
35
+ }
36
+ setLogBasePath(location.projectRoot);
37
+ return {
38
+ ok: true,
39
+ reason: existed ? "opened-existing" : "created-empty",
40
+ location,
41
+ };
42
+ }
43
+ catch (err) {
44
+ return {
45
+ ok: false,
46
+ reason: "open-failed",
47
+ location,
48
+ error: err instanceof Error ? err : new Error(String(err)),
49
+ };
50
+ }
51
+ }
52
+ export function openExistingWorkflowDatabase(basePath) {
53
+ const location = resolveWorkflowDatabaseLocation(basePath);
54
+ if (!existsSync(location.projectDb)) {
55
+ return { ok: false, reason: "missing-database", location };
56
+ }
57
+ return openWorkflowDatabase(basePath);
58
+ }
59
+ export function openWorkflowDatabasePath(path) {
60
+ return openDatabase(path);
61
+ }
62
+ export function openWorkflowDatabaseByWorkspace(workspace) {
63
+ return openDatabaseByWorkspace(workspace);
64
+ }
65
+ export function openWorkflowDatabaseByScope(scope) {
66
+ return openDatabaseByScope(scope);
67
+ }
68
+ export function closeWorkflowDatabase() {
69
+ closeDatabase();
70
+ }
71
+ export function closeWorkflowDatabaseByWorkspace(workspace) {
72
+ closeDatabaseByWorkspace(workspace);
73
+ }
74
+ export function closeAllWorkflowDatabases() {
75
+ closeAllDatabases();
76
+ }
77
+ export function isWorkflowDatabaseOpen() {
78
+ return isDbAvailable();
79
+ }
80
+ export function wasWorkflowDatabaseOpenAttempted() {
81
+ return wasDbOpenAttempted();
82
+ }
83
+ export function getWorkflowDatabaseStatus() {
84
+ return getDbStatus();
85
+ }
86
+ export function getWorkflowDatabaseProvider() {
87
+ return getDbProvider();
88
+ }
89
+ export function getWorkflowDatabasePath() {
90
+ return getDbPath();
91
+ }
92
+ export function refreshWorkflowDatabaseFromDisk() {
93
+ return refreshOpenDatabaseFromDisk();
94
+ }
95
+ export function checkpointWorkflowDatabase() {
96
+ checkpointDatabase();
97
+ }
98
+ export function vacuumWorkflowDatabase() {
99
+ vacuumDatabase();
100
+ }
101
+ export function backupWorkflowDatabaseSnapshot(label) {
102
+ return backupDatabaseSnapshot(label);
103
+ }
@@ -34,6 +34,7 @@
34
34
  // Adding a `unitType` mapping (or a future `unitTypes: string[]`) to an
35
35
  // existing entry is the place to lift any of these out of default-deny
36
36
  // when the analysis has been done.
37
+ import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
37
38
  const POLICY = {
38
39
  gsd_plan_slice: {
39
40
  toolName: "gsd_plan_slice",
@@ -96,17 +97,8 @@ const POLICY = {
96
97
  rationale: "plan-slice prompt explicitly forbids calling gsd_plan_task separately; per-task granularity multiplies manifest writes and projection re-renders with no payoff.",
97
98
  },
98
99
  };
99
- // Alias map keyed on the secondary name; resolves to the canonical entry above.
100
- // Sourced from packages/mcp-server/src/workflow-tools.ts alias registrations
101
- // (gsd_milestone_validate, gsd_roadmap_reassess, gsd_slice_replan, gsd_task_plan).
102
- const ALIASES = {
103
- gsd_milestone_validate: "gsd_validate_milestone",
104
- gsd_roadmap_reassess: "gsd_reassess_roadmap",
105
- gsd_slice_replan: "gsd_replan_slice",
106
- gsd_task_plan: "gsd_plan_task",
107
- };
108
100
  function resolveCanonical(name) {
109
- return ALIASES[name] ?? name;
101
+ return canonicalWorkflowSurfaceToolName(name);
110
102
  }
111
103
  export function getDelegationVerdict(toolName) {
112
104
  return POLICY[resolveCanonical(toolName)] ?? null;
@@ -0,0 +1,218 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Owns the guided-discuss to auto-mode handoff.
3
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { startAutoDetached } from "./auto.js";
6
+ import { extractDepthVerificationMilestoneId, getPendingGate } from "./bootstrap/write-gate.js";
7
+ import { getMilestone, insertMilestone, isDbAvailable } from "./gsd-db.js";
8
+ import { assessMilestoneHandoffReadiness, formatAcceptedDiscussHandoffMessage, } from "./milestone-readiness.js";
9
+ import { gsdRoot, resolveGsdRootFile, resolveMilestoneFile } from "./paths.js";
10
+ import { _getPendingAutoStart, deletePendingAutoStart } from "./pending-auto-start.js";
11
+ import { logWarning } from "./workflow-logger.js";
12
+ import { readManifest } from "./workflow-manifest.js";
13
+ // Cap failed in-flight DB row repair attempts before escalating to the user.
14
+ const MAX_DB_ROW_RECOVERIES = 3;
15
+ const PROJECT_DEPTH_GATE_IDS = new Set([
16
+ "depth_verification_project_confirm",
17
+ "depth_verification_requirements_confirm",
18
+ "depth_verification_research_decision_confirm",
19
+ ]);
20
+ export function scheduleAutoStartAfterIdle(ctx, pi, basePath, verboseMode, options, launch = startAutoDetached) {
21
+ const waitForIdle = typeof ctx.waitForIdle === "function"
22
+ ? ctx.waitForIdle.bind(ctx)
23
+ : async () => { };
24
+ void waitForIdle()
25
+ .then(() => {
26
+ setTimeout(() => launch(ctx, pi, basePath, verboseMode, options), 0);
27
+ })
28
+ .catch((err) => {
29
+ const message = err instanceof Error ? err.message : String(err);
30
+ ctx.ui.notify(`Auto-start failed while waiting for the prior turn to settle: ${message}`, "error");
31
+ logWarning("guided", `auto-start idle wait failed: ${message}`);
32
+ });
33
+ }
34
+ function manifestContainsMilestone(basePath, milestoneId) {
35
+ try {
36
+ const manifest = readManifest(basePath);
37
+ return (Array.isArray(manifest?.milestones) &&
38
+ manifest.milestones.some(m => m.id === milestoneId));
39
+ }
40
+ catch (e) {
41
+ logWarning("guided", `R3b: failed to read state manifest: ${e.message}`);
42
+ return false;
43
+ }
44
+ }
45
+ function notifyDbRowRecoveryFailed(entry) {
46
+ entry.ctx.ui.notify(`Milestone ${entry.milestoneId}: DB row recovery failed ${entry.r3bRecoveryCount} times. ` +
47
+ `Re-run /gsd to reset the recovery counter, or run /gsd-debug to diagnose without resetting.`, "error");
48
+ }
49
+ function noteDbRowRecoveryMiss(entry) {
50
+ entry.r3bRecoveryCount += 1;
51
+ if (entry.r3bRecoveryCount >= MAX_DB_ROW_RECOVERIES) {
52
+ notifyDbRowRecoveryFailed(entry);
53
+ }
54
+ }
55
+ function ensureMilestoneRowForAcceptedHandoff(entry, contextFile) {
56
+ if (!isDbAvailable())
57
+ return true;
58
+ const { basePath, milestoneId } = entry;
59
+ const milestoneRow = getMilestone(milestoneId);
60
+ if (milestoneRow)
61
+ return true;
62
+ if (manifestContainsMilestone(basePath, milestoneId)) {
63
+ logWarning("guided", `R3b: getMilestone(${milestoneId}) returned null but manifest has the row — treating as stale read`);
64
+ return true;
65
+ }
66
+ if (!contextFile) {
67
+ entry.ctx.ui.notify(`Milestone ${milestoneId}: discuss artifacts on disk but no DB row exists. ` +
68
+ `PROJECT.md may have failed to register milestones. ` +
69
+ `Re-save PROJECT.md with canonical "- [ ] M001: Title — One-liner" lines, ` +
70
+ `then re-run /gsd to recover.`, "error");
71
+ return false;
72
+ }
73
+ if (entry.r3bRecoveryCount >= MAX_DB_ROW_RECOVERIES) {
74
+ logWarning("guided", `R3b: milestone ${milestoneId} DB-row recovery limit reached ` +
75
+ `(${entry.r3bRecoveryCount}/${MAX_DB_ROW_RECOVERIES}); user already notified`);
76
+ return false;
77
+ }
78
+ logWarning("guided", `R3b: ${milestoneId} has CONTEXT.md but no DB row — inserting placeholder "queued" row ` +
79
+ `(attempt ${entry.r3bRecoveryCount + 1}/${MAX_DB_ROW_RECOVERIES})`);
80
+ try {
81
+ insertMilestone({ id: milestoneId, title: milestoneId, status: "queued" });
82
+ }
83
+ catch (e) {
84
+ logWarning("guided", `R3b: insertMilestone failed: ${e.message}`);
85
+ }
86
+ if (getMilestone(milestoneId))
87
+ return true;
88
+ noteDbRowRecoveryMiss(entry);
89
+ return false;
90
+ }
91
+ /**
92
+ * Extract milestone IDs from PROJECT.md milestone sequence table.
93
+ * Looks for rows like "| M001 | Name | Status |" and extracts the ID column.
94
+ */
95
+ function parseMilestoneSequenceFromProject(content) {
96
+ const ids = [];
97
+ const lines = content.split(/\r?\n/);
98
+ for (const line of lines) {
99
+ const match = line.match(/^\|\s*(M\d{3}[A-Z0-9-]*)\s*\|/);
100
+ if (match)
101
+ ids.push(match[1]);
102
+ }
103
+ return ids;
104
+ }
105
+ function hasBlockingDepthGate(entry) {
106
+ const basePathForGate = entry.scope.workspace.projectRoot;
107
+ const pendingGateId = getPendingGate(basePathForGate);
108
+ if (!pendingGateId)
109
+ return false;
110
+ const pendingMilestoneId = extractDepthVerificationMilestoneId(pendingGateId);
111
+ return pendingMilestoneId === entry.milestoneId || PROJECT_DEPTH_GATE_IDS.has(pendingGateId);
112
+ }
113
+ function discussionManifestPath(entry) {
114
+ return join(entry.scope.workspace.contract.projectGsd, "DISCUSSION-MANIFEST.json");
115
+ }
116
+ function warnForMissingProjectMilestones(entry) {
117
+ const { ctx, basePath } = entry;
118
+ const projectFile = resolveGsdRootFile(basePath, "PROJECT");
119
+ if (!projectFile)
120
+ return [];
121
+ try {
122
+ const projectContent = readFileSync(projectFile, "utf-8");
123
+ const projectIds = parseMilestoneSequenceFromProject(projectContent);
124
+ if (projectIds.length <= 1)
125
+ return projectIds;
126
+ const missing = projectIds.filter(id => {
127
+ const hasContext = !!resolveMilestoneFile(basePath, id, "CONTEXT");
128
+ const hasDraft = !!resolveMilestoneFile(basePath, id, "CONTEXT-DRAFT");
129
+ const hasDir = existsSync(join(gsdRoot(basePath), "milestones", id));
130
+ return !hasContext && !hasDraft && !hasDir;
131
+ });
132
+ if (missing.length > 0) {
133
+ ctx.ui.notify(`Multi-milestone validation: ${missing.join(", ")} not found in filesystem. ` +
134
+ `Discussion may not have completed all readiness gates.`, "warning");
135
+ }
136
+ return projectIds;
137
+ }
138
+ catch (e) {
139
+ logWarning("guided", `PROJECT.md parsing failed: ${e.message}`);
140
+ return [];
141
+ }
142
+ }
143
+ function discussionManifestIsComplete(entry, projectIds) {
144
+ const manifestPath = discussionManifestPath(entry);
145
+ if (!existsSync(manifestPath))
146
+ return true;
147
+ try {
148
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
149
+ const total = typeof manifest.total === "number" ? manifest.total : 0;
150
+ const completed = typeof manifest.gates_completed === "number" ? manifest.gates_completed : 0;
151
+ if (total > 1 && completed < total) {
152
+ return false;
153
+ }
154
+ if (projectIds.length > 0) {
155
+ const manifestIds = Object.keys(manifest.milestones ?? {});
156
+ const untracked = projectIds.filter(id => !manifestIds.includes(id));
157
+ if (untracked.length > 0) {
158
+ entry.ctx.ui.notify(`Discussion manifest missing gates for: ${untracked.join(", ")}`, "warning");
159
+ }
160
+ }
161
+ }
162
+ catch (e) {
163
+ logWarning("guided", `discussion manifest verification failed: ${e.message}`);
164
+ }
165
+ return true;
166
+ }
167
+ function cleanupAcceptedHandoffArtifacts(entry) {
168
+ const { basePath, milestoneId } = entry;
169
+ try {
170
+ const draftFile = resolveMilestoneFile(basePath, milestoneId, "CONTEXT-DRAFT");
171
+ if (draftFile)
172
+ unlinkSync(draftFile);
173
+ }
174
+ catch (e) {
175
+ logWarning("guided", `CONTEXT-DRAFT.md unlink failed: ${e.message}`);
176
+ }
177
+ const manifestPath = discussionManifestPath(entry);
178
+ if (existsSync(manifestPath)) {
179
+ try {
180
+ unlinkSync(manifestPath);
181
+ }
182
+ catch (e) {
183
+ logWarning("guided", `manifest unlink failed: ${e.message}`);
184
+ }
185
+ }
186
+ }
187
+ /** Called from agent_end to check if auto-mode should start after discuss. */
188
+ export function checkAutoStartAfterDiscuss(lookupBasePath) {
189
+ const entry = _getPendingAutoStart(lookupBasePath);
190
+ if (!entry)
191
+ return false;
192
+ const { ctx, pi, basePath, milestoneId, step } = entry;
193
+ const contextFilePath = entry.scope.contextFile();
194
+ const roadmapFilePath = entry.scope.roadmapFile();
195
+ const contextFile = existsSync(contextFilePath) ? contextFilePath : null;
196
+ const roadmapFile = existsSync(roadmapFilePath) ? roadmapFilePath : null;
197
+ if (!contextFile && !roadmapFile)
198
+ return false;
199
+ if (hasBlockingDepthGate(entry))
200
+ return false;
201
+ if (!ensureMilestoneRowForAcceptedHandoff(entry, contextFile))
202
+ return false;
203
+ const projectIds = warnForMissingProjectMilestones(entry);
204
+ if (!discussionManifestIsComplete(entry, projectIds))
205
+ return false;
206
+ cleanupAcceptedHandoffArtifacts(entry);
207
+ deletePendingAutoStart(basePath);
208
+ const readiness = assessMilestoneHandoffReadiness({
209
+ milestoneId,
210
+ contextFile,
211
+ roadmapFile,
212
+ });
213
+ ctx.ui.notify(formatAcceptedDiscussHandoffMessage(milestoneId, readiness), "success");
214
+ if (entry.startAuto !== false) {
215
+ scheduleAutoStartAfterIdle(ctx, pi, basePath, false, { step: step ?? true });
216
+ }
217
+ return true;
218
+ }
@@ -73,6 +73,15 @@ These are **separate concerns**:
73
73
 
74
74
  Setting `prefer_skills: []` does **not** disable skill discovery — it just means you have no preference overrides. Use `skill_discovery: off` to disable discovery entirely.
75
75
 
76
+ ### Parse & Validation Diagnostics
77
+
78
+ Preference loading never throws. When a file is malformed or contains invalid settings, GSD falls back to safe defaults but attaches structured diagnostics (see `collectPreferenceDiagnostics()` in `preferences-diagnostics.ts`) so the problem is reported instead of silently ignored:
79
+
80
+ - **Parse failures** (missing closing `---` delimiter, YAML syntax error, or an unrecognized file format) cause the whole file to be ignored. Loading continues to the next candidate — a valid global or legacy preferences file is still used, and a malformed project file never becomes the effective wrapper or blocks fallback.
81
+ - **Validation problems** (unknown keys, type mismatches) are sanitized or dropped per-field; the remaining valid settings in the file still apply.
82
+
83
+ Diagnostics record the file path, scope (global/project), severity (error/warning), kind (parse/validation), and — for YAML parse errors — the line and column. They surface through session-start notifications, `/gsd doctor`, and auto-mode preflight, with each surface deduping repeated diagnostics.
84
+
76
85
  ---
77
86
 
78
87
  ## Field Guide
@@ -2,11 +2,13 @@ import { existsSync, mkdirSync, lstatSync, readdirSync, readFileSync } from "nod
2
2
  import { join } from "node:path";
3
3
  import { loadFile, parseSummary, saveFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
4
4
  import { parseRoadmap as parseLegacyRoadmap, parsePlan as parseLegacyPlan } from "./parsers-legacy.js";
5
- import { isDbAvailable, openDatabase, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
6
- import { resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTasksDir, milestonesDir, gsdRoot, relMilestoneFile, relSliceFile, relTaskFile, relSlicePath, relGsdRootFile, resolveGsdRootFile, relMilestonePath, resolveGsdPathContract } from "./paths.js";
5
+ import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
6
+ import { openExistingWorkflowDatabase } from "./db-workspace.js";
7
+ import { resolveMilestoneFile, resolveMilestonePath, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTasksDir, milestonesDir, gsdRoot, relMilestoneFile, relSliceFile, relTaskFile, relSlicePath, relGsdRootFile, resolveGsdRootFile, relMilestonePath } from "./paths.js";
7
8
  import { deriveState, isMilestoneComplete } from "./state.js";
8
9
  import { invalidateAllCaches } from "./cache.js";
9
10
  import { loadEffectiveGSDPreferences } from "./preferences.js";
11
+ import { collectPreferenceDiagnostics, formatPreferenceDiagnosticDetail } from "./preferences-diagnostics.js";
10
12
  import { isClosedStatus } from "./status-guards.js";
11
13
  import { GLOBAL_STATE_CODES } from "./doctor-types.js";
12
14
  import { checkGitHealth, checkRuntimeHealth, checkGlobalHealth, checkEngineHealth } from "./doctor-checks.js";
@@ -286,13 +288,7 @@ export async function runGSDDoctor(basePath, options) {
286
288
  // CLI doctor can run before any tool handler has opened the DB. Runtime
287
289
  // health checks need the existing project DB to surface DB-backed crash
288
290
  // locks, paused sessions, and coordination rows.
289
- const dbPath = resolveGsdPathContract(basePath).projectDb;
290
- if (existsSync(dbPath)) {
291
- try {
292
- openDatabase(dbPath);
293
- }
294
- catch { /* surfaced later as db_unavailable */ }
295
- }
291
+ openExistingWorkflowDatabase(basePath);
296
292
  // Issue codes that represent completion state transitions — creating summary
297
293
  // stubs, marking slices/milestones done in the roadmap. These belong to the
298
294
  // dispatch lifecycle (complete-slice, complete-milestone units), not to
@@ -307,6 +303,17 @@ export async function runGSDDoctor(basePath, options) {
307
303
  return true;
308
304
  };
309
305
  const prefs = loadEffectiveGSDPreferences(basePath);
306
+ for (const diagnostic of collectPreferenceDiagnostics(basePath)) {
307
+ issues.push({
308
+ severity: diagnostic.severity,
309
+ code: "invalid_preferences",
310
+ scope: "project",
311
+ unitId: "project",
312
+ message: `GSD preferences ${diagnostic.kind}: ${formatPreferenceDiagnosticDetail(diagnostic)}`,
313
+ file: diagnostic.path,
314
+ fixable: false,
315
+ });
316
+ }
310
317
  if (prefs) {
311
318
  const prefIssues = validatePreferenceShape(prefs.preferences);
312
319
  for (const issue of prefIssues) {
@@ -32,7 +32,7 @@ const AFFORDABILITY_RE = /requires more credits|can only afford|insufficient cre
32
32
  // are emitted by SDK/harness transports for mid-stream disconnects.
33
33
  // These indicate transient network-level interruptions.
34
34
  // See: https://github.com/open-gsd/gsd-pi/issues/4558
35
- const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|web ?socket|fetch failed|connection.*reset|dns|unexpected eof|stream idle timeout|partial response received/i;
35
+ const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|web ?socket|fetch failed|connection.*reset|dns|unexpected eof|stream idle timeout|partial response received|stream ended without finish_reason/i;
36
36
  // Context overflow errors (context window/length exceeded) should be treated as server-class
37
37
  // transient errors so auto-mode can retry with reduced budget or fall back to a larger-context model.
38
38
  // See: https://github.com/open-gsd/gsd-pi/issues/4528
@@ -61,7 +61,22 @@ export function gitDiffCheckFailures(basePath) {
61
61
  .filter(Boolean)
62
62
  .join("\n")
63
63
  .trim();
64
- failures.push(output || `git diff --check ${args.join(" ")} failed`);
64
+ // git diff --check exits non-zero for both whitespace errors and leftover
65
+ // conflict markers. Only conflict markers block the gate — whitespace errors
66
+ // in staged files (common in auto-generated code) must not be misread as an
67
+ // unresolved merge conflict. Filter to lines git explicitly labels as
68
+ // "leftover conflict marker".
69
+ if (!output) {
70
+ failures.push(`git diff --check ${args.join(" ")} failed`);
71
+ continue;
72
+ }
73
+ const conflictMarkerLines = output
74
+ .split("\n")
75
+ .filter((line) => /leftover conflict marker/i.test(line))
76
+ .join("\n");
77
+ if (conflictMarkerLines) {
78
+ failures.push(conflictMarkerLines);
79
+ }
65
80
  }
66
81
  return failures;
67
82
  }