@opengsd/gsd-pi 1.1.1-dev.a5a2de8 → 1.1.1-dev.b2556262

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 (325) hide show
  1. package/dist/headless-recover.js +56 -1
  2. package/dist/resources/.managed-resources-content-hash +1 -1
  3. package/dist/resources/extensions/browser-tools/engine/managed-gsd-browser.js +18 -2
  4. package/dist/resources/extensions/browser-tools/engine/selection.js +1 -1
  5. package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
  6. package/dist/resources/extensions/browser-tools/index.js +68 -24
  7. package/dist/resources/extensions/browser-tools/state.js +12 -0
  8. package/dist/resources/extensions/browser-tools/tools/session.js +3 -2
  9. package/dist/resources/extensions/browser-tools/utils.js +3 -3
  10. package/dist/resources/extensions/browser-tools/web-app-detect.js +52 -0
  11. package/dist/resources/extensions/gsd/auto/loop.js +4 -2
  12. package/dist/resources/extensions/gsd/auto/phases.js +87 -12
  13. package/dist/resources/extensions/gsd/auto/session.js +22 -1
  14. package/dist/resources/extensions/gsd/auto/workflow-kernel.js +1 -0
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +81 -13
  16. package/dist/resources/extensions/gsd/auto-model-selection.js +154 -9
  17. package/dist/resources/extensions/gsd/auto-post-unit.js +19 -2
  18. package/dist/resources/extensions/gsd/auto-prompts.js +26 -21
  19. package/dist/resources/extensions/gsd/auto-recovery.js +4 -2
  20. package/dist/resources/extensions/gsd/auto-runtime-state.js +3 -0
  21. package/dist/resources/extensions/gsd/auto-start.js +1 -1
  22. package/dist/resources/extensions/gsd/auto-timers.js +24 -10
  23. package/dist/resources/extensions/gsd/auto.js +40 -15
  24. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +3 -3
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +192 -77
  26. package/dist/resources/extensions/gsd/bootstrap/system-context.js +1 -1
  27. package/dist/resources/extensions/gsd/closeout-wizard.js +32 -9
  28. package/dist/resources/extensions/gsd/commands/handlers/auto.js +10 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +2 -9
  30. package/dist/resources/extensions/gsd/commands-maintenance.js +93 -15
  31. package/dist/resources/extensions/gsd/commands-mcp-status.js +1 -1
  32. package/dist/resources/extensions/gsd/commands-prefs-wizard.js +2 -2
  33. package/dist/resources/extensions/gsd/config-overlay.js +1 -0
  34. package/dist/resources/extensions/gsd/context-masker.js +129 -5
  35. package/dist/resources/extensions/gsd/db-writer.js +35 -0
  36. package/dist/resources/extensions/gsd/docs/preferences-reference.md +50 -1
  37. package/dist/resources/extensions/gsd/gsd-db.js +480 -172
  38. package/dist/resources/extensions/gsd/guided-flow.js +4 -1
  39. package/dist/resources/extensions/gsd/markdown-renderer.js +37 -53
  40. package/dist/resources/extensions/gsd/md-importer.js +38 -3
  41. package/dist/resources/extensions/gsd/migration-auto-check.js +126 -31
  42. package/dist/resources/extensions/gsd/parsers-legacy.js +23 -0
  43. package/dist/resources/extensions/gsd/planner-handoff.js +98 -0
  44. package/dist/resources/extensions/gsd/planning-path-scope.js +22 -4
  45. package/dist/resources/extensions/gsd/pre-execution-checks.js +10 -2
  46. package/dist/resources/extensions/gsd/preferences-models.js +111 -43
  47. package/dist/resources/extensions/gsd/preferences-types.js +13 -0
  48. package/dist/resources/extensions/gsd/preferences-validation.js +68 -3
  49. package/dist/resources/extensions/gsd/preferences.js +4 -1
  50. package/dist/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  51. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  52. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  53. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  54. package/dist/resources/extensions/gsd/prompts/run-uat.md +2 -2
  55. package/dist/resources/extensions/gsd/prompts/system.md +1 -1
  56. package/dist/resources/extensions/gsd/roadmap-slices.js +5 -1
  57. package/dist/resources/extensions/gsd/safety/content-validator.js +6 -4
  58. package/dist/resources/extensions/gsd/skill-manifest.js +12 -0
  59. package/dist/resources/extensions/gsd/source-observations.js +306 -0
  60. package/dist/resources/extensions/gsd/state-reconciliation/drift/completion.js +15 -8
  61. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-render.js +33 -5
  62. package/dist/resources/extensions/gsd/state-reconciliation/drift/stale-worker.js +34 -13
  63. package/dist/resources/extensions/gsd/state-reconciliation/index.js +39 -14
  64. package/dist/resources/extensions/gsd/state-reconciliation/spawn-gate.js +4 -4
  65. package/dist/resources/extensions/gsd/state.js +7 -3
  66. package/dist/resources/extensions/gsd/tool-contract.js +15 -1
  67. package/dist/resources/extensions/gsd/tool-presentation-plan.js +24 -2
  68. package/dist/resources/extensions/gsd/tools/complete-slice.js +28 -0
  69. package/dist/resources/extensions/gsd/tools/plan-slice.js +42 -11
  70. package/dist/resources/extensions/gsd/tools/plan-task.js +7 -1
  71. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +62 -406
  72. package/dist/resources/extensions/gsd/uat-policy.js +130 -0
  73. package/dist/resources/extensions/gsd/uat-run.js +414 -0
  74. package/dist/resources/extensions/gsd/unit-context-manifest.js +3 -4
  75. package/dist/resources/extensions/gsd/unit-tool-contracts.js +38 -14
  76. package/dist/resources/extensions/gsd/verdict-parser.js +3 -8
  77. package/dist/resources/extensions/gsd/workflow-manifest.js +132 -5
  78. package/dist/resources/extensions/gsd/workflow-mcp.js +2 -3
  79. package/dist/resources/extensions/gsd/workflow-projections.js +8 -0
  80. package/dist/resources/extensions/gsd/worktree-manager.js +26 -0
  81. package/dist/resources/extensions/gsd/worktree-reentry.js +96 -0
  82. package/dist/resources/extensions/gsd/worktree-state-projection.js +18 -17
  83. package/dist/resources/extensions/shared/gsd-browser-cli.js +6 -0
  84. package/dist/resources/extensions/subagent/agents.js +1 -0
  85. package/dist/resources/extensions/subagent/index.js +27 -12
  86. package/dist/resources/extensions/subagent/launch.js +7 -2
  87. package/dist/web/standalone/.next/BUILD_ID +1 -1
  88. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  89. package/dist/web/standalone/.next/build-manifest.json +2 -2
  90. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  91. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  92. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  93. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  94. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  95. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  96. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  97. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  98. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  99. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  100. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  101. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  102. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  103. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  104. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  105. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  106. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  107. package/dist/web/standalone/.next/server/app/index.html +1 -1
  108. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  115. package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
  116. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  118. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  119. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  120. package/dist/web/standalone/node_modules/@gsd/native/dist/native.js +22 -0
  121. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  122. package/package.json +4 -4
  123. package/packages/cloud-mcp-gateway/package.json +2 -2
  124. package/packages/contracts/package.json +1 -1
  125. package/packages/daemon/package.json +4 -4
  126. package/packages/gsd-agent-core/package.json +5 -5
  127. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  128. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js +21 -23
  129. package/packages/gsd-agent-modes/dist/modes/interactive/components/assistant-message.js.map +1 -1
  130. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +3 -0
  131. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  132. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +25 -0
  133. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  134. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +1 -0
  135. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  136. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +66 -12
  137. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  138. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  139. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +18 -11
  140. package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  141. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.d.ts.map +1 -1
  142. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js +16 -0
  143. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-chat-render.js.map +1 -1
  144. package/packages/gsd-agent-modes/package.json +7 -7
  145. package/packages/mcp-server/dist/workflow-tools.js +1 -1
  146. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  147. package/packages/mcp-server/package.json +3 -3
  148. package/packages/native/dist/native.js +22 -0
  149. package/packages/native/package.json +1 -1
  150. package/packages/pi-agent-core/package.json +1 -1
  151. package/packages/pi-ai/dist/image-models.generated.d.ts +30 -0
  152. package/packages/pi-ai/dist/image-models.generated.d.ts.map +1 -1
  153. package/packages/pi-ai/dist/image-models.generated.js +30 -0
  154. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  155. package/packages/pi-ai/dist/models.generated.d.ts +174 -29
  156. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  157. package/packages/pi-ai/dist/models.generated.js +178 -54
  158. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  159. package/packages/pi-ai/dist/providers/transform-messages.d.ts.map +1 -1
  160. package/packages/pi-ai/dist/providers/transform-messages.js +8 -1
  161. package/packages/pi-ai/dist/providers/transform-messages.js.map +1 -1
  162. package/packages/pi-ai/package.json +1 -1
  163. package/packages/pi-coding-agent/dist/core/settings-manager.js +1 -1
  164. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  165. package/packages/pi-coding-agent/dist/theme/themes.js +1 -1
  166. package/packages/pi-coding-agent/dist/theme/themes.js.map +1 -1
  167. package/packages/pi-coding-agent/package.json +7 -7
  168. package/packages/pi-tui/dist/utils.d.ts +11 -0
  169. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  170. package/packages/pi-tui/dist/utils.js +119 -6
  171. package/packages/pi-tui/dist/utils.js.map +1 -1
  172. package/packages/pi-tui/package.json +2 -1
  173. package/packages/rpc-client/package.json +2 -2
  174. package/pkg/dist/theme/themes.js +1 -1
  175. package/pkg/dist/theme/themes.js.map +1 -1
  176. package/pkg/package.json +1 -1
  177. package/scripts/install/handoff.js +16 -3
  178. package/src/resources/extensions/browser-tools/engine/managed-gsd-browser.ts +21 -2
  179. package/src/resources/extensions/browser-tools/engine/selection.ts +1 -1
  180. package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
  181. package/src/resources/extensions/browser-tools/index.ts +75 -27
  182. package/src/resources/extensions/browser-tools/state.ts +13 -0
  183. package/src/resources/extensions/browser-tools/tests/browser-engine-selection.test.mjs +2 -2
  184. package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +57 -0
  185. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +37 -0
  186. package/src/resources/extensions/browser-tools/tests/web-app-detect.test.mjs +68 -0
  187. package/src/resources/extensions/browser-tools/tools/session.ts +4 -2
  188. package/src/resources/extensions/browser-tools/utils.ts +3 -3
  189. package/src/resources/extensions/browser-tools/web-app-detect.ts +63 -0
  190. package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
  191. package/src/resources/extensions/gsd/auto/loop.ts +4 -2
  192. package/src/resources/extensions/gsd/auto/phases.ts +89 -15
  193. package/src/resources/extensions/gsd/auto/session.ts +24 -1
  194. package/src/resources/extensions/gsd/auto/workflow-kernel.ts +1 -0
  195. package/src/resources/extensions/gsd/auto-dispatch.ts +117 -12
  196. package/src/resources/extensions/gsd/auto-model-selection.ts +190 -12
  197. package/src/resources/extensions/gsd/auto-post-unit.ts +20 -2
  198. package/src/resources/extensions/gsd/auto-prompts.ts +25 -22
  199. package/src/resources/extensions/gsd/auto-recovery.ts +22 -3
  200. package/src/resources/extensions/gsd/auto-runtime-state.ts +5 -0
  201. package/src/resources/extensions/gsd/auto-start.ts +1 -1
  202. package/src/resources/extensions/gsd/auto-timers.ts +25 -9
  203. package/src/resources/extensions/gsd/auto.ts +41 -14
  204. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +3 -3
  205. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +250 -78
  206. package/src/resources/extensions/gsd/bootstrap/system-context.ts +1 -1
  207. package/src/resources/extensions/gsd/closeout-wizard.ts +47 -13
  208. package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -0
  209. package/src/resources/extensions/gsd/commands/handlers/ops.ts +2 -17
  210. package/src/resources/extensions/gsd/commands-maintenance.ts +124 -13
  211. package/src/resources/extensions/gsd/commands-mcp-status.ts +1 -1
  212. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +2 -2
  213. package/src/resources/extensions/gsd/config-overlay.ts +1 -0
  214. package/src/resources/extensions/gsd/context-masker.ts +152 -5
  215. package/src/resources/extensions/gsd/db-writer.ts +38 -0
  216. package/src/resources/extensions/gsd/docs/preferences-reference.md +50 -1
  217. package/src/resources/extensions/gsd/gsd-db.ts +564 -186
  218. package/src/resources/extensions/gsd/guided-flow.ts +4 -1
  219. package/src/resources/extensions/gsd/markdown-renderer.ts +44 -66
  220. package/src/resources/extensions/gsd/md-importer.ts +49 -2
  221. package/src/resources/extensions/gsd/migration-auto-check.ts +154 -34
  222. package/src/resources/extensions/gsd/parsers-legacy.ts +20 -0
  223. package/src/resources/extensions/gsd/planner-handoff.ts +149 -0
  224. package/src/resources/extensions/gsd/planning-path-scope.ts +22 -4
  225. package/src/resources/extensions/gsd/pre-execution-checks.ts +9 -2
  226. package/src/resources/extensions/gsd/preferences-models.ts +113 -43
  227. package/src/resources/extensions/gsd/preferences-types.ts +47 -0
  228. package/src/resources/extensions/gsd/preferences-validation.ts +76 -2
  229. package/src/resources/extensions/gsd/preferences.ts +5 -0
  230. package/src/resources/extensions/gsd/prompts/gate-evaluate.md +1 -1
  231. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  232. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  233. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  234. package/src/resources/extensions/gsd/prompts/run-uat.md +2 -2
  235. package/src/resources/extensions/gsd/prompts/system.md +1 -1
  236. package/src/resources/extensions/gsd/roadmap-slices.ts +6 -1
  237. package/src/resources/extensions/gsd/safety/content-validator.ts +8 -5
  238. package/src/resources/extensions/gsd/skill-manifest.ts +12 -0
  239. package/src/resources/extensions/gsd/source-observations.ts +402 -0
  240. package/src/resources/extensions/gsd/state-reconciliation/drift/completion.ts +20 -8
  241. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-render.ts +44 -5
  242. package/src/resources/extensions/gsd/state-reconciliation/drift/stale-worker.ts +39 -11
  243. package/src/resources/extensions/gsd/state-reconciliation/index.ts +45 -15
  244. package/src/resources/extensions/gsd/state-reconciliation/spawn-gate.ts +4 -4
  245. package/src/resources/extensions/gsd/state.ts +7 -4
  246. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +114 -0
  247. package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +66 -4
  248. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +299 -1
  249. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +32 -0
  250. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +75 -3
  251. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +22 -1
  252. package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +4 -0
  253. package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +145 -0
  254. package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +9 -0
  255. package/src/resources/extensions/gsd/tests/closeout-wizard.test.ts +44 -0
  256. package/src/resources/extensions/gsd/tests/commands-dispatcher-unmerged-milestone.test.ts +26 -1
  257. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +118 -0
  258. package/src/resources/extensions/gsd/tests/content-validator.test.ts +74 -0
  259. package/src/resources/extensions/gsd/tests/context-masker.test.ts +56 -1
  260. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +17 -2
  261. package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +24 -0
  262. package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +1 -11
  263. package/src/resources/extensions/gsd/tests/gate-dispatch.test.ts +64 -0
  264. package/src/resources/extensions/gsd/tests/gate-storage.test.ts +15 -0
  265. package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +62 -1
  266. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +4 -1
  267. package/src/resources/extensions/gsd/tests/interrupted-session-auto.test.ts +27 -0
  268. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +16 -0
  269. package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +42 -0
  270. package/src/resources/extensions/gsd/tests/mcp-project-config.test.ts +7 -1
  271. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +1 -1
  272. package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +99 -0
  273. package/src/resources/extensions/gsd/tests/plan-slice.test.ts +99 -2
  274. package/src/resources/extensions/gsd/tests/plan-task.test.ts +19 -0
  275. package/src/resources/extensions/gsd/tests/planner-handoff.test.ts +100 -0
  276. package/src/resources/extensions/gsd/tests/preferences.test.ts +14 -0
  277. package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +1 -0
  278. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +133 -0
  279. package/src/resources/extensions/gsd/tests/provider-switch-observer.test.ts +55 -0
  280. package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +101 -1
  281. package/src/resources/extensions/gsd/tests/repository-registry.test.ts +2 -2
  282. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +28 -0
  283. package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +5 -3
  284. package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +162 -18
  285. package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +4 -3
  286. package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +8 -0
  287. package/src/resources/extensions/gsd/tests/source-observations.test.ts +275 -0
  288. package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +43 -0
  289. package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +76 -21
  290. package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +203 -0
  291. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +170 -0
  292. package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +7 -1
  293. package/src/resources/extensions/gsd/tests/workflow-kernel.test.ts +7 -0
  294. package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +306 -1
  295. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +77 -10
  296. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +260 -5
  297. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +511 -1
  298. package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +102 -0
  299. package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +44 -0
  300. package/src/resources/extensions/gsd/tool-contract.ts +29 -1
  301. package/src/resources/extensions/gsd/tool-presentation-plan.ts +41 -6
  302. package/src/resources/extensions/gsd/tools/complete-slice.ts +29 -0
  303. package/src/resources/extensions/gsd/tools/plan-slice.ts +54 -12
  304. package/src/resources/extensions/gsd/tools/plan-task.ts +8 -1
  305. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +71 -489
  306. package/src/resources/extensions/gsd/types.ts +1 -0
  307. package/src/resources/extensions/gsd/uat-policy.ts +191 -0
  308. package/src/resources/extensions/gsd/uat-run.ts +550 -0
  309. package/src/resources/extensions/gsd/unit-context-manifest.ts +3 -4
  310. package/src/resources/extensions/gsd/unit-tool-contracts.ts +38 -14
  311. package/src/resources/extensions/gsd/verdict-parser.ts +3 -10
  312. package/src/resources/extensions/gsd/workflow-manifest.ts +193 -7
  313. package/src/resources/extensions/gsd/workflow-mcp.ts +2 -3
  314. package/src/resources/extensions/gsd/workflow-projections.ts +9 -0
  315. package/src/resources/extensions/gsd/worktree-manager.ts +32 -0
  316. package/src/resources/extensions/gsd/worktree-reentry.ts +103 -0
  317. package/src/resources/extensions/gsd/worktree-state-projection.ts +22 -22
  318. package/src/resources/extensions/shared/gsd-browser-cli.ts +6 -0
  319. package/src/resources/extensions/shared/tests/format-utils.test.ts +8 -3
  320. package/src/resources/extensions/subagent/agents.ts +4 -0
  321. package/src/resources/extensions/subagent/index.ts +28 -3
  322. package/src/resources/extensions/subagent/launch.ts +8 -0
  323. package/src/resources/extensions/subagent/tests/model-override.test.ts +31 -0
  324. /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_buildManifest.js +0 -0
  325. /package/dist/web/standalone/.next/static/{9y3LeeR2uGr2yRj9RjY3D → tJOKQbQRO-9MiFDO8DIDS}/_ssgManifest.js +0 -0
@@ -20,82 +20,103 @@ export function resolveModelForUnit(unitType) {
20
20
  return resolved?.primary;
21
21
  }
22
22
  /**
23
- * Resolve model and fallbacks for a given auto-mode unit type.
24
- * Returns the primary model and ordered fallbacks, or undefined if not configured.
23
+ * Ordered phase-bucket chain a unit type resolves against, most-specific
24
+ * first. The first chain entry with a configured value wins; later entries
25
+ * are siblings the unit falls back to (e.g. `discuss → planning`).
25
26
  *
26
- * Supports both legacy string format and extended object format:
27
- * - Legacy: `planning: claude-opus-4-6`
28
- * - Extended: `planning: { model: claude-opus-4-6, fallbacks: [glm-5, minimax-m2.5] }`
27
+ * Single source of truth for the unit-type phase mapping, shared by model
28
+ * resolution (`resolveModelWithFallbacksForUnit`) and thinking resolution
29
+ * (`resolveThinkingLevelForUnit`) so the two never drift (ADR-026).
29
30
  */
30
- export function resolveModelWithFallbacksForUnit(unitType) {
31
- const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
32
- const models = prefs?.preferences?.models;
33
- if (!models)
34
- return undefined;
35
- const m = models;
36
- let phaseConfig;
31
+ export function phaseChainForUnit(unitType) {
37
32
  switch (unitType) {
38
33
  case "research-milestone":
39
34
  case "research-slice":
40
- phaseConfig = m.research;
41
- break;
35
+ // Deep-mode project research orchestrator. Reads PROJECT.md / REQUIREMENTS.md
36
+ // and fans out research subagents. Routes to the research bucket.
37
+ case "research-project":
38
+ return ["research"];
42
39
  case "plan-milestone":
43
40
  case "plan-slice":
44
41
  case "refine-slice":
45
42
  case "replan-slice":
46
- phaseConfig = m.planning;
47
- break;
43
+ return ["planning"];
44
+ // Deep-mode project-level discussion units route to the same model bucket
45
+ // as milestone-level discussion (interactive interview style). Workflow
46
+ // preferences and research-decision are tiny ask_user_questions style units
47
+ // that share the discuss bucket because they are conversational. All fall
48
+ // back to planning when no `discuss` bucket is set.
48
49
  case "discuss-milestone":
49
50
  case "discuss-slice":
50
- // Deep-mode project-level discussion units route to the same model
51
- // bucket as milestone-level discussion (interactive interview style).
52
51
  case "discuss-project":
53
52
  case "discuss-requirements":
54
- // Workflow preferences and research-decision are tiny ask_user_questions
55
- // style units; they share the discuss bucket because they are
56
- // conversational rather than research/execution. Falling back to planning
57
- // when no `discuss` bucket is set keeps parity with the milestone units.
58
53
  case "workflow-preferences":
59
54
  case "research-decision":
60
- phaseConfig = m.discuss ?? m.planning;
61
- break;
62
- // Deep-mode project research orchestrator. Reads PROJECT.md / REQUIREMENTS.md
63
- // and fans out research subagents. Routes to the research bucket so it
64
- // gets the research-tier model when one is configured.
65
- case "research-project":
66
- phaseConfig = m.research;
67
- break;
55
+ return ["discuss", "planning"];
68
56
  case "execute-task":
69
57
  case "reactive-execute":
70
- phaseConfig = m.execution;
71
- break;
58
+ return ["execution"];
72
59
  case "execute-task-simple":
73
- phaseConfig = m.execution_simple ?? m.execution;
74
- break;
60
+ return ["execution_simple", "execution"];
75
61
  case "complete-slice":
76
62
  case "complete-milestone":
77
63
  case "worktree-merge":
78
- phaseConfig = m.completion;
79
- break;
64
+ return ["completion"];
80
65
  case "run-uat":
81
- phaseConfig = m.uat ?? m.completion;
82
- break;
66
+ return ["uat", "completion"];
83
67
  case "reassess-roadmap":
84
68
  case "rewrite-docs":
85
69
  case "gate-evaluate":
86
70
  case "validate-milestone":
87
- phaseConfig = m.validation ?? m.planning;
88
- break;
71
+ return ["validation", "planning"];
89
72
  default:
90
73
  // Subagent unit types (e.g., "subagent", "subagent/scout")
91
74
  if (unitType === "subagent" || unitType.startsWith("subagent/")) {
92
- phaseConfig = m.subagent;
93
- break;
75
+ return ["subagent"];
94
76
  }
95
77
  return undefined;
96
78
  }
97
- if (!phaseConfig)
79
+ }
80
+ /**
81
+ * Find the phase bucket whose `models` entry wins the chain for a unit, plus
82
+ * that entry. Returns undefined when no phase in the chain is configured.
83
+ */
84
+ function resolveWinningPhase(models, chain) {
85
+ if (!models)
98
86
  return undefined;
87
+ for (const key of chain) {
88
+ const config = models[key];
89
+ // Falsy check (not `!= null`) so an empty-string model is treated as
90
+ // unconfigured and the chain falls through — matches the pre-refactor
91
+ // switch, which bailed via `if (!phaseConfig)`.
92
+ if (!config)
93
+ continue;
94
+ // An object entry only "wins" if it provides a usable model. A model-less
95
+ // object (e.g. `{ provider: x }`, or `{}` left after stripping an invalid
96
+ // `thinking`) must not shadow sibling fallback or yield `{ primary: undefined }`.
97
+ if (typeof config === "object" && !config.model)
98
+ continue;
99
+ return { phase: key, config };
100
+ }
101
+ return undefined;
102
+ }
103
+ /**
104
+ * Resolve model and fallbacks for a given auto-mode unit type.
105
+ * Returns the primary model and ordered fallbacks, or undefined if not configured.
106
+ *
107
+ * Supports both legacy string format and extended object format:
108
+ * - Legacy: `planning: claude-opus-4-6`
109
+ * - Extended: `planning: { model: claude-opus-4-6, fallbacks: [glm-5, minimax-m2.5] }`
110
+ */
111
+ export function resolveModelWithFallbacksForUnit(unitType) {
112
+ const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
113
+ const chain = phaseChainForUnit(unitType);
114
+ if (!chain)
115
+ return undefined;
116
+ const winner = resolveWinningPhase(prefs?.preferences?.models, chain);
117
+ if (!winner)
118
+ return undefined;
119
+ const phaseConfig = winner.config;
99
120
  // Normalize: string -> { model, fallbacks: [] }
100
121
  if (typeof phaseConfig === "string") {
101
122
  return { primary: phaseConfig, fallbacks: [] };
@@ -110,6 +131,52 @@ export function resolveModelWithFallbacksForUnit(unitType) {
110
131
  fallbacks: phaseConfig.fallbacks ?? [],
111
132
  };
112
133
  }
134
+ /**
135
+ * Resolve the explicitly configured reasoning effort for a unit type (ADR-026).
136
+ *
137
+ * Thinking travels with the model. The chain is walked most-specific-first up to
138
+ * and including the phase whose model won; at each level inline
139
+ * `models.<phase>.thinking` is preferred, then the same phase's `thinking` block
140
+ * entry. This means:
141
+ * - a more-specific block key (`thinking.execution_simple`) surfaces even when
142
+ * the model only resolves on a less-specific sibling (`models.execution`);
143
+ * - inline thinking is honored even on a model-less `models.<phase>` entry
144
+ * (e.g. `{ thinking: "high" }` with no `model`);
145
+ * - a unit that claimed its own model bucket never borrows a *less*-specific
146
+ * sibling's thinking (the walk stops at the winning phase).
147
+ * When no model is configured anywhere in the chain, the walk spans the full
148
+ * chain so inline thinking and the `thinking` block both resolve on their own
149
+ * sibling chain.
150
+ *
151
+ * Returns undefined when nothing explicit is configured — the dispatch path
152
+ * then falls back to the session/default level and applies the code-writing
153
+ * floor. Session level, defaults, the floor, and capability clamping are NOT
154
+ * applied here.
155
+ */
156
+ export function resolveThinkingLevelForUnit(unitType) {
157
+ const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] })?.preferences;
158
+ if (!prefs)
159
+ return undefined;
160
+ const chain = phaseChainForUnit(unitType);
161
+ if (!chain)
162
+ return undefined;
163
+ const models = prefs.models;
164
+ const block = prefs.thinking;
165
+ // Walk most-specific-first, up to and including the winning model phase (or
166
+ // the full chain when no model is configured), checking inline then block.
167
+ const winner = resolveWinningPhase(models, chain);
168
+ const limit = winner ? chain.indexOf(winner.phase) + 1 : chain.length;
169
+ for (let i = 0; i < limit; i++) {
170
+ const key = chain[i];
171
+ const entry = models?.[key];
172
+ if (typeof entry === "object" && entry?.thinking)
173
+ return entry.thinking; // inline (incl. model-less)
174
+ const blockLevel = block?.[key];
175
+ if (blockLevel)
176
+ return blockLevel; // block
177
+ }
178
+ return undefined;
179
+ }
113
180
  /**
114
181
  * Resolve the default session model from GSD preferences.
115
182
  *
@@ -339,6 +406,7 @@ export function resolveAutoSupervisorConfig() {
339
406
  soft_timeout_minutes: configured.soft_timeout_minutes ?? 20,
340
407
  idle_timeout_minutes: configured.idle_timeout_minutes ?? 10,
341
408
  hard_timeout_minutes: configured.hard_timeout_minutes ?? 30,
409
+ stalled_tool_timeout_minutes: configured.stalled_tool_timeout_minutes ?? 5,
342
410
  ...(configured.model ? { model: configured.model } : {}),
343
411
  };
344
412
  }
@@ -46,6 +46,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
46
46
  "skill_rules",
47
47
  "custom_instructions",
48
48
  "models",
49
+ "thinking",
49
50
  "skill_discovery",
50
51
  "skill_staleness_days",
51
52
  "auto_supervisor",
@@ -133,6 +134,18 @@ export const KNOWN_UNIT_LABELS = [
133
134
  "research-decision", "research-project",
134
135
  ];
135
136
  export const SKILL_ACTIONS = new Set(["use", "prefer", "avoid"]);
137
+ /** The nine model-routing phase buckets. */
138
+ export const GSD_MODEL_PHASE_KEYS = [
139
+ "research",
140
+ "planning",
141
+ "discuss",
142
+ "execution",
143
+ "execution_simple",
144
+ "completion",
145
+ "validation",
146
+ "subagent",
147
+ "uat",
148
+ ];
136
149
  /**
137
150
  * Format a skill reference for the system prompt.
138
151
  * If resolved, shows the path so the agent knows exactly where to read.
@@ -8,8 +8,18 @@
8
8
  import { isAbsolute } from "node:path";
9
9
  import { VALID_BRANCH_NAME } from "./git-service.js";
10
10
  import { normalizeStringArray } from "../shared/format-utils.js";
11
- import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_LABELS, SKILL_ACTIONS, } from "./preferences-types.js";
11
+ import { getGateIdsForTurn } from "./gate-registry.js";
12
+ import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_LABELS, GSD_MODEL_PHASE_KEYS, SKILL_ACTIONS, } from "./preferences-types.js";
12
13
  const VALID_TOKEN_PROFILES = new Set(["budget", "balanced", "quality", "burn-max"]);
14
+ const VALID_THINKING_LEVELS = new Set([
15
+ "off",
16
+ "minimal",
17
+ "low",
18
+ "medium",
19
+ "high",
20
+ "xhigh",
21
+ ]);
22
+ const KNOWN_MODEL_PHASE_KEYS = new Set(GSD_MODEL_PHASE_KEYS);
13
23
  const VALID_UOK_TURN_ACTIONS = new Set([
14
24
  "commit",
15
25
  "snapshot",
@@ -23,6 +33,7 @@ const VALID_POST_UNIT_HOOK_ON_BLOCK_ACTIONS = new Set([
23
33
  "queue-slice",
24
34
  "pause",
25
35
  ]);
36
+ const VALID_GATE_EVALUATE_SLICE_GATES = new Set(getGateIdsForTurn("gate-evaluate"));
26
37
  export function validatePreferences(preferences) {
27
38
  const errors = [];
28
39
  const warnings = [];
@@ -375,12 +386,60 @@ export function validatePreferences(preferences) {
375
386
  // ─── Models ─────────────────────────────────────────────────────────
376
387
  if (preferences.models !== undefined) {
377
388
  if (preferences.models && typeof preferences.models === "object") {
378
- validated.models = preferences.models;
389
+ // Static check for inline per-phase thinking (ADR-026). The resolved
390
+ // model isn't known until dispatch, so capability is clamped there; here
391
+ // we warn on illegal level strings AND strip them, so a typo can't reach
392
+ // resolveThinkingLevelForUnit and be treated as explicit configuration.
393
+ const sanitizedModels = {};
394
+ for (const [phase, entry] of Object.entries(preferences.models)) {
395
+ if (entry && typeof entry === "object" && "thinking" in entry) {
396
+ const level = entry.thinking;
397
+ if (level !== undefined && !VALID_THINKING_LEVELS.has(level)) {
398
+ warnings.push(`models.${phase}.thinking "${String(level)}" is not a valid thinking level ` +
399
+ `(off, minimal, low, medium, high, xhigh) — ignored`);
400
+ const { thinking: _ignored, ...rest } = entry;
401
+ // If stripping the bad thinking leaves no usable model, drop the
402
+ // phase entirely rather than storing a hollow `{}` / `{ provider }`
403
+ // entry that resolveWinningPhase would otherwise treat as configured.
404
+ if (rest.model) {
405
+ sanitizedModels[phase] = rest;
406
+ }
407
+ continue;
408
+ }
409
+ }
410
+ sanitizedModels[phase] = entry;
411
+ }
412
+ validated.models = sanitizedModels;
379
413
  }
380
414
  else {
381
415
  errors.push("models must be an object");
382
416
  }
383
417
  }
418
+ // ─── Thinking (separate per-phase block, ADR-026) ───────────────────
419
+ if (preferences.thinking !== undefined) {
420
+ if (preferences.thinking && typeof preferences.thinking === "object" && !Array.isArray(preferences.thinking)) {
421
+ const validatedThinking = {};
422
+ for (const [phase, level] of Object.entries(preferences.thinking)) {
423
+ if (!KNOWN_MODEL_PHASE_KEYS.has(phase)) {
424
+ warnings.push(`unknown thinking phase "${phase}" — must be one of: ` +
425
+ `${[...KNOWN_MODEL_PHASE_KEYS].join(", ")} — ignored`);
426
+ continue;
427
+ }
428
+ if (!VALID_THINKING_LEVELS.has(level)) {
429
+ warnings.push(`thinking.${phase} "${String(level)}" is not a valid thinking level ` +
430
+ `(off, minimal, low, medium, high, xhigh) — ignored`);
431
+ continue;
432
+ }
433
+ validatedThinking[phase] = level;
434
+ }
435
+ if (Object.keys(validatedThinking).length > 0) {
436
+ validated.thinking = validatedThinking;
437
+ }
438
+ }
439
+ else {
440
+ errors.push("thinking must be an object");
441
+ }
442
+ }
384
443
  // ─── Auto Supervisor ────────────────────────────────────────────────
385
444
  if (preferences.auto_supervisor !== undefined) {
386
445
  if (preferences.auto_supervisor && typeof preferences.auto_supervisor === "object") {
@@ -931,7 +990,13 @@ export function validatePreferences(preferences) {
931
990
  }
932
991
  if (ge.slice_gates !== undefined) {
933
992
  if (Array.isArray(ge.slice_gates) && ge.slice_gates.every((g) => typeof g === "string")) {
934
- validGe.slice_gates = ge.slice_gates;
993
+ const invalid = ge.slice_gates.filter((g) => !VALID_GATE_EVALUATE_SLICE_GATES.has(g));
994
+ if (invalid.length === 0) {
995
+ validGe.slice_gates = ge.slice_gates;
996
+ }
997
+ else {
998
+ errors.push(`gate_evaluation.slice_gates must contain only gate-evaluate slice gates: ${[...VALID_GATE_EVALUATE_SLICE_GATES].join(", ")}`);
999
+ }
935
1000
  }
936
1001
  else {
937
1002
  errors.push("gate_evaluation.slice_gates must be an array of strings");
@@ -37,7 +37,7 @@ export function resolveSkillStalenessDays(basePath) {
37
37
  return prefs?.preferences.skill_staleness_days ?? 60;
38
38
  }
39
39
  // ─── Re-exports: models ─────────────────────────────────────────────────────
40
- export { resolveModelForUnit, resolveModelWithFallbacksForUnit, getNextFallbackModel, isTransientNetworkError, validateModelId, updatePreferencesModels, resolveDynamicRoutingConfig, resolveAutoSupervisorConfig, resolveProfileDefaults, getProfileTierMap, resolveEffectiveProfile, resolveInlineLevel, resolveContextSelection, resolveSearchProviderFromPreferences, resolveDisabledModelProvidersFromPreferences, } from "./preferences-models.js";
40
+ export { resolveModelForUnit, resolveModelWithFallbacksForUnit, resolveThinkingLevelForUnit, phaseChainForUnit, getNextFallbackModel, isTransientNetworkError, validateModelId, updatePreferencesModels, resolveDynamicRoutingConfig, resolveAutoSupervisorConfig, resolveProfileDefaults, getProfileTierMap, resolveEffectiveProfile, resolveInlineLevel, resolveContextSelection, resolveSearchProviderFromPreferences, resolveDisabledModelProvidersFromPreferences, } from "./preferences-models.js";
41
41
  // ─── Re-exports: MCP ────────────────────────────────────────────────────────
42
42
  export { resolveModelMcpConfig } from "./preferences-mcp.js";
43
43
  // ─── Path Constants & Getters ───────────────────────────────────────────────
@@ -330,6 +330,9 @@ function mergePreferences(base, override) {
330
330
  skill_rules: [...(base.skill_rules ?? []), ...(override.skill_rules ?? [])],
331
331
  custom_instructions: mergeStringLists(base.custom_instructions, override.custom_instructions),
332
332
  models: { ...(base.models ?? {}), ...(override.models ?? {}) },
333
+ thinking: (base.thinking || override.thinking)
334
+ ? { ...(base.thinking ?? {}), ...(override.thinking ?? {}) }
335
+ : undefined,
333
336
  skill_discovery: override.skill_discovery ?? base.skill_discovery,
334
337
  skill_staleness_days: override.skill_staleness_days ?? base.skill_staleness_days,
335
338
  auto_supervisor: { ...(base.auto_supervisor ?? {}), ...(override.auto_supervisor ?? {}) },
@@ -38,7 +38,7 @@ You are evaluating **quality gates in parallel** for this slice. Each gate is an
38
38
  3. **Verify each gate wrote its result** by checking that `gsd_save_gate_result` was called for each gate ID.
39
39
  - Call it **directly** — do **not** use `ToolSearch` (it is not available in GSD).
40
40
  - Inside Claude Code use the active MCP-scoped workflow name for `gsd_save_gate_result`; otherwise use `gsd_save_gate_result`.
41
- - Always pass all required fields (camelCase): `milestoneId`, `sliceId`, `gateId`, `verdict`, `rationale`. Never call with an empty `{}` object.
41
+ - Always pass all required fields (camelCase): `milestoneId`, `sliceId`, `gateId`, `verdict`, `rationale`, and `findings` (empty string if none). Never call with an empty `{}` object.
42
42
  4. **Report the batch outcome** — which gates passed, which flagged concerns, and which were omitted as not applicable.
43
43
 
44
44
  Gate agents may return `verdict: "omitted"` if the gate question is not applicable to this slice (e.g., no auth surface for Q3, no existing requirements touched for Q4). This is expected for simple slices.
@@ -14,7 +14,7 @@ All relevant context is preloaded below. Start immediately without re-reading th
14
14
 
15
15
  ## Already Planned? Soft Brake
16
16
 
17
- If `{{outputPath}}` exists with at least one slice line (e.g. `- [ ] **S01:`) AND `gsd_query` reports slice rows for this milestone, a prior `gsd_plan_milestone` call already persisted the plan. Do **not** re-call it; its UPSERT could overwrite existing planning. Skip to the ready phrase.
17
+ If `{{outputPath}}` exists with at least one slice line (e.g. `- [ ] **S01:`) AND `gsd_milestone_status` reports slice rows for this milestone, a prior `gsd_plan_milestone` call already persisted the plan. Do **not** re-call it; its UPSERT could overwrite existing planning. Skip to the ready phrase.
18
18
 
19
19
  If only the file or only DB rows exist, the prior write was incomplete; plan normally so the tool reconciles both.
20
20
 
@@ -44,7 +44,7 @@ If slice research is inlined, trust its architectural findings, but verify every
44
44
  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.
45
45
  7. Right-size tasks. Simple slices can be one task; split only when context, ownership, or verification boundaries justify it.
46
46
  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.
47
- 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, or tests — those belong only in `inputs`. If a task is a pure verification or test task that produces no new files, `expectedOutput` may be `[]` or limited to test-result artifacts (e.g. a log or assertion output). 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.
47
+ 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
48
  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.
49
49
  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.
50
50
  12. If planning creates structural decisions, call `gsd_decision_save` for each; the tool persists the decision and regenerates `.gsd/DECISIONS.md`.
@@ -64,7 +64,7 @@ Then:
64
64
  2. {{skillActivation}} Record the installed skills you expect executors to use in each task plan's `skills_used` frontmatter.
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
  4. For non-trivial slices, plan observability / proof level / integration closure, threat surface, and requirement impact. Omit entirely for simple slices.
67
- 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"`).
67
+ 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
68
  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.
69
69
  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.
70
70
  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`.
@@ -27,7 +27,7 @@ You are the UAT runner. Execute every check defined in `{{uatPath}}` as deeply a
27
27
  ### Automation rules by mode
28
28
 
29
29
  - `artifact-driven` — verify with shell commands, scripts, file reads, and artifact structure checks.
30
- - `browser-executable` — use gsd-browser tools to navigate to the target URL and verify expected behavior. Prefer `mcp__gsd-browser__browser_*` tools when namespaced, or direct `browser_*` tools when surfaced without a namespace. Capture screenshots as evidence. Record pass/fail with specific assertions.
30
+ - `browser-executable` — use browser tools to navigate to the target URL and verify expected behavior. Prefer direct `browser_*` tools when available. Capture screenshots as evidence. Record pass/fail with specific assertions.
31
31
  - `runtime-executable` — execute the specified command or script. Capture stdout/stderr as evidence. Record pass/fail based on exit code and output.
32
32
  - `live-runtime` — exercise the real runtime path. Start or connect to the app/service if needed, use browser/runtime/network checks, and verify observable behavior.
33
33
  - `mixed` — run all automatable artifact-driven and live-runtime checks. Separate any remaining human-only checks explicitly.
@@ -48,7 +48,7 @@ Choose the lightest tool that proves the check honestly:
48
48
  - Run `node` / other script invocations
49
49
  - Read files and verify their contents
50
50
  - Check that expected artifacts exist and have correct structure
51
- - For live/runtime/UI checks, exercise the real flow with gsd-browser when applicable and inspect runtime/network/console state
51
+ - For live/runtime/UI checks, exercise the real flow with browser tools when applicable and inspect runtime/network/console state
52
52
  - When a check cannot be honestly automated, gather the best objective evidence you can and mark it `NEEDS-HUMAN`
53
53
 
54
54
  For each check, record:
@@ -118,7 +118,7 @@ Templates are in `{{templatesDir}}`.
118
118
 
119
119
  **Secrets:** Use `secure_env_collect`. Never ask the user to edit `.env` files or paste secrets.
120
120
 
121
- **Browser verification:** Verify frontend work against a running app with gsd-browser by default. Use `browser_find`/`browser_snapshot_refs` for discovery, refs/selectors -> `browser_batch` for actions, `browser_assert` for verification, and `browser_diff` -> console/network logs -> full inspection as last resort. If tools are MCP-namespaced, prefer `mcp__gsd-browser__browser_*`. Retry only with a new hypothesis.
121
+ **Browser verification:** Verify frontend work against a running app with browser tools by default. Use `browser_find`/`browser_snapshot_refs` for discovery, refs/selectors -> `browser_batch` for actions, `browser_assert` for verification, and `browser_diff` -> console/network logs -> full inspection as last resort. If browser tools are MCP-namespaced, use that host-provided browser surface. Retry only with a new hypothesis.
122
122
 
123
123
  **Database:** Never query `.gsd/gsd.db` directly via `sqlite3`, `better-sqlite3`, or `node -e require('better-sqlite3')`; the engine owns a single-writer WAL connection. Use `gsd_milestone_status`, `gsd_journal_query`, or other `gsd_*` tools.
124
124
 
@@ -194,7 +194,11 @@ export function parseRoadmapSlices(content) {
194
194
  const depends = depsMatch && depsMatch[1].trim()
195
195
  ? expandDependencies(depsMatch[1].split(",").map(s => s.trim()))
196
196
  : [];
197
- currentSlice = { id, title, risk, depends, done, demo: "" };
197
+ // ADR-011: the renderer writes a `[sketch]` badge for sketch slices.
198
+ // Parse it back so the is_sketch flag survives a markdown → DB re-import
199
+ // (e.g. /gsd recover); otherwise the flag was silently lost.
200
+ const isSketch = /\[sketch\]/i.test(rest);
201
+ currentSlice = { id, title, risk, depends, done, demo: "", isSketch };
198
202
  continue;
199
203
  }
200
204
  if (currentSlice && line.trim().startsWith(">")) {
@@ -29,6 +29,8 @@ export function validateContent(unitType, artifactPath) {
29
29
  return [];
30
30
  }
31
31
  }
32
+ const TASK_MARKER_RE = /^\s*(?:-\s+\[[ xX]\]\s+\*\*T\d+:|#{2,4}\s+T\d+\b)/gm;
33
+ const SLICE_MARKER_RE = /^\s*(?:-\s+\[[ xX]\]\s+\*\*S\d+:|#{2,4}\s+S\d+\b)/gm;
32
34
  const VALIDATORS = {
33
35
  "plan-slice": validatePlanSlice,
34
36
  "plan-milestone": validatePlanMilestone,
@@ -36,10 +38,10 @@ const VALIDATORS = {
36
38
  function validatePlanSlice(content) {
37
39
  const violations = [];
38
40
  // Must have at least 1 task entry — single-task slices are valid (#3649)
39
- const taskCount = (content.match(/- \[[ x]\] \*\*T\d+/g) || []).length;
41
+ const taskCount = (content.match(TASK_MARKER_RE) || []).length;
40
42
  if (taskCount < 1) {
41
43
  violations.push({
42
- severity: "warning",
44
+ severity: "error",
43
45
  reason: `Slice plan has ${taskCount} task(s) — expected at least 1`,
44
46
  });
45
47
  }
@@ -62,10 +64,10 @@ function validatePlanSlice(content) {
62
64
  function validatePlanMilestone(content) {
63
65
  const violations = [];
64
66
  // Must have at least 1 slice entry
65
- const sliceCount = (content.match(/##\s+S\d+/g) || []).length;
67
+ const sliceCount = (content.match(SLICE_MARKER_RE) || []).length;
66
68
  if (sliceCount < 1) {
67
69
  violations.push({
68
- severity: "warning",
70
+ severity: "error",
69
71
  reason: `Milestone roadmap has ${sliceCount} slice(s) — expected at least 1`,
70
72
  });
71
73
  }
@@ -114,6 +114,18 @@ const UNIT_TYPE_SKILL_MANIFEST = {
114
114
  "review",
115
115
  "accessibility",
116
116
  ],
117
+ // Slice closeout — the "closer" role: verify assembled task work, write the
118
+ // downstream-ready summary + UAT, optionally drive reviewer/security/tester
119
+ // subagents. Predictable skill set, mirrors `complete-milestone`.
120
+ "complete-slice": [
121
+ "verify-before-complete",
122
+ "test",
123
+ "review",
124
+ "security-review",
125
+ "write-docs",
126
+ "observability",
127
+ "handoff",
128
+ ],
117
129
  // `execute-task` intentionally omitted — implementation hot path covers a
118
130
  // wide surface of technologies; wildcard fallback preserves today's
119
131
  // behavior until per-task skill hints can be derived from task-plan