@opengsd/gsd-pi 1.2.0-dev.fb12b103 → 1.2.0-dev.fbdca60b

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 (580) hide show
  1. package/dist/cli-model-override.d.ts +15 -0
  2. package/dist/cli-model-override.js +21 -0
  3. package/dist/cli.js +1 -18
  4. package/dist/headless-events.js +7 -5
  5. package/dist/loader.js +6 -4
  6. package/dist/mcp-server.js +2 -1
  7. package/dist/register-agent-bundles.d.ts +11 -2
  8. package/dist/register-agent-bundles.js +18 -4
  9. package/dist/resource-loader.d.ts +10 -5
  10. package/dist/resource-loader.js +121 -6
  11. package/dist/resources/.managed-resources-content-hash +1 -1
  12. package/dist/resources/GSD-WORKFLOW.md +5 -4
  13. package/dist/resources/extensions/ask-user-questions.js +3 -2
  14. package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
  15. package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
  16. package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
  17. package/dist/resources/extensions/gsd/auto/custom-verify-retry-store.js +17 -2
  18. package/dist/resources/extensions/gsd/auto/detect-stuck.js +33 -13
  19. package/dist/resources/extensions/gsd/auto/dispatch-history.js +120 -0
  20. package/dist/resources/extensions/gsd/auto/dispatch-key.js +37 -0
  21. package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
  22. package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
  23. package/dist/resources/extensions/gsd/auto/loop.js +7 -1
  24. package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
  25. package/dist/resources/extensions/gsd/auto/orchestrator.js +167 -64
  26. package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
  27. package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
  28. package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
  29. package/dist/resources/extensions/gsd/auto/session.js +3 -0
  30. package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
  31. package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
  32. package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
  33. package/dist/resources/extensions/gsd/auto-direct-dispatch.js +11 -34
  34. package/dist/resources/extensions/gsd/auto-dispatch.js +39 -58
  35. package/dist/resources/extensions/gsd/auto-model-selection.js +11 -7
  36. package/dist/resources/extensions/gsd/auto-post-unit.js +30 -12
  37. package/dist/resources/extensions/gsd/auto-prompts.js +66 -9
  38. package/dist/resources/extensions/gsd/auto-start.js +26 -8
  39. package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
  40. package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +5 -4
  41. package/dist/resources/extensions/gsd/auto-verification.js +23 -30
  42. package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
  43. package/dist/resources/extensions/gsd/auto.js +52 -2
  44. package/dist/resources/extensions/gsd/blocked-models.js +28 -0
  45. package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +26 -6
  46. package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
  47. package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +2 -2
  48. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +107 -45
  49. package/dist/resources/extensions/gsd/bootstrap/write-gate.js +302 -80
  50. package/dist/resources/extensions/gsd/closeout-wizard.js +92 -0
  51. package/dist/resources/extensions/gsd/commands/context.js +16 -2
  52. package/dist/resources/extensions/gsd/commands-handlers.js +46 -3
  53. package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
  54. package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
  55. package/dist/resources/extensions/gsd/consent-question.js +353 -0
  56. package/dist/resources/extensions/gsd/consent-verdict.js +63 -0
  57. package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
  58. package/dist/resources/extensions/gsd/db/engine.js +24 -6
  59. package/dist/resources/extensions/gsd/db/queries.js +56 -0
  60. package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
  61. package/dist/resources/extensions/gsd/db-transaction.js +27 -23
  62. package/dist/resources/extensions/gsd/db-writer.js +8 -17
  63. package/dist/resources/extensions/gsd/dispatch-guard.js +10 -35
  64. package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
  65. package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
  66. package/dist/resources/extensions/gsd/doctor-git-checks.js +2 -18
  67. package/dist/resources/extensions/gsd/engine-hook-contract.js +70 -0
  68. package/dist/resources/extensions/gsd/files.js +33 -19
  69. package/dist/resources/extensions/gsd/gsd-command-home.js +22 -12
  70. package/dist/resources/extensions/gsd/gsd-db.js +17 -21
  71. package/dist/resources/extensions/gsd/guidance.js +60 -0
  72. package/dist/resources/extensions/gsd/guided-flow.js +93 -4
  73. package/dist/resources/extensions/gsd/health-widget.js +87 -28
  74. package/dist/resources/extensions/gsd/markdown-renderer.js +10 -0
  75. package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
  76. package/dist/resources/extensions/gsd/memory-relations.js +1 -1
  77. package/dist/resources/extensions/gsd/milestone-closeout.js +85 -24
  78. package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
  79. package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
  80. package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
  81. package/dist/resources/extensions/gsd/notifications.js +12 -7
  82. package/dist/resources/extensions/gsd/parsers-legacy.js +16 -4
  83. package/dist/resources/extensions/gsd/projection-flush.js +7 -0
  84. package/dist/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  85. package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
  86. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  87. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  88. package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
  89. package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  90. package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  91. package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  92. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  93. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  94. package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  95. package/dist/resources/extensions/gsd/prompts/run-uat.md +8 -4
  96. package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  97. package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  98. package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  99. package/dist/resources/extensions/gsd/reactive-graph.js +8 -1
  100. package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
  101. package/dist/resources/extensions/gsd/session-lock.js +1 -1
  102. package/dist/resources/extensions/gsd/skill-activation.js +3 -6
  103. package/dist/resources/extensions/gsd/state.js +11 -2
  104. package/dist/resources/extensions/gsd/tool-contract.js +14 -3
  105. package/dist/resources/extensions/gsd/tool-presentation-plan.js +4 -4
  106. package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
  107. package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
  108. package/dist/resources/extensions/gsd/tools/complete-slice.js +22 -12
  109. package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
  110. package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
  111. package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
  112. package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
  113. package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
  114. package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
  115. package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
  116. package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
  117. package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +67 -2
  118. package/dist/resources/extensions/gsd/uat-policy.js +40 -15
  119. package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
  120. package/dist/resources/extensions/gsd/unit-registry.js +34 -4
  121. package/dist/resources/extensions/gsd/verdict-parser.js +1 -1
  122. package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
  123. package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
  124. package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
  125. package/dist/resources/extensions/gsd/workflow-events.js +6 -18
  126. package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
  127. package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
  128. package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
  129. package/dist/resources/extensions/gsd/worktree-lifecycle.js +3 -2
  130. package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
  131. package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
  132. package/dist/resources/extensions/gsd/worktree.js +8 -1
  133. package/dist/resources/extensions/mcp-client/manager.js +6 -1
  134. package/dist/resources/extensions/shared/gsd-browser-cli.js +21 -2
  135. package/dist/resources/shared/gsd-browser-path-sync.js +214 -0
  136. package/dist/resources/shared/package-manager-detection.js +1 -1
  137. package/dist/resources/skills/create-skill/SKILL.md +3 -0
  138. package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
  139. package/dist/runtime-checks.d.ts +10 -0
  140. package/dist/runtime-checks.js +27 -0
  141. package/dist/tsconfig.extensions.tsbuildinfo +1 -1
  142. package/dist/update-check.d.ts +2 -0
  143. package/dist/update-check.js +24 -1
  144. package/dist/update-cmd.js +20 -3
  145. package/dist/web/standalone/.next/BUILD_ID +1 -1
  146. package/dist/web/standalone/.next/app-path-routes-manifest.json +6 -6
  147. package/dist/web/standalone/.next/build-manifest.json +2 -2
  148. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  149. package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
  150. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  151. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  152. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  153. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  154. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  155. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  156. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  157. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  158. package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
  159. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  160. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  161. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  162. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  163. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  164. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  165. package/dist/web/standalone/.next/server/app/api/boot/route.js.nft.json +1 -1
  166. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
  167. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
  168. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
  169. package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
  170. package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
  171. package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
  172. package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
  173. package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
  174. package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
  175. package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
  176. package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
  177. package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
  178. package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
  179. package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
  180. package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
  181. package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
  182. package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  183. package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
  184. package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  185. package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
  186. package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
  187. package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
  188. package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
  189. package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
  190. package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
  191. package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
  192. package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
  193. package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
  194. package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
  197. package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
  198. package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +1 -1
  199. package/dist/web/standalone/.next/server/app/index.html +1 -1
  200. package/dist/web/standalone/.next/server/app/index.rsc +1 -1
  201. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  202. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
  203. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  204. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  205. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  206. package/dist/web/standalone/.next/server/app-paths-manifest.json +6 -6
  207. package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
  208. package/dist/web/standalone/.next/server/chunks/8357.js +2 -2
  209. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  210. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  211. package/dist/web/standalone/.next/server/pages/500.html +1 -1
  212. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  213. package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
  214. package/dist/web/standalone/node_modules/postcss/lib/container.js +26 -18
  215. package/dist/web/standalone/node_modules/postcss/lib/css-syntax-error.js +47 -14
  216. package/dist/web/standalone/node_modules/postcss/lib/declaration.js +4 -4
  217. package/dist/web/standalone/node_modules/postcss/lib/fromJSON.js +3 -3
  218. package/dist/web/standalone/node_modules/postcss/lib/input.js +54 -29
  219. package/dist/web/standalone/node_modules/postcss/lib/lazy-result.js +47 -37
  220. package/dist/web/standalone/node_modules/postcss/lib/map-generator.js +26 -9
  221. package/dist/web/standalone/node_modules/postcss/lib/no-work-result.js +57 -55
  222. package/dist/web/standalone/node_modules/postcss/lib/node.js +99 -31
  223. package/dist/web/standalone/node_modules/postcss/lib/parse.js +1 -1
  224. package/dist/web/standalone/node_modules/postcss/lib/parser.js +10 -9
  225. package/dist/web/standalone/node_modules/postcss/lib/postcss.js +12 -12
  226. package/dist/web/standalone/node_modules/postcss/lib/previous-map.js +30 -11
  227. package/dist/web/standalone/node_modules/postcss/lib/processor.js +7 -7
  228. package/dist/web/standalone/node_modules/postcss/lib/result.js +5 -5
  229. package/dist/web/standalone/node_modules/postcss/lib/rule.js +6 -6
  230. package/dist/web/standalone/node_modules/postcss/lib/stringifier.js +69 -28
  231. package/dist/web/standalone/node_modules/postcss/lib/tokenize.js +6 -2
  232. package/dist/web/standalone/node_modules/postcss/package.json +48 -48
  233. package/package.json +3 -3
  234. package/packages/cloud-mcp-gateway/package.json +2 -2
  235. package/packages/contracts/package.json +1 -1
  236. package/packages/daemon/package.json +4 -4
  237. package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
  238. package/packages/gsd-agent-core/dist/sdk.js +6 -4
  239. package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
  240. package/packages/gsd-agent-core/package.json +5 -5
  241. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  242. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  243. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
  244. package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
  245. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
  246. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  247. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +50 -6
  248. package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
  249. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
  250. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
  251. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
  252. package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
  253. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
  254. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  255. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
  256. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
  257. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
  258. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
  259. package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
  260. package/packages/gsd-agent-modes/package.json +7 -7
  261. package/packages/mcp-server/README.md +12 -3
  262. package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
  263. package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
  264. package/packages/mcp-server/dist/cli-runner.js +137 -0
  265. package/packages/mcp-server/dist/cli-runner.js.map +1 -0
  266. package/packages/mcp-server/dist/cli.js +2 -53
  267. package/packages/mcp-server/dist/cli.js.map +1 -1
  268. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts +29 -0
  269. package/packages/mcp-server/dist/moonshot-tool-schema.d.ts.map +1 -0
  270. package/packages/mcp-server/dist/moonshot-tool-schema.js +50 -0
  271. package/packages/mcp-server/dist/moonshot-tool-schema.js.map +1 -0
  272. package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
  273. package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
  274. package/packages/mcp-server/dist/pid-registry.js +459 -0
  275. package/packages/mcp-server/dist/pid-registry.js.map +1 -0
  276. package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
  277. package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
  278. package/packages/mcp-server/dist/probe-mode.js +10 -0
  279. package/packages/mcp-server/dist/probe-mode.js.map +1 -0
  280. package/packages/mcp-server/dist/server.d.ts.map +1 -1
  281. package/packages/mcp-server/dist/server.js +4 -0
  282. package/packages/mcp-server/dist/server.js.map +1 -1
  283. package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
  284. package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
  285. package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
  286. package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
  287. package/packages/mcp-server/dist/workflow-tools.d.ts +18 -18
  288. package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
  289. package/packages/mcp-server/dist/workflow-tools.js +161 -81
  290. package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
  291. package/packages/mcp-server/package.json +5 -4
  292. package/packages/native/package.json +1 -1
  293. package/packages/pi-agent-core/dist/agent-loop.js +43 -2
  294. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  295. package/packages/pi-agent-core/package.json +1 -1
  296. package/packages/pi-ai/README.md +1 -0
  297. package/packages/pi-ai/dist/image-models.generated.d.ts +2 -2
  298. package/packages/pi-ai/dist/image-models.generated.js +6 -6
  299. package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
  300. package/packages/pi-ai/dist/index.d.ts +2 -0
  301. package/packages/pi-ai/dist/index.d.ts.map +1 -1
  302. package/packages/pi-ai/dist/index.js +2 -0
  303. package/packages/pi-ai/dist/index.js.map +1 -1
  304. package/packages/pi-ai/dist/models.generated.d.ts +419 -221
  305. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  306. package/packages/pi-ai/dist/models.generated.js +468 -269
  307. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  308. package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  309. package/packages/pi-ai/dist/providers/anthropic.js +12 -7
  310. package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
  311. package/packages/pi-ai/dist/providers/google-shared.d.ts +5 -0
  312. package/packages/pi-ai/dist/providers/google-shared.d.ts.map +1 -1
  313. package/packages/pi-ai/dist/providers/google-shared.js +12 -3
  314. package/packages/pi-ai/dist/providers/google-shared.js.map +1 -1
  315. package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  316. package/packages/pi-ai/dist/providers/openai-completions.js +7 -3
  317. package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
  318. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts +9 -0
  319. package/packages/pi-ai/dist/utils/moonshot-tool-schema.d.ts.map +1 -0
  320. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js +34 -0
  321. package/packages/pi-ai/dist/utils/moonshot-tool-schema.js.map +1 -0
  322. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  323. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +6 -2
  324. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  325. package/packages/pi-ai/package.json +3 -2
  326. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  327. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  328. package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
  329. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  330. package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
  331. package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
  332. package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
  333. package/packages/pi-coding-agent/package.json +7 -7
  334. package/packages/pi-tui/README.md +15 -0
  335. package/packages/pi-tui/dist/index.d.ts +2 -2
  336. package/packages/pi-tui/dist/index.d.ts.map +1 -1
  337. package/packages/pi-tui/dist/index.js +2 -2
  338. package/packages/pi-tui/dist/index.js.map +1 -1
  339. package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
  340. package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
  341. package/packages/pi-tui/dist/terminal-image.js +54 -2
  342. package/packages/pi-tui/dist/terminal-image.js.map +1 -1
  343. package/packages/pi-tui/dist/terminal.d.ts +12 -0
  344. package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
  345. package/packages/pi-tui/dist/terminal.js +70 -25
  346. package/packages/pi-tui/dist/terminal.js.map +1 -1
  347. package/packages/pi-tui/dist/tui.d.ts +15 -0
  348. package/packages/pi-tui/dist/tui.d.ts.map +1 -1
  349. package/packages/pi-tui/dist/tui.js +106 -21
  350. package/packages/pi-tui/dist/tui.js.map +1 -1
  351. package/packages/pi-tui/dist/utils.d.ts.map +1 -1
  352. package/packages/pi-tui/dist/utils.js +110 -36
  353. package/packages/pi-tui/dist/utils.js.map +1 -1
  354. package/packages/pi-tui/package.json +2 -2
  355. package/packages/rpc-client/package.json +2 -2
  356. package/pkg/dist/theme/theme.d.ts.map +1 -1
  357. package/pkg/dist/theme/theme.js +45 -17
  358. package/pkg/dist/theme/theme.js.map +1 -1
  359. package/pkg/package.json +1 -1
  360. package/src/resources/GSD-WORKFLOW.md +5 -4
  361. package/src/resources/extensions/ask-user-questions.ts +7 -2
  362. package/src/resources/extensions/browser-tools/tests/gsd-browser-launch-config.test.mjs +11 -0
  363. package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
  364. package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
  365. package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
  366. package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
  367. package/src/resources/extensions/gsd/auto/custom-verify-retry-store.ts +21 -3
  368. package/src/resources/extensions/gsd/auto/detect-stuck.ts +32 -9
  369. package/src/resources/extensions/gsd/auto/dispatch-history.ts +168 -0
  370. package/src/resources/extensions/gsd/auto/dispatch-key.ts +39 -0
  371. package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
  372. package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
  373. package/src/resources/extensions/gsd/auto/loop.ts +7 -1
  374. package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
  375. package/src/resources/extensions/gsd/auto/orchestrator.ts +186 -66
  376. package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
  377. package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
  378. package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
  379. package/src/resources/extensions/gsd/auto/session.ts +3 -0
  380. package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
  381. package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
  382. package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
  383. package/src/resources/extensions/gsd/auto-direct-dispatch.ts +18 -48
  384. package/src/resources/extensions/gsd/auto-dispatch.ts +37 -62
  385. package/src/resources/extensions/gsd/auto-model-selection.ts +16 -7
  386. package/src/resources/extensions/gsd/auto-post-unit.ts +33 -12
  387. package/src/resources/extensions/gsd/auto-prompts.ts +78 -9
  388. package/src/resources/extensions/gsd/auto-start.ts +27 -11
  389. package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
  390. package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +4 -4
  391. package/src/resources/extensions/gsd/auto-verification.ts +26 -28
  392. package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
  393. package/src/resources/extensions/gsd/auto.ts +64 -2
  394. package/src/resources/extensions/gsd/blocked-models.ts +49 -0
  395. package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +34 -5
  396. package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
  397. package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +2 -2
  398. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +118 -50
  399. package/src/resources/extensions/gsd/bootstrap/write-gate.ts +350 -86
  400. package/src/resources/extensions/gsd/closeout-wizard.ts +102 -0
  401. package/src/resources/extensions/gsd/commands/context.ts +16 -2
  402. package/src/resources/extensions/gsd/commands-handlers.ts +46 -3
  403. package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
  404. package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
  405. package/src/resources/extensions/gsd/consent-question.ts +431 -0
  406. package/src/resources/extensions/gsd/consent-verdict.ts +86 -0
  407. package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
  408. package/src/resources/extensions/gsd/db/engine.ts +26 -6
  409. package/src/resources/extensions/gsd/db/queries.ts +66 -0
  410. package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
  411. package/src/resources/extensions/gsd/db-transaction.ts +37 -20
  412. package/src/resources/extensions/gsd/db-writer.ts +11 -19
  413. package/src/resources/extensions/gsd/dispatch-guard.ts +8 -31
  414. package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
  415. package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
  416. package/src/resources/extensions/gsd/doctor-git-checks.ts +2 -19
  417. package/src/resources/extensions/gsd/engine-hook-contract.ts +79 -0
  418. package/src/resources/extensions/gsd/files.ts +33 -12
  419. package/src/resources/extensions/gsd/gsd-command-home.ts +13 -3
  420. package/src/resources/extensions/gsd/gsd-db.ts +19 -22
  421. package/src/resources/extensions/gsd/guidance.ts +78 -0
  422. package/src/resources/extensions/gsd/guided-flow.ts +145 -24
  423. package/src/resources/extensions/gsd/health-widget.ts +91 -27
  424. package/src/resources/extensions/gsd/markdown-renderer.ts +11 -0
  425. package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
  426. package/src/resources/extensions/gsd/memory-relations.ts +1 -1
  427. package/src/resources/extensions/gsd/milestone-closeout.ts +109 -24
  428. package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
  429. package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
  430. package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
  431. package/src/resources/extensions/gsd/notifications.ts +13 -6
  432. package/src/resources/extensions/gsd/parsers-legacy.ts +16 -4
  433. package/src/resources/extensions/gsd/projection-flush.ts +20 -0
  434. package/src/resources/extensions/gsd/prompts/complete-slice.md +3 -3
  435. package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
  436. package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
  437. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
  438. package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
  439. package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
  440. package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
  441. package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
  442. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  443. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  444. package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
  445. package/src/resources/extensions/gsd/prompts/run-uat.md +8 -4
  446. package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
  447. package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
  448. package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
  449. package/src/resources/extensions/gsd/reactive-graph.ts +11 -1
  450. package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
  451. package/src/resources/extensions/gsd/session-lock.ts +1 -1
  452. package/src/resources/extensions/gsd/skill-activation.ts +3 -6
  453. package/src/resources/extensions/gsd/state.ts +12 -1
  454. package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
  455. package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
  456. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
  457. package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +75 -1
  458. package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +257 -18
  459. package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
  460. package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
  461. package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
  462. package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
  463. package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
  464. package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
  465. package/src/resources/extensions/gsd/tests/blocked-models.test.ts +19 -0
  466. package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +42 -0
  467. package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
  468. package/src/resources/extensions/gsd/tests/consent-question.test.ts +351 -0
  469. package/src/resources/extensions/gsd/tests/custom-verify-retry-store.test.ts +67 -0
  470. package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
  471. package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
  472. package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
  473. package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +12 -11
  474. package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
  475. package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
  476. package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +328 -0
  477. package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
  478. package/src/resources/extensions/gsd/tests/doctor-git-checks-terminal.test.ts +73 -0
  479. package/src/resources/extensions/gsd/tests/engine-hook-contract.test.ts +148 -0
  480. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
  481. package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
  482. package/src/resources/extensions/gsd/tests/gsd-command-home.test.ts +120 -0
  483. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +46 -0
  484. package/src/resources/extensions/gsd/tests/guidance.test.ts +23 -0
  485. package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
  486. package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
  487. package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
  488. package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +217 -0
  489. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
  490. package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
  491. package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
  492. package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +95 -4
  493. package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
  494. package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
  495. package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
  496. package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
  497. package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
  498. package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +18 -0
  499. package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
  500. package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +143 -0
  501. package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
  502. package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
  503. package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
  504. package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
  505. package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
  506. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +124 -6
  507. package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
  508. package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
  509. package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
  510. package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
  511. package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
  512. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
  513. package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
  514. package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
  515. package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
  516. package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
  517. package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
  518. package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
  519. package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
  520. package/src/resources/extensions/gsd/tests/uat-policy.test.ts +88 -0
  521. package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
  522. package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
  523. package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
  524. package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
  525. package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
  526. package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
  527. package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
  528. package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
  529. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
  530. package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +273 -38
  531. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
  532. package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
  533. package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
  534. package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
  535. package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
  536. package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
  537. package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +358 -0
  538. package/src/resources/extensions/gsd/tests/write-gate.test.ts +67 -1
  539. package/src/resources/extensions/gsd/tool-contract.ts +38 -3
  540. package/src/resources/extensions/gsd/tool-presentation-plan.ts +4 -4
  541. package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
  542. package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
  543. package/src/resources/extensions/gsd/tools/complete-slice.ts +22 -12
  544. package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
  545. package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
  546. package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
  547. package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
  548. package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
  549. package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
  550. package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
  551. package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
  552. package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +81 -2
  553. package/src/resources/extensions/gsd/uat-policy.ts +60 -15
  554. package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
  555. package/src/resources/extensions/gsd/unit-registry.ts +34 -4
  556. package/src/resources/extensions/gsd/verdict-parser.ts +1 -1
  557. package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
  558. package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
  559. package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
  560. package/src/resources/extensions/gsd/workflow-events.ts +12 -20
  561. package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
  562. package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
  563. package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
  564. package/src/resources/extensions/gsd/worktree-lifecycle.ts +3 -8
  565. package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
  566. package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
  567. package/src/resources/extensions/gsd/worktree.ts +7 -1
  568. package/src/resources/extensions/mcp-client/manager.ts +7 -1
  569. package/src/resources/extensions/shared/gsd-browser-cli.ts +23 -2
  570. package/src/resources/shared/gsd-browser-path-sync.ts +273 -0
  571. package/src/resources/shared/package-manager-detection.ts +1 -1
  572. package/src/resources/skills/create-skill/SKILL.md +3 -0
  573. package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
  574. package/dist/resources/extensions/gsd/user-input-boundary.js +0 -218
  575. package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
  576. package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +0 -173
  577. package/src/resources/extensions/gsd/user-input-boundary.ts +0 -216
  578. package/src/resources/skills/gsd-browser/SKILL.md +0 -41
  579. /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
  580. /package/dist/web/standalone/.next/static/{mU4QIDlpVHDdjDpeEKh5W → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
@@ -0,0 +1,431 @@
1
+ /**
2
+ * Consent Question module — the single home for the user-question lifecycle:
3
+ * classification → gating → answer validation → cancellation.
4
+ *
5
+ * Every question the assistant puts to a human is classified into a kind, and
6
+ * the kind alone decides the fail policy:
7
+ *
8
+ * - "gate" — mechanical write gates (depth verification, destructive
9
+ * confirm). Fail-closed; structural answer validation is
10
+ * delegated to the write-gate validators.
11
+ * - "consent" — approval/confirmation questions ("ready to write?",
12
+ * "is this correct?"). Fail-closed.
13
+ * - "decision" — explicit user decisions (research vs skip). Fail-closed.
14
+ * - "informational" — anything that is not asking the user to consent or
15
+ * decide. Fail-open.
16
+ *
17
+ * Fail-closed means an empty/missing answer is NEVER treated as an answer —
18
+ * evaluateAnswer returns "waiting" so callers pause instead of proceeding.
19
+ * This fixes #528 (empty `selected` on a non-gate question used to pass
20
+ * through as a real answer) by construction.
21
+ *
22
+ * shouldPauseForQuestion replaces the old unit-type allowlist: a classified
23
+ * consent/decision question pauses regardless of unit type, including
24
+ * interactive mode where no unit is active. This fixes #682 (prose approval
25
+ * questions outside the 4 allowlisted discuss units rendered as un-gated
26
+ * prose menus) by construction.
27
+ */
28
+
29
+ import { isGateQuestionId } from "./bootstrap/write-gate.js";
30
+ import {
31
+ evaluateGateAnswer,
32
+ hasNotesValue,
33
+ hasSelectedValue,
34
+ type VerdictAnswerDetails,
35
+ type VerdictQuestionShape,
36
+ } from "./consent-verdict.js";
37
+ import { isDestructiveConfirmGateId } from "./safety/destructive-confirmation.js";
38
+
39
+ // ── Taxonomy ────────────────────────────────────────────────────────────────
40
+
41
+ export type QuestionKind = "gate" | "consent" | "decision" | "informational";
42
+
43
+ export type GateSubKind = "depth-verification" | "approval" | "destructive-confirm";
44
+
45
+ export type FailPolicy = "closed" | "open";
46
+
47
+ export type AnswerOutcome = "waiting" | "answered" | "verified" | "declined" | "cancelled";
48
+
49
+ export interface ClassifiedQuestion {
50
+ kind: QuestionKind;
51
+ gateSubKind?: GateSubKind;
52
+ }
53
+
54
+ /** Fail policy is derived from the kind — there is no per-question override. */
55
+ export function failPolicyForKind(kind: QuestionKind): FailPolicy {
56
+ return kind === "informational" ? "open" : "closed";
57
+ }
58
+
59
+ // ── Prose detectors (moved from user-input-boundary) ────────────────────────
60
+
61
+ const REMOTE_QUESTION_FAILURE_RE =
62
+ /(?:Remote (?:auth failed|questions failed|channel configured but returned no result|questions timed out|questions timed out or failed)|Failed to send questions via)/i;
63
+
64
+ const APPROVAL_WAIT_RE =
65
+ /\bwait(?:ing)?\s+for\s+(?:your\s+)?(?:confirmation|approval|input|response|answer)\b/i;
66
+
67
+ const APPROVAL_QUESTION_RE =
68
+ /\b(?:confirm|confirmation|approve|approval|approved|captured|correct|correctly|happy\s+with|ready\s+to\s+(?:write|save|proceed|ship)|(?:want|need)\s+to\s+adjust|should\s+I\s+(?:write|save|proceed)|do\s+you\s+want\s+me\s+to\s+(?:write|save|proceed)|ship\s+it)\b/i;
69
+
70
+ const APPROVAL_RIGHT_QUESTION_RE =
71
+ /\b(?:does|do|is|are|was|were|did)\b[^\n?]{0,120}\bright\b/i;
72
+
73
+ const APPROVAL_CHANGE_QUESTION_RE =
74
+ /\b(?:anything\s+else|anything|something)\s+to\s+(?:adjust|add|remove|reclassify)\b/i;
75
+
76
+ const RESEARCH_DECISION_QUESTION_RE =
77
+ /\b(?:research|skip)\b/i;
78
+
79
+ const ASK_USER_QUESTIONS_CANCELLED_RE =
80
+ /ask_user_questions was cancelled before receiving a response/i;
81
+
82
+ /** Scan question-mark-terminated fragments of `text` against `patterns`. */
83
+ function hasQuestionMatching(text: string, patterns: RegExp[]): boolean {
84
+ for (let i = 0; i < text.length; i++) {
85
+ if (text[i] !== "?") continue;
86
+ const previousBreak = Math.max(
87
+ text.lastIndexOf("\n", i),
88
+ text.lastIndexOf(".", i),
89
+ text.lastIndexOf("!", i),
90
+ text.lastIndexOf("?", i - 1),
91
+ );
92
+ const fragment = text.slice(previousBreak + 1, i + 1);
93
+ if (patterns.some((pattern) => pattern.test(fragment))) return true;
94
+ }
95
+ return false;
96
+ }
97
+
98
+ export function hasApprovalQuestion(text: string): boolean {
99
+ return hasQuestionMatching(text, [
100
+ APPROVAL_QUESTION_RE,
101
+ APPROVAL_RIGHT_QUESTION_RE,
102
+ APPROVAL_CHANGE_QUESTION_RE,
103
+ ]);
104
+ }
105
+
106
+ export function hasResearchDecisionQuestion(text: string): boolean {
107
+ return hasQuestionMatching(text, [RESEARCH_DECISION_QUESTION_RE]);
108
+ }
109
+
110
+ /**
111
+ * Detect a plain-text "Next steps:" menu — numbered options with an "Other"
112
+ * choice — emitted as prose instead of a structured ask_user_questions call.
113
+ * Without this, auto-mode treats the menu as informational and loops on its
114
+ * own turn until tokens are exhausted (#454).
115
+ */
116
+ export function hasPlainTextNextStepsMenu(lines: string[]): boolean {
117
+ const nextStepsIndex = lines.findIndex((line) => /^next steps\s*:?$/i.test(line));
118
+ if (nextStepsIndex < 0) return false;
119
+ const menuLines = lines.slice(nextStepsIndex + 1);
120
+ const numberedOptions = menuLines.filter((line) => /^\d+[.)]\s+\S/.test(line));
121
+ return numberedOptions.length >= 2 && numberedOptions.some((line) => /\bother\b/i.test(line));
122
+ }
123
+
124
+ // ── Message text extraction (moved from user-input-boundary) ────────────────
125
+
126
+ function extractMessageText(msg: unknown, includeThinking: boolean): string {
127
+ if (!msg || typeof msg !== "object") return "";
128
+ const content = (msg as { content?: unknown }).content;
129
+ if (typeof content === "string") return content;
130
+ if (!Array.isArray(content)) return "";
131
+ const parts: string[] = [];
132
+ for (const block of content) {
133
+ if (!block || typeof block !== "object") continue;
134
+ const typed = block as { type?: unknown; text?: unknown; thinking?: unknown };
135
+ if (typed.type === "text" && typeof typed.text === "string") {
136
+ parts.push(typed.text);
137
+ }
138
+ // Thinking blocks are internal reasoning, not user-visible — included only
139
+ // when the caller asks for the full transcript text.
140
+ if (includeThinking && typed.type === "thinking" && typeof typed.thinking === "string") {
141
+ parts.push(typed.thinking);
142
+ }
143
+ }
144
+ return parts.join("\n");
145
+ }
146
+
147
+ function lastAssistantMessageText(
148
+ messages: unknown[] | null | undefined,
149
+ includeThinking: boolean,
150
+ ): string {
151
+ if (!Array.isArray(messages)) return "";
152
+ for (let i = messages.length - 1; i >= 0; i--) {
153
+ const msg = messages[i];
154
+ if (!msg || typeof msg !== "object") continue;
155
+ if ((msg as { role?: unknown }).role !== "assistant") continue;
156
+ const text = extractMessageText(msg, includeThinking).trim();
157
+ if (text) return text;
158
+ }
159
+ return "";
160
+ }
161
+
162
+ export function lastAssistantText(messages: unknown[] | null | undefined): string {
163
+ return lastAssistantMessageText(messages, true);
164
+ }
165
+
166
+ function lastAssistantVisibleText(messages: unknown[] | null | undefined): string {
167
+ return lastAssistantMessageText(messages, false);
168
+ }
169
+
170
+ function anyMessageMatches(messages: unknown[] | undefined, patterns: RegExp[]): boolean {
171
+ if (!Array.isArray(messages)) return false;
172
+ return messages.some((msg) => {
173
+ if (!msg || typeof msg !== "object") return false;
174
+ if ((msg as { role?: unknown }).role === "user") return false;
175
+ const text = extractMessageText(msg, false);
176
+ return patterns.some((pattern) => pattern.test(text));
177
+ });
178
+ }
179
+
180
+ // ── Classification ──────────────────────────────────────────────────────────
181
+
182
+ const APPROVAL_GATE_ID_RE = /^depth_verification_.+_confirm$/;
183
+
184
+ export interface ClassifyQuestionInput {
185
+ /** ask_user_questions question id, when classifying a structured question. */
186
+ id?: unknown;
187
+ /** Question options, when classifying a structured question. */
188
+ options?: Array<{ label?: string }> | undefined;
189
+ /** Prose text, when classifying a streamed text boundary. */
190
+ text?: string;
191
+ /** Active unit type, used to pick the prose detector for decisions. */
192
+ unitType?: string;
193
+ }
194
+
195
+ /**
196
+ * Classify a question — structured (by id) or prose (by text) — into a kind.
197
+ *
198
+ * Structured questions with a recognized gate id are gates; every other
199
+ * structured question is asking the user something, so it classifies as
200
+ * consent (fail-closed). Prose classifies by the approval/decision detectors;
201
+ * prose that matches neither is informational (fail-open).
202
+ */
203
+ export function classifyQuestion(input: ClassifyQuestionInput): ClassifiedQuestion {
204
+ if (isDestructiveConfirmGateId(input.id)) {
205
+ return { kind: "gate", gateSubKind: "destructive-confirm" };
206
+ }
207
+ if (typeof input.id === "string" && isGateQuestionId(input.id)) {
208
+ return {
209
+ kind: "gate",
210
+ gateSubKind: APPROVAL_GATE_ID_RE.test(input.id) ? "approval" : "depth-verification",
211
+ };
212
+ }
213
+ // Any other structured question is a real elicitation of the user.
214
+ if (typeof input.id === "string" || Array.isArray(input.options)) {
215
+ return { kind: "consent" };
216
+ }
217
+ const text = input.text ?? "";
218
+ if (input.unitType === "research-decision" && hasResearchDecisionQuestion(text)) {
219
+ return { kind: "decision" };
220
+ }
221
+ if (hasApprovalQuestion(text)) {
222
+ return { kind: "consent" };
223
+ }
224
+ return { kind: "informational" };
225
+ }
226
+
227
+ // ── Answer validation ───────────────────────────────────────────────────────
228
+
229
+ // The question/answer shapes are the consent-verdict leaf's shapes — one
230
+ // definition shared with write-gate so the two consumers cannot drift.
231
+ export type ConsentQuestionShape = VerdictQuestionShape;
232
+ export type ConsentAnswerDetails = VerdictAnswerDetails;
233
+
234
+ /**
235
+ * THE single policy point for whether a question's answer counts as answered.
236
+ *
237
+ * - cancelled rounds → "cancelled" for every kind.
238
+ * - gate: delegates to evaluateGateAnswer in the consent-verdict leaf — the
239
+ * same verdict engine write-gate's applyAskUserQuestionsGateResult consumes;
240
+ * confirm option → "verified", any other real selection → "declined",
241
+ * empty/missing → "waiting" (fail-closed).
242
+ * - consent/decision: a non-empty selection or non-empty notes → "answered";
243
+ * empty/missing → "waiting" (fail-closed; fixes #528).
244
+ * - informational: always "answered" (fail-open).
245
+ */
246
+ export function evaluateAnswer(options: {
247
+ question: ConsentQuestionShape;
248
+ details: ConsentAnswerDetails;
249
+ }): AnswerOutcome {
250
+ const { question, details } = options;
251
+ if (details.cancelled) return "cancelled";
252
+
253
+ const { kind } = classifyQuestion({ id: question.id, options: question.options });
254
+ if (failPolicyForKind(kind) === "open") return "answered";
255
+
256
+ if (kind === "gate") {
257
+ // Gates keep strict structural validation: only the confirmation option
258
+ // verifies; notes never satisfy a gate.
259
+ return evaluateGateAnswer(question, details);
260
+ }
261
+
262
+ const questionId = typeof question.id === "string" ? question.id : "";
263
+ const answer = details.response?.answers?.[questionId];
264
+
265
+ if (hasSelectedValue(answer?.selected)) return "answered";
266
+ // Notes-only is a real user utterance for consent/decision questions, but
267
+ // never for gates (handled above).
268
+ if (hasNotesValue(answer?.notes)) return "answered";
269
+ return "waiting";
270
+ }
271
+
272
+ const OUTCOME_PRECEDENCE: AnswerOutcome[] = [
273
+ "cancelled",
274
+ "waiting",
275
+ "declined",
276
+ "verified",
277
+ "answered",
278
+ ];
279
+
280
+ /**
281
+ * Evaluate a whole ask_user_questions round. The round outcome is the most
282
+ * blocking per-question outcome (cancelled > waiting > declined > verified >
283
+ * answered). An empty round with a response is "answered"; an empty round
284
+ * without a response is "waiting" only when cancelled is not set and there is
285
+ * nothing to validate — callers treat a missing response with no questions as
286
+ * a no-op, so it reports "answered" here.
287
+ */
288
+ export function evaluateAskUserQuestionsRound(
289
+ questions: ConsentQuestionShape[],
290
+ details: ConsentAnswerDetails,
291
+ ): AnswerOutcome {
292
+ if (details.cancelled) return "cancelled";
293
+ let worst: AnswerOutcome = "answered";
294
+ for (const question of questions) {
295
+ const outcome = evaluateAnswer({ question, details });
296
+ if (OUTCOME_PRECEDENCE.indexOf(outcome) < OUTCOME_PRECEDENCE.indexOf(worst)) {
297
+ worst = outcome;
298
+ }
299
+ }
300
+ return worst;
301
+ }
302
+
303
+ export function formatUnansweredConsentQuestionMessage(questions: ConsentQuestionShape[]): string {
304
+ const ids = questions
305
+ .map((question) => (typeof question.id === "string" ? question.id : null))
306
+ .filter((id): id is string => Boolean(id));
307
+ return [
308
+ `ask_user_questions returned without a selection${ids.length ? ` for ${ids.join(", ")}` : ""}.`,
309
+ "An empty answer is not consent — do not infer approval or proceed.",
310
+ "Re-call ask_user_questions with the same question(s) and wait for the user's response.",
311
+ ].join(" ");
312
+ }
313
+
314
+ // ── Pause gating (replaces the unit-type allowlist) ─────────────────────────
315
+
316
+ /**
317
+ * Shared preamble for the awaiting-input predicates: cancellation and remote
318
+ * delivery failures always pause (an undelivered question can never be
319
+ * answered, so proceeding would be fail-open), as does an explicit
320
+ * "waiting for your approval/input" phrase in the last assistant text.
321
+ *
322
+ * Returns `forced: true` when the boundary is unconditional, plus the last
323
+ * assistant visible text for the caller's own classification.
324
+ */
325
+ function awaitingBoundary(messages: unknown[] | undefined): { forced: boolean; text: string } {
326
+ if (anyMessageMatches(messages, [ASK_USER_QUESTIONS_CANCELLED_RE, REMOTE_QUESTION_FAILURE_RE])) {
327
+ return { forced: true, text: "" };
328
+ }
329
+ const text = lastAssistantVisibleText(messages);
330
+ if (text && APPROVAL_WAIT_RE.test(text)) return { forced: true, text };
331
+ return { forced: false, text };
332
+ }
333
+
334
+ /**
335
+ * Decide whether the assistant should pause for a prose user question.
336
+ *
337
+ * Unlike the retired USER_APPROVAL_UNIT_TYPES allowlist, this pauses for any
338
+ * classified consent/decision question regardless of unit type — including
339
+ * interactive mode where no unit is active (#682).
340
+ */
341
+ export function shouldPauseForQuestion(
342
+ unitType: string | undefined,
343
+ messages: unknown[] | undefined,
344
+ ): boolean {
345
+ const { forced, text } = awaitingBoundary(messages);
346
+ if (forced) return true;
347
+ // Streaming hot path: this runs on every message_update for every unit type.
348
+ // The classifiers only ever match question-mark-terminated fragments, so
349
+ // text without a "?" can never classify as consent/decision — bail before
350
+ // the multi-regex scan.
351
+ if (!text || !text.includes("?")) return false;
352
+ const { kind } = classifyQuestion({ text, unitType });
353
+ return kind === "consent" || kind === "decision";
354
+ }
355
+
356
+ // ── Awaiting-input boundaries (moved from user-input-boundary) ──────────────
357
+
358
+ export function isAwaitingUserInput(messages: unknown[] | undefined): boolean {
359
+ const { forced, text } = awaitingBoundary(messages);
360
+ if (forced) return true;
361
+ if (!text) return false;
362
+ const lines = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
363
+ if (lines.some((line) => line.endsWith("?"))) return true;
364
+ if (hasPlainTextNextStepsMenu(lines)) return true;
365
+ return hasApprovalQuestion(text);
366
+ }
367
+
368
+ export function isAwaitingApprovalBoundary(messages: unknown[] | undefined): boolean {
369
+ // With no unit type, classification reduces to the approval detectors —
370
+ // exactly the approval boundary.
371
+ return shouldPauseForQuestion(undefined, messages);
372
+ }
373
+
374
+ // ── Approval gate ids + explicit responses (moved from user-input-boundary) ─
375
+
376
+ export function approvalGateIdForUnit(
377
+ unitType: string | undefined,
378
+ unitId?: string | null,
379
+ ): string | null {
380
+ if (!unitType) return null;
381
+ if (unitType === "discuss-project") return "depth_verification_project_confirm";
382
+ if (unitType === "discuss-requirements") return "depth_verification_requirements_confirm";
383
+ if (unitType === "research-decision") return "depth_verification_research_decision_confirm";
384
+ if (unitType === "discuss-milestone") {
385
+ const safeUnitId = typeof unitId === "string" && /^[A-Za-z0-9_-]+$/.test(unitId)
386
+ ? unitId
387
+ : "milestone";
388
+ return `depth_verification_${safeUnitId}_confirm`;
389
+ }
390
+ return null;
391
+ }
392
+
393
+ const CHANGE_REQUEST_RESPONSE_RE =
394
+ /\b(?:no|nope|nah|not\s+yet|don't|do\s+not|change|add|remove|reclassify|adjust|clarify|missing|instead|but|however|wait|hold)\b/i;
395
+
396
+ const APPROVAL_RESPONSE_RE =
397
+ /^(?:y|yes|yeah|yep|approve|approved|confirm|confirmed|correct|right|looks\s+(?:good|right)|sounds\s+good|all\s+good|ok|okay|go\s+ahead|proceed|write\s+it|save\s+it|do\s+it)\b/i;
398
+
399
+ const RESEARCH_DECISION_RESPONSE_RE =
400
+ /^(?:research|run\s+research|do\s+research|skip|skip\s+research|no\s+research)\b/i;
401
+
402
+ export function isExplicitApprovalResponse(
403
+ input: string | undefined,
404
+ pendingGateId?: string | null,
405
+ ): boolean {
406
+ const text = input?.trim() ?? "";
407
+ if (!text) return false;
408
+ if (pendingGateId?.includes("research_decision")) {
409
+ return RESEARCH_DECISION_RESPONSE_RE.test(text);
410
+ }
411
+ if (CHANGE_REQUEST_RESPONSE_RE.test(text)) return false;
412
+ return APPROVAL_RESPONSE_RE.test(text);
413
+ }
414
+
415
+ /** True when an assistant message already has an in-flight ask_user_questions tool call. */
416
+ export function messageHasPendingAskUserQuestionsTool(message: unknown): boolean {
417
+ if (!message || typeof message !== "object") return false;
418
+ const content = (message as { content?: unknown }).content;
419
+ if (!Array.isArray(content)) return false;
420
+ return content.some((block) => {
421
+ if (!block || typeof block !== "object") return false;
422
+ // Claude Code marks completion by attaching externalResult, not by setting state.
423
+ // Streaming blocks often carry no state; serverToolUse is the claude-code-cli MCP path.
424
+ const tool = block as { type?: string; name?: string; state?: string; externalResult?: unknown };
425
+ if (tool.type !== "toolCall" && tool.type !== "serverToolUse") return false;
426
+ const name = String(tool.name ?? "").toLowerCase();
427
+ if (!name.includes("ask_user_questions")) return false;
428
+ if (tool.externalResult !== undefined) return false;
429
+ return tool.state !== "completed" && tool.state !== "done";
430
+ });
431
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Consent verdict leaf — the single per-question verdict engine shared by the
3
+ * write gate (bootstrap/write-gate.ts) and the Consent Question module
4
+ * (consent-question.ts).
5
+ *
6
+ * This module is a dependency leaf on purpose: write-gate consumes
7
+ * evaluateGateAnswer here while consent-question imports write-gate's id
8
+ * predicates, so putting the verdict anywhere else would create an import
9
+ * cycle. It must not import from either module (ADR-039).
10
+ */
11
+
12
+ export type GateAnswerVerdict = "waiting" | "verified" | "declined" | "cancelled";
13
+
14
+ export interface VerdictQuestionShape {
15
+ id?: unknown;
16
+ options?: Array<{ label?: string }>;
17
+ }
18
+
19
+ export interface VerdictAnswerDetails {
20
+ cancelled?: boolean;
21
+ interrupted?: boolean;
22
+ response?: {
23
+ answers?: Record<string, { selected?: unknown; notes?: unknown } | undefined>;
24
+ } | null;
25
+ }
26
+
27
+ /**
28
+ * Check whether a depth_verification answer confirms the discussion is complete.
29
+ * Uses structural validation: the selected answer must exactly match the first
30
+ * option label from the question definition (the confirmation option by convention).
31
+ * This rejects free-form "Other" text, decline options, and garbage input without
32
+ * coupling to any specific label substring.
33
+ *
34
+ * @param selected The answer's selected value from details.response.answers[id].selected
35
+ * @param options The question's options array from event.input.questions[n].options
36
+ */
37
+ export function isDepthConfirmationAnswer(
38
+ selected: unknown,
39
+ options?: Array<{ label?: string }>,
40
+ ): boolean {
41
+ const value = Array.isArray(selected) ? selected[0] : selected;
42
+ if (typeof value !== "string" || !value) return false;
43
+
44
+ // If options are available, structurally validate: selected must exactly match
45
+ // the first option (confirmation) label. Rejects free-form "Other" and decline options.
46
+ if (Array.isArray(options) && options.length > 0) {
47
+ const confirmLabel = options[0]?.label;
48
+ return typeof confirmLabel === "string" && value === confirmLabel;
49
+ }
50
+
51
+ // Fail-closed: no options means we cannot structurally validate the answer.
52
+ // Returning false prevents any free-form string from unlocking the gate.
53
+ return false;
54
+ }
55
+
56
+ export function hasSelectedValue(selected: unknown): boolean {
57
+ if (Array.isArray(selected)) {
58
+ return selected.some((value) => typeof value === "string" && value.length > 0);
59
+ }
60
+ return typeof selected === "string" && selected.length > 0;
61
+ }
62
+
63
+ export function hasNotesValue(notes: unknown): boolean {
64
+ return typeof notes === "string" && notes.trim().length > 0;
65
+ }
66
+
67
+ /**
68
+ * THE per-question verdict for gate questions (fail-closed):
69
+ *
70
+ * - cancelled rounds → "cancelled".
71
+ * - the confirmation option (structural match) → "verified".
72
+ * - any other real selection → "declined".
73
+ * - empty/missing selection → "waiting" — an empty answer is NEVER an answer,
74
+ * so notes can never satisfy a gate either.
75
+ */
76
+ export function evaluateGateAnswer(
77
+ question: VerdictQuestionShape,
78
+ details: VerdictAnswerDetails,
79
+ ): GateAnswerVerdict {
80
+ if (details.cancelled) return "cancelled";
81
+ const questionId = typeof question.id === "string" ? question.id : "";
82
+ const answer = details.response?.answers?.[questionId];
83
+ if (isDepthConfirmationAnswer(answer?.selected, question.options)) return "verified";
84
+ if (hasSelectedValue(answer?.selected)) return "declined";
85
+ return "waiting";
86
+ }
@@ -223,6 +223,7 @@ export function writeLock(
223
223
  * stale session-file pointer.
224
224
  */
225
225
  export function clearLock(basePath: string): void {
226
+ const legacyLock = readLegacyLock(basePath);
226
227
  clearLegacyLockFile(basePath);
227
228
 
228
229
  if (!isDbAvailable()) return;
@@ -235,8 +236,15 @@ export function clearLock(basePath: string): void {
235
236
  deleteRuntimeKv("worker", staleWorker.worker_id, SESSION_FILE_KV_KEY);
236
237
  return;
237
238
  }
238
- const lock = readLegacyLock(basePath);
239
- if (lock?.pid) markWorkerStoppingByPid(projectRoot, lock.pid);
239
+ if (legacyLock?.pid) {
240
+ markWorkerStoppingByPid(projectRoot, legacyLock.pid);
241
+ const workerByLegacyPid = getAllAutoWorkers().find(
242
+ (w) =>
243
+ w.pid === legacyLock.pid
244
+ && normalizeRealPath(w.project_root_realpath) === projectRoot,
245
+ );
246
+ if (workerByLegacyPid) forceReleaseLeasesForWorker(workerByLegacyPid.worker_id);
247
+ }
240
248
  const worker = findActiveWorkerForCurrentProcess(projectRoot);
241
249
  if (worker) deleteRuntimeKv("worker", worker.worker_id, SESSION_FILE_KV_KEY);
242
250
 
@@ -1,11 +1,13 @@
1
1
  // Project/App: gsd-pi
2
2
  // File Purpose: GSD engine — connection ownership, lifecycle, schema/migrations,
3
3
  // and transaction primitives for the single-writer layer. The shared handle
4
- // (currentDb) lives here; writers (db/writers/*) and the Query Module
5
- // (db/queries.ts) read it through getDb()/getDbOrNull().
4
+ // (currentDb) lives here; domain writers, allowlisted coordination/runtime
5
+ // writers, schema/migration helpers, and the Query Module (db/queries.ts) read
6
+ // it through getDb()/getDbOrNull().
6
7
  //
7
8
  // This file legitimately holds DDL and BEGIN/COMMIT control, so it is
8
- // allowlisted in tests/single-writer-invariant.test.ts alongside db/writers/.
9
+ // allowlisted in tests/single-writer-invariant.test.ts alongside the explicit
10
+ // writer layer.
9
11
  import { createRequire } from "node:module";
10
12
  import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
11
13
  import { dirname, join } from "node:path";
@@ -16,7 +18,7 @@ import { createDbAdapter, type DbAdapter } from "../db-adapter.js";
16
18
  import { createBaseSchemaObjects } from "../db-base-schema.js";
17
19
  import { createCoordinationTablesV24 } from "../db-coordination-schema.js";
18
20
  import { createDbConnectionCache, type DbConnectionCacheEntry } from "../db-connection-cache.js";
19
- import { backupDatabaseBeforeMigration } from "../db-migration-backup.js";
21
+ import { backupDatabaseBeforeMigration, isMigrationBackupError } from "../db-migration-backup.js";
20
22
  import {
21
23
  applyMigrationV2Artifacts,
22
24
  applyMigrationV3Memories,
@@ -601,8 +603,9 @@ export function openDatabase(path: string): boolean {
601
603
  initSchema(adapter, fileBacked, path);
602
604
  } catch (err) {
603
605
  // Corrupt freelist: DDL fails with "malformed" but VACUUM can rebuild.
604
- // Attempt VACUUM recovery before giving up (see #2519).
605
- if (fileBacked && err instanceof Error && err.message?.includes("malformed")) {
606
+ // Pre-migration backup failures are already pre-DDL and must propagate
607
+ // instead of being masked by VACUUM recovery (see #2519).
608
+ if (shouldAttemptVacuumRecovery(fileBacked, err)) {
606
609
  try {
607
610
  adapter.exec("VACUUM");
608
611
  initSchema(adapter, fileBacked, path);
@@ -634,6 +637,12 @@ export function openDatabase(path: string): boolean {
634
637
  return true;
635
638
  }
636
639
 
640
+ function shouldAttemptVacuumRecovery(fileBacked: boolean, err: unknown): boolean {
641
+ return fileBacked && err instanceof Error && err.message.includes("malformed") && !isMigrationBackupError(err);
642
+ }
643
+
644
+ export const _shouldAttemptVacuumRecoveryForTest = shouldAttemptVacuumRecovery;
645
+
637
646
  export function closeDatabase(): void {
638
647
  if (currentDb) {
639
648
  try {
@@ -735,6 +744,7 @@ function createTransactionControls(db: DbAdapter) {
735
744
  return {
736
745
  begin: () => db.exec("BEGIN"),
737
746
  beginRead: () => db.exec("BEGIN DEFERRED"),
747
+ beginImmediate: () => db.exec("BEGIN IMMEDIATE"),
738
748
  commit: () => db.exec("COMMIT"),
739
749
  rollback: () => db.exec("ROLLBACK"),
740
750
  };
@@ -755,6 +765,16 @@ export function transaction<T>(fn: () => T): T {
755
765
  return _transactionRunner.transaction(createTransactionControls(currentDb), fn);
756
766
  }
757
767
 
768
+ /**
769
+ * Run a BEGIN IMMEDIATE write transaction for operations that need SQLite's
770
+ * reserved writer lock before issuing updates. Re-entrant like transaction():
771
+ * nested calls run inside the outer transaction without a nested BEGIN.
772
+ */
773
+ export function immediateTransaction<T>(fn: () => T): T {
774
+ if (!currentDb) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
775
+ return _transactionRunner.immediateTransaction(createTransactionControls(currentDb), fn);
776
+ }
777
+
758
778
  /**
759
779
  * Wrap a block of reads in a DEFERRED transaction so that all SELECTs observe
760
780
  * a consistent snapshot of the DB even if a concurrent writer commits between