@opengsd/gsd-pi 1.2.0-dev.4c756166 → 1.2.0-dev.5457a158

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 (338) hide show
  1. package/dist/cli-style.d.ts +17 -0
  2. package/dist/cli-style.js +28 -0
  3. package/dist/cli.js +1 -1
  4. package/dist/headless-events.d.ts +4 -2
  5. package/dist/headless-events.js +7 -29
  6. package/dist/models-resolver.d.ts +3 -13
  7. package/dist/models-resolver.js +3 -22
  8. package/dist/resource-loader.js +2 -14
  9. package/dist/resources/.managed-resources-content-hash +1 -1
  10. package/dist/resources/extensions/bg-shell/utilities.js +5 -2
  11. package/dist/resources/extensions/claude-code-cli/models.js +9 -0
  12. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +35 -4
  13. package/dist/resources/extensions/gsd/auto/orchestrator.js +33 -4
  14. package/dist/resources/extensions/gsd/auto/phases.js +6 -1
  15. package/dist/resources/extensions/gsd/auto-post-unit.js +19 -8
  16. package/dist/resources/extensions/gsd/auto-prompts.js +3 -0
  17. package/dist/resources/extensions/gsd/auto-start.js +12 -14
  18. package/dist/resources/extensions/gsd/auto-tool-tracking.js +18 -0
  19. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +7 -16
  20. package/dist/resources/extensions/gsd/auto-worktree-repair.js +10 -2
  21. package/dist/resources/extensions/gsd/auto-worktree.js +35 -352
  22. package/dist/resources/extensions/gsd/auto.js +8 -20
  23. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -2
  24. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +9 -6
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +86 -6
  26. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +30 -4
  27. package/dist/resources/extensions/gsd/branch-patterns.js +2 -0
  28. package/dist/resources/extensions/gsd/captures.js +5 -15
  29. package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
  30. package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
  31. package/dist/resources/extensions/gsd/crash-recovery.js +4 -12
  32. package/dist/resources/extensions/gsd/db/engine.js +755 -0
  33. package/dist/resources/extensions/gsd/db/queries.js +372 -0
  34. package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
  35. package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
  36. package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
  37. package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
  38. package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
  39. package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
  40. package/dist/resources/extensions/gsd/doctor-environment.js +5 -11
  41. package/dist/resources/extensions/gsd/doctor-format.js +9 -6
  42. package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
  43. package/dist/resources/extensions/gsd/doctor-runtime-checks.js +21 -16
  44. package/dist/resources/extensions/gsd/error-classifier.js +9 -0
  45. package/dist/resources/extensions/gsd/git-service.js +1 -0
  46. package/dist/resources/extensions/gsd/gitignore.js +3 -0
  47. package/dist/resources/extensions/gsd/gsd-db.js +171 -2048
  48. package/dist/resources/extensions/gsd/guidance.js +98 -0
  49. package/dist/resources/extensions/gsd/guided-flow.js +51 -5
  50. package/dist/resources/extensions/gsd/mcp-tool-name.js +5 -13
  51. package/dist/resources/extensions/gsd/memory-consolidation-scanner.js +1 -1
  52. package/dist/resources/extensions/gsd/migrate/safety.js +20 -9
  53. package/dist/resources/extensions/gsd/migration-auto-check.js +24 -3
  54. package/dist/resources/extensions/gsd/model-cost-table.js +1 -0
  55. package/dist/resources/extensions/gsd/model-router.js +3 -0
  56. package/dist/resources/extensions/gsd/notification-store.js +11 -4
  57. package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
  58. package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +11 -7
  59. package/dist/resources/extensions/gsd/paths.js +37 -24
  60. package/dist/resources/extensions/gsd/pre-execution-checks.js +91 -3
  61. package/dist/resources/extensions/gsd/preferences-models.js +12 -46
  62. package/dist/resources/extensions/gsd/preferences.js +14 -0
  63. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  64. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  65. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  66. package/dist/resources/extensions/gsd/provider-error-guidance.js +1 -5
  67. package/dist/resources/extensions/gsd/provider-switch-observer.js +1 -1
  68. package/dist/resources/extensions/gsd/publication.js +87 -0
  69. package/dist/resources/extensions/gsd/recovery-classification.js +41 -87
  70. package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
  71. package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
  72. package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
  73. package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
  74. package/dist/resources/extensions/gsd/state.js +1 -20
  75. package/dist/resources/extensions/gsd/status-guards.js +56 -8
  76. package/dist/resources/extensions/gsd/stop-notice.js +57 -0
  77. package/dist/resources/extensions/gsd/tool-surface-readiness.js +56 -0
  78. package/dist/resources/extensions/gsd/tools/complete-slice.js +24 -43
  79. package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -8
  80. package/dist/resources/extensions/gsd/tools/plan-slice.js +12 -6
  81. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +11 -29
  82. package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
  83. package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
  84. package/dist/resources/extensions/gsd/undo.js +8 -7
  85. package/dist/resources/extensions/gsd/unit-closeout.js +138 -0
  86. package/dist/resources/extensions/gsd/unit-context-composer.js +9 -1
  87. package/dist/resources/extensions/gsd/unit-context-manifest.js +4 -27
  88. package/dist/resources/extensions/gsd/unit-registry.js +350 -0
  89. package/dist/resources/extensions/gsd/unit-tool-contracts.js +9 -182
  90. package/dist/resources/extensions/gsd/workflow-tool-surface.js +1 -1
  91. package/dist/resources/extensions/gsd/worktree-git-recovery.js +293 -0
  92. package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
  93. package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
  94. package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
  95. package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
  96. package/dist/resources/extensions/gsd/worktree-root.js +28 -6
  97. package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
  98. package/dist/resources/extensions/gsd/worktree-session-state.js +12 -11
  99. package/dist/resources/skills/gsd-browser/SKILL.md +1 -1
  100. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  101. package/dist/web/standalone/.next/BUILD_ID +1 -1
  102. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  103. package/dist/web/standalone/.next/build-manifest.json +2 -2
  104. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  105. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  106. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  108. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  114. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  116. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  122. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  123. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  124. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  125. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  126. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  127. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  128. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  129. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  130. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  131. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  132. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  133. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  134. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  135. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  136. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  137. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  138. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  139. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  140. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  141. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  142. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  143. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  144. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  145. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  146. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  147. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  148. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  149. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  150. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  151. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  152. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  153. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  154. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  155. package/dist/web/standalone/.next/server/app/index.html +1 -1
  156. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  158. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  163. package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
  164. package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
  165. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  166. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  168. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  169. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  170. package/dist/worktree-cli.js +3 -6
  171. package/dist/worktree-status-banner.js +7 -11
  172. package/package.json +1 -1
  173. package/packages/cloud-mcp-gateway/package.json +2 -2
  174. package/packages/contracts/dist/workflow.d.ts +4 -0
  175. package/packages/contracts/dist/workflow.d.ts.map +1 -1
  176. package/packages/contracts/dist/workflow.js.map +1 -1
  177. package/packages/contracts/package.json +1 -1
  178. package/packages/daemon/package.json +4 -4
  179. package/packages/gsd-agent-core/package.json +5 -5
  180. package/packages/gsd-agent-modes/package.json +7 -7
  181. package/packages/mcp-server/dist/cli.js +6 -3
  182. package/packages/mcp-server/dist/cli.js.map +1 -1
  183. package/packages/mcp-server/dist/workflow-tools.d.ts +8 -0
  184. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  185. package/packages/mcp-server/dist/workflow-tools.js +46 -21
  186. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  187. package/packages/mcp-server/package.json +3 -3
  188. package/packages/native/package.json +1 -1
  189. package/packages/pi-agent-core/package.json +1 -1
  190. package/packages/pi-ai/dist/models.generated.d.ts +294 -239
  191. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  192. package/packages/pi-ai/dist/models.generated.js +260 -256
  193. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  194. package/packages/pi-ai/package.json +1 -1
  195. package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
  196. package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
  197. package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
  198. package/packages/pi-coding-agent/package.json +7 -7
  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/bg-shell/utilities.ts +5 -2
  203. package/src/resources/extensions/claude-code-cli/models.ts +9 -0
  204. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +37 -2
  205. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +28 -0
  206. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -1
  207. package/src/resources/extensions/gsd/auto/orchestrator.ts +39 -5
  208. package/src/resources/extensions/gsd/auto/phases.ts +10 -1
  209. package/src/resources/extensions/gsd/auto-post-unit.ts +25 -7
  210. package/src/resources/extensions/gsd/auto-prompts.ts +3 -0
  211. package/src/resources/extensions/gsd/auto-start.ts +12 -15
  212. package/src/resources/extensions/gsd/auto-tool-tracking.ts +19 -0
  213. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +10 -17
  214. package/src/resources/extensions/gsd/auto-worktree-repair.ts +13 -2
  215. package/src/resources/extensions/gsd/auto-worktree.ts +41 -364
  216. package/src/resources/extensions/gsd/auto.ts +20 -24
  217. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -5
  218. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -6
  219. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +87 -6
  220. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +29 -3
  221. package/src/resources/extensions/gsd/branch-patterns.ts +3 -0
  222. package/src/resources/extensions/gsd/captures.ts +5 -16
  223. package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
  224. package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
  225. package/src/resources/extensions/gsd/crash-recovery.ts +3 -9
  226. package/src/resources/extensions/gsd/db/engine.ts +809 -0
  227. package/src/resources/extensions/gsd/db/queries.ts +453 -0
  228. package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
  229. package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
  230. package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
  231. package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
  232. package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
  233. package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
  234. package/src/resources/extensions/gsd/doctor-environment.ts +5 -13
  235. package/src/resources/extensions/gsd/doctor-format.ts +12 -7
  236. package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
  237. package/src/resources/extensions/gsd/doctor-runtime-checks.ts +22 -17
  238. package/src/resources/extensions/gsd/error-classifier.ts +11 -0
  239. package/src/resources/extensions/gsd/git-service.ts +1 -0
  240. package/src/resources/extensions/gsd/gitignore.ts +3 -0
  241. package/src/resources/extensions/gsd/gsd-db.ts +173 -2373
  242. package/src/resources/extensions/gsd/guidance.ts +139 -0
  243. package/src/resources/extensions/gsd/guided-flow.ts +50 -5
  244. package/src/resources/extensions/gsd/mcp-tool-name.ts +6 -11
  245. package/src/resources/extensions/gsd/memory-consolidation-scanner.ts +1 -1
  246. package/src/resources/extensions/gsd/migrate/safety.ts +18 -7
  247. package/src/resources/extensions/gsd/migration-auto-check.ts +28 -3
  248. package/src/resources/extensions/gsd/model-cost-table.ts +1 -0
  249. package/src/resources/extensions/gsd/model-router.ts +3 -0
  250. package/src/resources/extensions/gsd/notification-store.ts +26 -3
  251. package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
  252. package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +10 -7
  253. package/src/resources/extensions/gsd/paths.ts +42 -22
  254. package/src/resources/extensions/gsd/pre-execution-checks.ts +109 -3
  255. package/src/resources/extensions/gsd/preferences-models.ts +10 -46
  256. package/src/resources/extensions/gsd/preferences.ts +18 -0
  257. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  258. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  259. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  260. package/src/resources/extensions/gsd/provider-error-guidance.ts +4 -9
  261. package/src/resources/extensions/gsd/provider-switch-observer.ts +1 -1
  262. package/src/resources/extensions/gsd/publication.ts +122 -0
  263. package/src/resources/extensions/gsd/recovery-classification.ts +47 -88
  264. package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
  265. package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
  266. package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
  267. package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
  268. package/src/resources/extensions/gsd/state.ts +4 -21
  269. package/src/resources/extensions/gsd/status-guards.ts +59 -8
  270. package/src/resources/extensions/gsd/stop-notice.ts +75 -0
  271. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +123 -0
  272. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +3 -1
  273. package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
  274. package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
  275. package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
  276. package/src/resources/extensions/gsd/tests/checkout-branch-stash-guard.test.ts +66 -1
  277. package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +44 -0
  278. package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +8 -7
  279. package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +157 -0
  280. package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
  281. package/src/resources/extensions/gsd/tests/guidance.test.ts +125 -0
  282. package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +51 -4
  283. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +54 -1
  284. package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
  285. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +85 -1
  286. package/src/resources/extensions/gsd/tests/notification-store.test.ts +32 -0
  287. package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +193 -1
  288. package/src/resources/extensions/gsd/tests/provider-error-guidance.test.ts +3 -3
  289. package/src/resources/extensions/gsd/tests/publication.test.ts +120 -0
  290. package/src/resources/extensions/gsd/tests/recovery-classification-illegal-transition.test.ts +30 -0
  291. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +248 -1
  292. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +1 -0
  293. package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +38 -0
  294. package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
  295. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +43 -6
  296. package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +36 -0
  297. package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
  298. package/src/resources/extensions/gsd/tests/stop-notice.test.ts +70 -0
  299. package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +8 -0
  300. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +155 -0
  301. package/src/resources/extensions/gsd/tests/unit-closeout.test.ts +209 -0
  302. package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +23 -2
  303. package/src/resources/extensions/gsd/tests/unit-registry.test.ts +163 -0
  304. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -2
  305. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +2 -2
  306. package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +41 -4
  307. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +22 -1
  308. package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
  309. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
  310. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
  311. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
  312. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
  313. package/src/resources/extensions/gsd/tests/write-gate.test.ts +42 -0
  314. package/src/resources/extensions/gsd/tool-surface-readiness.ts +76 -0
  315. package/src/resources/extensions/gsd/tools/complete-slice.ts +23 -58
  316. package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -8
  317. package/src/resources/extensions/gsd/tools/plan-slice.ts +12 -6
  318. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +11 -38
  319. package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
  320. package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
  321. package/src/resources/extensions/gsd/undo.ts +9 -8
  322. package/src/resources/extensions/gsd/unit-closeout.ts +201 -0
  323. package/src/resources/extensions/gsd/unit-context-composer.ts +12 -1
  324. package/src/resources/extensions/gsd/unit-context-manifest.ts +4 -28
  325. package/src/resources/extensions/gsd/unit-registry.ts +425 -0
  326. package/src/resources/extensions/gsd/unit-tool-contracts.ts +27 -192
  327. package/src/resources/extensions/gsd/workflow-tool-surface.ts +4 -1
  328. package/src/resources/extensions/gsd/worktree-git-recovery.ts +314 -0
  329. package/src/resources/extensions/gsd/worktree-lifecycle.ts +10 -1
  330. package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
  331. package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
  332. package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
  333. package/src/resources/extensions/gsd/worktree-root.ts +29 -6
  334. package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
  335. package/src/resources/extensions/gsd/worktree-session-state.ts +11 -11
  336. package/src/resources/skills/gsd-browser/SKILL.md +1 -1
  337. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_buildManifest.js +0 -0
  338. /package/dist/web/standalone/.next/static/{DUFWcMFRH3iXh7d2fbrOF → 2p9Rv9pQflAxCBbGVI2vb}/_ssgManifest.js +0 -0
@@ -17,7 +17,7 @@ import { spawnSync } from "node:child_process";
17
17
  import { nativeScanGsdTree, type GsdTreeEntry } from "./native-parser-bridge.js";
18
18
  import { DIR_CACHE_MAX } from "./constants.js";
19
19
  import { gsdHome } from "./gsd-home.js";
20
- import { isGsdWorktreePath, resolveExternalStateProjectGsdFromWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
20
+ import { findWorktreeSegment, isGsdWorktreePath, resolveExternalStateProjectGsdFromWorktreePath, resolveWorktreeProjectRoot } from "./worktree-root.js";
21
21
 
22
22
  // ─── Directory Listing Cache ──────────────────────────────────────────────────
23
23
 
@@ -148,6 +148,39 @@ export function clearPathCache(): void {
148
148
 
149
149
  // ─── Name Builders ─────────────────────────────────────────────────────────
150
150
 
151
+ /** Directories owned by the GSD framework — metadata, never project source. */
152
+ export const FRAMEWORK_METADATA_DIRS: readonly string[] = [".gsd", ".planning", ".audits"];
153
+
154
+ /**
155
+ * Every artifact suffix used with the name builders below — the single source
156
+ * for the `<ID>-<SUFFIX>.md` naming vocabulary. Extend this list when a new
157
+ * artifact type is introduced; consumers (md-importer walking, pre-execution
158
+ * artifact detection) pick it up from here.
159
+ */
160
+ export const PLANNING_ARTIFACT_SUFFIXES: readonly string[] = [
161
+ "CONTEXT",
162
+ "CONTEXT-DRAFT",
163
+ "ROADMAP",
164
+ "PLAN",
165
+ "REPLAN",
166
+ "SUMMARY",
167
+ "RESEARCH",
168
+ "VALIDATION",
169
+ "ASSESSMENT",
170
+ "UAT",
171
+ "DISCUSSION",
172
+ "EVAL-REVIEW",
173
+ "PARKED",
174
+ "VERIFICATION-FAILED",
175
+ "CONTINUE",
176
+ ];
177
+
178
+ /** Matches a bare planning-artifact file name, e.g. "M001-CONTEXT.md", "S01-PLAN.md". */
179
+ export const PLANNING_ARTIFACT_NAME_RE = new RegExp(
180
+ `^[MST]\\d+-(${PLANNING_ARTIFACT_SUFFIXES.join("|")})\\.md$`,
181
+ "i",
182
+ );
183
+
151
184
  /**
152
185
  * Build a milestone-level file name.
153
186
  * ("M001", "CONTEXT") → "M001-CONTEXT.md"
@@ -458,29 +491,16 @@ function assertNotGlobalGsdHome(basePath: string, result: string): void {
458
491
  * When gsdRoot() is called with such a path, we must NOT walk up to the
459
492
  * project root's .gsd — each worktree manages its own .gsd state (#2594).
460
493
  *
461
- * Matches both forward-slash and platform-native separators to handle
462
- * Windows paths (path.sep = '\\') and normalized Unix paths.
494
+ * Layout matching is owned by worktree-root's findWorktreeSegment; this
495
+ * only adds the requirement that a non-empty worktree name follows the
496
+ * marker (the worktrees container dir itself is not a worktree).
463
497
  */
464
498
  function isInsideGsdWorktree(p: string): boolean {
465
- // Match /.gsd/worktrees/<name> where <name> is the final segment or
466
- // followed by a separator. The <name> segment must be non-empty.
467
- const sepFwd = "/";
468
- const sepNative = "\\";
469
- const markers = [
470
- `${sepFwd}.gsd${sepFwd}worktrees${sepFwd}`,
471
- `${sepNative}.gsd${sepNative}worktrees${sepNative}`,
472
- ];
473
- for (const marker of markers) {
474
- const idx = p.indexOf(marker);
475
- if (idx === -1) continue;
476
- // Verify there's a non-empty worktree name after the marker
477
- const afterMarker = p.slice(idx + marker.length);
478
- // The name is everything up to the next separator (or end of string)
479
- const nameEnd = afterMarker.search(/[/\\]/);
480
- const name = nameEnd === -1 ? afterMarker : afterMarker.slice(0, nameEnd);
481
- if (name.length > 0) return true;
482
- }
483
- return false;
499
+ const normalized = p.replaceAll("\\", "/");
500
+ const segment = findWorktreeSegment(normalized);
501
+ if (!segment) return false;
502
+ const name = normalized.slice(segment.afterWorktrees).split("/")[0];
503
+ return name.length > 0;
484
504
  }
485
505
 
486
506
  function probeGsdRoot(rawBasePath: string): string {
@@ -24,6 +24,7 @@ import { isAbsolute, relative, resolve } from "node:path";
24
24
  import type { TaskRow } from "./db-task-slice-rows.js";
25
25
  import type { PreExecutionCheckJSON } from "./verification-evidence.ts";
26
26
  import { validateVerificationCommand } from "./verification-gate.js";
27
+ import { FRAMEWORK_METADATA_DIRS, PLANNING_ARTIFACT_NAME_RE } from "./paths.js";
27
28
 
28
29
  const NPM_COMMAND = process.platform === "win32" ? "npm.cmd" : "npm";
29
30
 
@@ -586,6 +587,9 @@ export function checkFilePathConsistency(
586
587
  // Skip empty strings
587
588
  if (!file.trim()) continue;
588
589
  if (!shouldValidateInputAsPath(file)) continue;
590
+ // Planning-artifact references are owned by checkPlanningArtifactReferences,
591
+ // which reports a precise removal message instead of "doesn't exist".
592
+ if (isPlanningArtifactReference(file, basePath, context)) continue;
589
593
 
590
594
  // Normalize path for consistent comparison
591
595
  const normalizedFile = toComparisonPath(file, basePath);
@@ -628,6 +632,85 @@ export function checkFilePathConsistency(
628
632
  return results;
629
633
  }
630
634
 
635
+ // ─── Planning Artifact Reference Check ───────────────────────────────────────
636
+
637
+ function isFrameworkMetadataPath(normalizedFile: string): boolean {
638
+ return normalizedFile.split("/").some((segment) => FRAMEWORK_METADATA_DIRS.includes(segment.toLowerCase()));
639
+ }
640
+
641
+ /**
642
+ * True when a task IO entry references a GSD planning artifact.
643
+ *
644
+ * Task inputs are source files only — planning artifacts are projections of DB
645
+ * state that the framework preloads as composed context (see CONTEXT.md "Task
646
+ * Input"). Two triggers, deliberately different in strictness:
647
+ *
648
+ * - Any path entering framework-owned metadata (.gsd/, .planning/, .audits/)
649
+ * is always a violation, even when the file exists.
650
+ * - A bare artifact-style basename (M001-CONTEXT.md, S01-PLAN.md, …) is a
651
+ * violation only when it does NOT resolve to a real file. When such a file
652
+ * genuinely exists in the source tree (e.g. a fixture), it is a source file
653
+ * and stays legal; a path with directory components is likewise left to the
654
+ * ordinary existence checks.
655
+ */
656
+ function isPlanningArtifactReference(
657
+ rawEntry: string,
658
+ basePath: string,
659
+ context?: PreExecutionCheckContext,
660
+ ): boolean {
661
+ if (!shouldValidateInputAsPath(rawEntry)) return false;
662
+ const normalized = toComparisonPath(rawEntry, basePath);
663
+ if (isFrameworkMetadataPath(normalized)) return true;
664
+ return (
665
+ !normalized.includes("/") &&
666
+ PLANNING_ARTIFACT_NAME_RE.test(normalized) &&
667
+ !inputExistsOnDisk(normalized, basePath, context)
668
+ );
669
+ }
670
+
671
+ /**
672
+ * Block GSD planning artifacts in task IO fields (inputs, files, expectedOutput).
673
+ *
674
+ * For inputs/files the violation smuggles a projection into the executor's
675
+ * preloaded source context; for expectedOutput it promises a write the runtime
676
+ * write-gate would reject mid-execution. Both get a precise message so the
677
+ * planning retry steers toward *removing* the reference, not creating the file.
678
+ * checkFilePathConsistency and checkTaskOrdering skip entries this check owns.
679
+ */
680
+ export function checkPlanningArtifactReferences(
681
+ tasks: TaskRow[],
682
+ basePath: string,
683
+ context?: PreExecutionCheckContext,
684
+ ): PreExecutionCheckJSON[] {
685
+ const results: PreExecutionCheckJSON[] = [];
686
+
687
+ for (const task of tasks) {
688
+ const fields = [
689
+ { label: "inputs", entries: task.inputs },
690
+ { label: "files", entries: task.files },
691
+ { label: "expectedOutput", entries: task.expected_output },
692
+ ];
693
+ for (const { label, entries } of fields) {
694
+ for (const file of entries) {
695
+ if (!isPlanningArtifactReference(file, basePath, context)) continue;
696
+ const message =
697
+ label === "expectedOutput"
698
+ ? `Task ${task.id} lists '${file}' in expectedOutput — GSD planning artifacts are written by workflow tools (e.g. gsd_summary_save), never by tasks; remove it`
699
+ : `Task ${task.id} lists '${file}' in ${label} — GSD planning artifacts are projections preloaded as context, never task ${label}; remove it`;
700
+ results.push({
701
+ category: "file",
702
+ target: file,
703
+ passed: false,
704
+ message,
705
+ blocking: true,
706
+ });
707
+ }
708
+ }
709
+ }
710
+
711
+ return results;
712
+ }
713
+
631
714
  // ─── Task Ordering Check ─────────────────────────────────────────────────────
632
715
 
633
716
  /**
@@ -671,6 +754,9 @@ export function checkTaskOrdering(
671
754
  for (const file of filesToCheck) {
672
755
  if (isRuntimeOnlyInput(file)) continue;
673
756
  if (!shouldValidateInputAsPath(file)) continue;
757
+ // Owned by checkPlanningArtifactReferences — avoid a duplicate sequence
758
+ // finding on top of the removal message.
759
+ if (isPlanningArtifactReference(file, basePath, context)) continue;
674
760
 
675
761
  const normalizedFile = toComparisonPath(file, basePath);
676
762
  if (containsGlobPattern(normalizedFile)) continue;
@@ -700,6 +786,27 @@ export function checkTaskOrdering(
700
786
  return results;
701
787
  }
702
788
 
789
+ // ─── Shared Path-Check Composition ───────────────────────────────────────────
790
+
791
+ /**
792
+ * The synchronous path-shaped checks, in order. One list shared by the
793
+ * plan-persist gate (gsd_plan_slice) and the dispatch gate
794
+ * (runPreExecutionChecks) so the two cannot drift — the checks coordinate
795
+ * ownership of planning-artifact entries via isPlanningArtifactReference
796
+ * skips, which only works when they run as a set.
797
+ */
798
+ export function runTaskPathChecks(
799
+ tasks: TaskRow[],
800
+ basePath: string,
801
+ context?: PreExecutionCheckContext,
802
+ ): PreExecutionCheckJSON[] {
803
+ return [
804
+ ...checkPlanningArtifactReferences(tasks, basePath, context),
805
+ ...checkFilePathConsistency(tasks, basePath, context),
806
+ ...checkTaskOrdering(tasks, basePath, context),
807
+ ];
808
+ }
809
+
703
810
  // ─── Interface Contract Check ────────────────────────────────────────────────
704
811
 
705
812
  interface FunctionSignature {
@@ -866,12 +973,11 @@ export async function runPreExecutionChecks(
866
973
  const allChecks: PreExecutionCheckJSON[] = [];
867
974
 
868
975
  // Run sync checks first
869
- const fileChecks = checkFilePathConsistency(tasks, basePath, context);
870
- const orderingChecks = checkTaskOrdering(tasks, basePath, context);
976
+ const pathChecks = runTaskPathChecks(tasks, basePath, context);
871
977
  const contractChecks = checkInterfaceContracts(tasks, basePath);
872
978
  const verificationChecks = checkVerificationCommands(tasks);
873
979
 
874
- allChecks.push(...fileChecks, ...orderingChecks, ...contractChecks, ...verificationChecks);
980
+ allChecks.push(...pathChecks, ...contractChecks, ...verificationChecks);
875
981
 
876
982
  // Run async package checks
877
983
  const packageChecks = await checkPackageExistence(tasks, basePath);
@@ -26,6 +26,7 @@ import type {
26
26
  AutoSupervisorConfig,
27
27
  } from "./preferences-types.js";
28
28
  import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
29
+ import { getUnitPhaseChain } from "./unit-registry.js";
29
30
 
30
31
  // Re-export types so existing consumers of ./preferences-models.js keep working
31
32
  export type { GSDPhaseModelConfig, GSDModelConfig, GSDModelConfigV2, ResolvedModelConfig } from "./preferences-types.js";
@@ -49,53 +50,16 @@ export function resolveModelForUnit(unitType: string): string | undefined {
49
50
  * (`resolveThinkingLevelForUnit`) so the two never drift (ADR-026).
50
51
  */
51
52
  export function phaseChainForUnit(unitType: string): GSDModelPhaseKey[] | undefined {
52
- switch (unitType) {
53
- case "research-milestone":
54
- case "research-slice":
55
- // Deep-mode project research orchestrator. Reads PROJECT.md / REQUIREMENTS.md
56
- // and fans out research subagents. Routes to the research bucket.
57
- case "research-project":
58
- return ["research"];
59
- case "plan-milestone":
60
- case "plan-slice":
61
- case "refine-slice":
62
- case "replan-slice":
63
- return ["planning"];
64
- // Deep-mode project-level discussion units route to the same model bucket
65
- // as milestone-level discussion (interactive interview style). Workflow
66
- // preferences and research-decision are tiny ask_user_questions style units
67
- // that share the discuss bucket because they are conversational. All fall
68
- // back to planning when no `discuss` bucket is set.
69
- case "discuss-milestone":
70
- case "discuss-slice":
71
- case "discuss-project":
72
- case "discuss-requirements":
73
- case "workflow-preferences":
74
- case "research-decision":
75
- return ["discuss", "planning"];
76
- case "execute-task":
77
- case "reactive-execute":
78
- return ["execution"];
79
- case "execute-task-simple":
80
- return ["execution_simple", "execution"];
81
- case "complete-slice":
82
- case "complete-milestone":
83
- case "worktree-merge":
84
- return ["completion"];
85
- case "run-uat":
86
- return ["uat", "completion"];
87
- case "reassess-roadmap":
88
- case "rewrite-docs":
89
- case "gate-evaluate":
90
- case "validate-milestone":
91
- return ["validation", "planning"];
92
- default:
93
- // Subagent unit types (e.g., "subagent", "subagent/scout")
94
- if (unitType === "subagent" || unitType.startsWith("subagent/")) {
95
- return ["subagent"];
96
- }
97
- return undefined;
53
+ // Unit types declare their chain on their Unit Descriptor (ADR-033).
54
+ const declared = getUnitPhaseChain(unitType);
55
+ if (declared) return [...declared];
56
+ // Dispatch types without a Unit Descriptor.
57
+ if (unitType === "worktree-merge") return ["completion"];
58
+ // Subagent unit types (e.g., "subagent", "subagent/scout")
59
+ if (unitType === "subagent" || unitType.startsWith("subagent/")) {
60
+ return ["subagent"];
98
61
  }
62
+ return undefined;
99
63
  }
100
64
 
101
65
  /**
@@ -867,6 +867,24 @@ export function getIsolationMode(basePath?: string): "none" | "worktree" | "bran
867
867
  return "none"; // default — no isolation, work on current branch
868
868
  }
869
869
 
870
+ /**
871
+ * Resolve the isolation mode a unit actually runs under. A session whose
872
+ * worktree isolation has degraded (worktree creation failed) falls back to
873
+ * the milestone branch in the project root, so configured "worktree" becomes
874
+ * effective "branch". A stranded-work recovery session likewise runs under
875
+ * the adopted mode (`strandedRecoveryIsolationMode`) rather than the
876
+ * configured one until the recovered milestone merges — adopting the
877
+ * milestone branch in the project root is intentional, not degraded.
878
+ */
879
+ export function resolveEffectiveUnitIsolationMode(
880
+ configuredMode: ReturnType<typeof getIsolationMode>,
881
+ isolationDegraded: boolean,
882
+ strandedRecoveryIsolationMode: "worktree" | "branch" | null = null,
883
+ ): ReturnType<typeof getIsolationMode> {
884
+ if (configuredMode === "worktree" && isolationDegraded) return "branch";
885
+ return strandedRecoveryIsolationMode ?? configuredMode;
886
+ }
887
+
870
888
  export function resolveParallelConfig(prefs: GSDPreferences | undefined): import("./types.js").ParallelConfig {
871
889
  return {
872
890
  enabled: prefs?.parallel?.enabled ?? false,
@@ -45,7 +45,7 @@ If slice research is inlined, trust its architectural findings, but verify every
45
45
  6. Include Threat Surface (Q3), Requirement Impact (Q4), proof level, observability, integration closure, Failure Modes (Q5), Load Profile (Q6), and Negative Tests (Q7) only where applicable.
46
46
  7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
47
47
  8. Task `verify` commands must be safe, simple commands. Do not use shell pipes, redirects, semicolons, backticks, command substitution, output trimming, or grep regex alternation with `|`. If multiple checks are needed, create a small test file and run it with `node --test` or a package test script, or use separate simple commands joined only with `&&`. For absence checks, verify a pattern does not exist with `! grep -q 'pattern' file` or `! rg -q 'pattern' file`; do not use `grep -c` or `rg -c` to assert zero matches because count commands exit 1 when they find zero matches, and the verification gate treats that as failure.
48
- 9. Each task needs the exact `gsd_plan_slice.tasks[]` shape: `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. `description` should contain the Why / Do / Done-when narrative. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even when there is only one path (for example, `"inputs": ["src/index.ts"]`, never `"inputs": "src/index.ts"`). Use paths relative to `{{workingDirectory}}`; do not put absolute paths to the original checkout or any directory outside `{{workingDirectory}}` in `files`, `inputs`, `expectedOutput`, or verification commands. **`expectedOutput` must only list files the task actually creates or overwrites on disk.** Do NOT include files the task merely reads, verifies, tests, or describes — those belong in `inputs`, `verify`, `description`, or slice success criteria. If a task is a pure verification or test task that produces no new files, `expectedOutput` must be `[]`; if it writes a test-result log or assertion output file, list only that concrete file path. A file that does not yet exist on disk and is needed as an `input` must be produced by an earlier task's `expectedOutput` — if no prior task creates it, add a task before this one that does.
48
+ 9. Each task needs the exact `gsd_plan_slice.tasks[]` shape: `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. `description` should contain the Why / Do / Done-when narrative. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even when there is only one path (for example, `"inputs": ["src/index.ts"]`, never `"inputs": "src/index.ts"`). Use paths relative to `{{workingDirectory}}`; do not put absolute paths to the original checkout or any directory outside `{{workingDirectory}}` in `files`, `inputs`, `expectedOutput`, or verification commands. **`expectedOutput` must only list files the task actually creates or overwrites on disk.** Do NOT include files the task merely reads, verifies, tests, or describes — those belong in `inputs`, `verify`, `description`, or slice success criteria. If a task is a pure verification or test task that produces no new files, `expectedOutput` must be `[]`; if it writes a test-result log or assertion output file, list only that concrete file path. A file that does not yet exist on disk and is needed as an `input` must be produced by an earlier task's `expectedOutput` — if no prior task creates it, add a task before this one that does. Never list GSD planning artifacts — anything under `.gsd/`, `.planning/`, or `.audits/`, or artifact names like `M001-CONTEXT.md` / `S01-PLAN.md` — in `inputs`, `files`, or `expectedOutput`: their content is preloaded as context, and they are written by workflow tools, not by tasks.
49
49
  10. Persist with `gsd_plan_slice` using `milestoneId`, `sliceId`, `goal`, optional `successCriteria`/`proofLevel`/`integrationClosure`/`observabilityImpact`, and `tasks`. `gsd_plan_slice` handles task persistence transactionally and renders `{{outputPath}}` plus task plans; do not call `gsd_plan_task`. The DB-backed tool is the canonical write path. Do **not** rely on direct `PLAN.md` writes as the source of truth.
50
50
  11. Self-audit before finishing: goal/demo closure, requirement coverage, deliverable coverage audit (cross-check every file listed in CONTEXT.md `## Scope` / `### In Scope` against task `files` or `expectedOutput`), locked decisions, concrete paths, dependency order, wiring, scope size, proof truthfulness, feature completeness, and quality gates. Quality gates: non-trivial slices/tasks include specific Q3-Q7 coverage where applicable.
51
51
  12. If planning creates structural decisions, call `gsd_decision_save` for each; the tool persists the decision and regenerates `.gsd/DECISIONS.md`.
@@ -65,7 +65,7 @@ Then:
65
65
  3. Define slice-level verification: the objective stopping condition. Plan real test files with real assertions; for simple slices, executable commands are fine.
66
66
  **Web apps:** when inlined Web App UAT guidance is present, follow it for Playwright scaffolding and browser-capable verification commands.
67
67
  4. For non-trivial slices, plan observability / proof level / integration closure, threat surface, and requirement impact. Omit entirely for simple slices.
68
- 5. Decompose the slice into tasks that fit one context window each. Every task passed to `gsd_plan_slice` must use the exact keys `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. Put Why / Do / Done-when detail in `description`. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even for one path (for example, `"expectedOutput": ["src/index.ts"]`, never `"expectedOutput": "src/index.ts"`). `expectedOutput` is path-only: list only files the task creates or overwrites, and use `[]` for pure verification tasks.
68
+ 5. Decompose the slice into tasks that fit one context window each. Every task passed to `gsd_plan_slice` must use the exact keys `taskId`, `title`, `description`, `estimate`, `files`, `verify`, `inputs`, `expectedOutput`, and optional `observabilityImpact`. Put Why / Do / Done-when detail in `description`. `files`, `inputs`, and `expectedOutput` must be JSON arrays of strings, even for one path (for example, `"expectedOutput": ["src/index.ts"]`, never `"expectedOutput": "src/index.ts"`). `expectedOutput` is path-only: list only files the task creates or overwrites, and use `[]` for pure verification tasks. Never list GSD planning artifacts — anything under `.gsd/`, `.planning/`, or `.audits/`, or artifact names like `M001-CONTEXT.md` / `S01-PLAN.md` — in `inputs`, `files`, or `expectedOutput`: their content is preloaded as context, and they are written by workflow tools, not by tasks.
69
69
  6. **Persist planning state through `gsd_plan_slice`.** Call it with the full payload. The tool writes to the DB and renders `{{outputPath}}` and `{{slicePath}}/tasks/T##-PLAN.md` automatically. Do NOT rely on direct `PLAN.md` writes.
70
70
  7. **Self-audit the plan.** If every task were completed exactly as written, the slice goal/demo should be true. Every must-have maps to a task. Inputs and Expected Output are backtick-wrapped file paths.
71
71
  8. If refinement produced structural decisions that diverge from the sketch, call `gsd_decision_save` for each; the tool persists the decision and regenerates `.gsd/DECISIONS.md`.
@@ -34,7 +34,7 @@ Consider these captures when rewriting the remaining tasks — they represent th
34
34
 
35
35
  1. Use the inlined blocker summary excerpt first. Read the full blocker task summary only if the excerpt is absent, marked truncated, or lacks the specific blocker evidence needed to replan.
36
36
  2. Analyze the remaining `[ ]` tasks in the slice plan. Determine which are still valid, which need modification, and which should be replaced.
37
- 3. **Persist replan state through `gsd_replan_slice`.** Call it with: `milestoneId`, `sliceId`, `blockerTaskId`, `blockerDescription`, `whatChanged`, `updatedTasks` (array of task objects with taskId, title, description, estimate, files, verify, inputs, expectedOutput), `removedTaskIds` (array of task ID strings). The tool structurally enforces preservation of completed tasks, writes replan history to the DB, re-renders `{{planPath}}`, and renders `{{replanPath}}`. Preserve or update the Threat Surface and Requirement Impact sections if the replan changes the slice's security posture or requirement coverage.
37
+ 3. **Persist replan state through `gsd_replan_slice`.** Call it with: `milestoneId`, `sliceId`, `blockerTaskId`, `blockerDescription`, `whatChanged`, `updatedTasks` (array of task objects with taskId, title, description, estimate, files, verify, inputs, expectedOutput), `removedTaskIds` (array of task ID strings). Never list GSD planning artifacts — anything under `.gsd/`, `.planning/`, or `.audits/`, or artifact names like `M001-CONTEXT.md` / `S01-PLAN.md` — in `inputs`, `files`, or `expectedOutput`: their content is preloaded as context, and they are written by workflow tools, not by tasks. The tool structurally enforces preservation of completed tasks, writes replan history to the DB, re-renders `{{planPath}}`, and renders `{{replanPath}}`. Preserve or update the Threat Surface and Requirement Impact sections if the replan changes the slice's security posture or requirement coverage.
38
38
  4. If any incomplete task had a `T0x-PLAN.md`, remove or rewrite it to match the new task description.
39
39
  5. Do not commit manually — the system auto-commits your changes after this unit completes.
40
40
 
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * Actionable remediation hints when auto-mode pauses on provider/model errors.
3
+ * Render with formatGuidance from the Guidance module.
3
4
  */
4
5
 
6
+ import type { Guidance } from "./guidance.js";
7
+
5
8
  export interface ProviderErrorGuidanceInput {
6
9
  errorMsg: string;
7
10
  provider?: string;
@@ -12,10 +15,7 @@ export interface ProviderErrorGuidanceInput {
12
15
  hasConfiguredFallbacks?: boolean;
13
16
  }
14
17
 
15
- export interface ProviderErrorGuidance {
16
- summary: string;
17
- steps: string[];
18
- }
18
+ export type ProviderErrorGuidance = Guidance;
19
19
 
20
20
  /** Map auto unit types to the `models:` key in PREFERENCES.md. */
21
21
  export function unitTypeToPrefsPhaseKey(unitType: string | undefined): string | undefined {
@@ -129,8 +129,3 @@ export function resolveProviderErrorGuidance(input: ProviderErrorGuidanceInput):
129
129
  return { summary, steps };
130
130
  }
131
131
 
132
- /** Flatten guidance into a pause banner / notification string. */
133
- export function formatProviderErrorGuidance(guidance: ProviderErrorGuidance): string {
134
- const numbered = guidance.steps.map((step, index) => `${index + 1}. ${step}`).join("\n");
135
- return `${guidance.summary}\n\n${numbered}`;
136
- }
@@ -128,7 +128,7 @@ function emitAudit(report: ProviderSwitchReport): void {
128
128
 
129
129
  function emitNotification(report: ProviderSwitchReport): void {
130
130
  try {
131
- appendNotification(summarize(report), "warning", "workflow-logger");
131
+ appendNotification(summarize(report), "warning", "workflow-logger", { kind: "provider-switch" });
132
132
  } catch {
133
133
  // Notification persistence is best-effort.
134
134
  }
@@ -0,0 +1,122 @@
1
+ // Project/App: gsd-pi
2
+ // File Purpose: Publication module — push and draft-PR creation for a merged milestone (ADR-034).
3
+ //
4
+ // Publication is distinct from the merge verb: merging a milestone branch is a
5
+ // Worktree Lifecycle concern (worktree, branch, lease, stash discipline);
6
+ // publication needs only the resulting commit, a remote, and preferences.
7
+ // Extracted from the tail of `mergeMilestoneToMain` (auto-worktree.ts) so it is
8
+ // testable without a merge fixture and reachable from any closeout path.
9
+ //
10
+ // Publication failure is non-fatal to a completed local merge: every failure is
11
+ // logged and reported in the result, never thrown.
12
+
13
+ import { execFileSync } from "node:child_process";
14
+
15
+ import {
16
+ buildPullRequestEvidence,
17
+ createDraftPullRequestFromEvidence,
18
+ } from "./pull-request-process.js";
19
+ import { logWarning } from "./workflow-logger.js";
20
+
21
+ export interface PublicationPrefs {
22
+ autoPush: boolean;
23
+ autoPr: boolean;
24
+ remote?: string;
25
+ prTargetBranch?: string;
26
+ }
27
+
28
+ export interface PublicationRequest {
29
+ basePath: string;
30
+ milestoneId: string;
31
+ milestoneTitle: string;
32
+ /** The branch the milestone was merged to (push target for auto-push). */
33
+ integrationBranch: string;
34
+ /** The milestone branch (push + PR head for auto-PR). */
35
+ milestoneBranch: string;
36
+ /** Pre-rendered per-slice summary blocks for the PR body. */
37
+ sliceSummaries: readonly string[];
38
+ /** True when the merge found nothing to commit — publication is skipped. */
39
+ nothingToCommit: boolean;
40
+ prefs: PublicationPrefs;
41
+ }
42
+
43
+ export interface PublicationResult {
44
+ pushed: boolean;
45
+ prCreated: boolean;
46
+ prUrl?: string;
47
+ }
48
+
49
+ export function gitRemoteExists(basePath: string, remote: string): boolean {
50
+ try {
51
+ execFileSync("git", ["remote", "get-url", remote], {
52
+ cwd: basePath,
53
+ stdio: ["ignore", "pipe", "pipe"],
54
+ encoding: "utf-8",
55
+ });
56
+ return true;
57
+ } catch {
58
+ return false;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Publish a merged milestone per preferences: push the integration branch
64
+ * (auto-push, suppressed when auto-PR owns the remote interaction) and/or
65
+ * push the milestone branch and open a draft PR (auto-PR).
66
+ */
67
+ export function publishMilestone(request: PublicationRequest): PublicationResult {
68
+ const result: PublicationResult = { pushed: false, prCreated: false };
69
+ if (request.nothingToCommit) return result;
70
+
71
+ const { basePath, prefs } = request;
72
+ const remote = prefs.remote ?? "origin";
73
+
74
+ if (prefs.autoPush && !prefs.autoPr && gitRemoteExists(basePath, remote)) {
75
+ try {
76
+ execFileSync("git", ["push", remote, request.integrationBranch], {
77
+ cwd: basePath,
78
+ stdio: ["ignore", "pipe", "pipe"],
79
+ encoding: "utf-8",
80
+ });
81
+ result.pushed = true;
82
+ } catch (err) {
83
+ // Push failure is non-fatal
84
+ logWarning("worktree", `git push failed: ${err instanceof Error ? err.message : String(err)}`);
85
+ }
86
+ }
87
+
88
+ // #2302: PR creation is not gated on pushed/auto-push.
89
+ if (prefs.autoPr && gitRemoteExists(basePath, remote)) {
90
+ try {
91
+ // Push the milestone branch to remote first
92
+ execFileSync("git", ["push", remote, request.milestoneBranch], {
93
+ cwd: basePath,
94
+ stdio: ["ignore", "pipe", "pipe"],
95
+ encoding: "utf-8",
96
+ });
97
+ const prEvidence = buildPullRequestEvidence({
98
+ milestoneId: request.milestoneId,
99
+ milestoneTitle: request.milestoneTitle,
100
+ changeType: "feat",
101
+ summaries: [...request.sliceSummaries],
102
+ testsRun: ["Auto-created after milestone merge. Run `npm run verify:merge` before marking this draft ready."],
103
+ rollbackNotes: ["Close the draft PR or revert the merge commit if review finds a behavior regression."],
104
+ how: "Generated by git.auto_pr after the milestone branch was pushed and merged locally.",
105
+ });
106
+ const prUrl = createDraftPullRequestFromEvidence(basePath, request.milestoneId, prEvidence, {
107
+ head: request.milestoneBranch,
108
+ base: prefs.prTargetBranch ?? request.integrationBranch,
109
+ });
110
+ if (!prUrl) {
111
+ throw new Error("gh pr create returned no URL");
112
+ }
113
+ result.prCreated = true;
114
+ result.prUrl = prUrl;
115
+ } catch (err) {
116
+ // PR creation failure is non-fatal — gh may not be installed or authenticated
117
+ logWarning("worktree", `PR creation failed: ${err instanceof Error ? err.message : String(err)}`);
118
+ }
119
+ }
120
+
121
+ return result;
122
+ }